Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: Epic fixes #4312

Merged
merged 12 commits into from Mar 25, 2018
16 changes: 6 additions & 10 deletions rpcs3/Emu/Cell/Modules/cellAvconfExt.cpp
@@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/RSX/rsx_utils.h"

#include "cellAudioIn.h"
#include "cellAudioOut.h"
Expand All @@ -9,8 +11,6 @@

logs::channel cellAvconfExt("cellAvconfExt");

vm::gvar<f32> g_gamma; // TODO

s32 cellAudioOutUnregisterDevice(u32 deviceNumber)
{
cellAvconfExt.todo("cellAudioOutUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
Expand Down Expand Up @@ -56,7 +56,8 @@ s32 cellVideoOutGetGamma(u32 videoOut, vm::ptr<f32> gamma)
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}

*gamma = *g_gamma;
auto conf = fxm::get_always<rsx::avconf>();
*gamma = conf->gamma;

return CELL_OK;
}
Expand Down Expand Up @@ -87,7 +88,8 @@ s32 cellVideoOutSetGamma(u32 videoOut, f32 gamma)
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
}

*g_gamma = gamma;
auto conf = fxm::get_always<rsx::avconf>();
conf->gamma = gamma;

return CELL_OK;
}
Expand Down Expand Up @@ -152,12 +154,6 @@ s32 cellVideoOutSetCopyControl(u32 videoOut, u32 control)

DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
{
REG_VAR(cellSysutilAvconfExt, g_gamma).flag(MFF_HIDDEN).init = []
{
// Test
*g_gamma = 1.0f;
};

REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice);
REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2);
REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetXVColor);
Expand Down
7 changes: 7 additions & 0 deletions rpcs3/Emu/Cell/Modules/cellVideoOut.cpp
@@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/RSX/rsx_utils.h"

#include "cellVideoOut.h"

Expand Down Expand Up @@ -145,6 +147,11 @@ error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration
return CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}

auto conf = fxm::get_always<rsx::avconf>();
conf->aspect = config->aspect;
conf->format = config->format;
conf->scanline_pitch = config->pitch;

return CELL_OK;
}

Expand Down
25 changes: 21 additions & 4 deletions rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp
Expand Up @@ -644,10 +644,10 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D));
return true;
case rsx::texture_dimension_extended::texture_dimension_2d:
if (DstExpectsSca() && (m_prog.shadow_textures & (1 << dst.tex_num)))
if (m_prog.shadow_textures & (1 << dst.tex_num))
{
m_shadow_sampled_textures |= (1 << dst.tex_num);
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D) + ".r", false); //No swizzle mask on shadow lookup
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D) + ".xxxx");
return true;
}
if (m_prog.redirected_textures & (1 << dst.tex_num))
Expand Down Expand Up @@ -676,10 +676,10 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
return true;
case rsx::texture_dimension_extended::texture_dimension_2d:
//Note shadow comparison only returns a true/false result!
if (DstExpectsSca() && (m_prog.shadow_textures & (1 << dst.tex_num)))
if (m_prog.shadow_textures & (1 << dst.tex_num))
{
m_shadow_sampled_textures |= (1 << dst.tex_num);
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ) + ".r", false); //No swizzle mask on shadow lookup
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ) + ".xxxx");
}
else
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ));
Expand Down Expand Up @@ -711,6 +711,23 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
}
return false;
case RSX_FP_OPCODE_TXB:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case rsx::texture_dimension_extended::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_BIAS));
return true;
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_BIAS));
m_2d_sampled_textures |= (1 << dst.tex_num);
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_BIAS));
return true;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_BIAS));
return true;
}
return false;
case RSX_FP_OPCODE_TXL:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
Expand Down
147 changes: 127 additions & 20 deletions rpcs3/Emu/RSX/Common/GLSLCommon.h
Expand Up @@ -313,7 +313,45 @@ namespace glsl
OS << "}\n\n";
}

static void insert_glsl_legacy_function(std::ostream& OS, glsl::program_domain domain, bool require_lit_emulation, bool require_depth_conversion = false, bool require_wpos = false)
static void insert_rop(std::ostream& OS, bool _32_bit_exports)
{
const std::string reg0 = _32_bit_exports ? "r0" : "h0";
const std::string reg1 = _32_bit_exports ? "r2" : "h4";
const std::string reg2 = _32_bit_exports ? "r3" : "h6";
const std::string reg3 = _32_bit_exports ? "r4" : "h8";

//TODO: Implement all ROP options like CSAA and ALPHA_TO_ONE here
OS << " if ((rop_control & 0xFF) != 0)\n";
OS << " {\n";
OS << " bool alpha_test = (rop_control & 0x11) > 0;\n";
OS << " uint alpha_func = ((rop_control >> 16) & 0x7);\n";
OS << " bool srgb_convert = (rop_control & 0x2) > 0;\n\n";
OS << " if (alpha_test && !comparison_passes(" << reg0 << ".a, alpha_ref, alpha_func))\n";
OS << " {\n";
OS << " discard;\n";
OS << " }\n";

if (!_32_bit_exports)
{
//Tested using NPUB90375; some shaders (32-bit output only?) do not obey srgb flags
OS << " else if (srgb_convert)\n";
OS << " {\n";
OS << " " << reg0 << ".rgb = linear_to_srgb(" << reg0 << ").rgb;\n";
OS << " " << reg1 << ".rgb = linear_to_srgb(" << reg1 << ").rgb;\n";
OS << " " << reg2 << ".rgb = linear_to_srgb(" << reg2 << ").rgb;\n";
OS << " " << reg3 << ".rgb = linear_to_srgb(" << reg3 << ").rgb;\n";
OS << " }\n";
}

OS << " }\n\n";

OS << " ocol0 = " << reg0 << ";\n";
OS << " ocol1 = " << reg1 << ";\n";
OS << " ocol2 = " << reg2 << ";\n";
OS << " ocol3 = " << reg3 << ";\n\n";
}

static void insert_glsl_legacy_function(std::ostream& OS, glsl::program_domain domain, bool require_lit_emulation, bool require_depth_conversion = false, bool require_wpos = false, bool require_texture_ops = true)
{
if (require_lit_emulation)
{
Expand Down Expand Up @@ -394,6 +432,67 @@ namespace glsl
OS << "}\n\n";
}

if (require_texture_ops)
{
OS << "vec4 linear_to_srgb(vec4 cl)\n";
OS << "{\n";
OS << " vec4 low = cl * 12.92;\n";
OS << " vec4 high = 1.055 * pow(cl, vec4(1. / 2.4)) - 0.055;\n";
OS << " bvec4 select = lessThan(cl, vec4(0.0031308));\n";
OS << " return clamp(mix(high, low, select), 0., 1.);\n";
OS << "}\n\n";

OS << "float srgb_to_linear(float cs)\n";
OS << "{\n";
OS << " if (cs <= 0.04045) return cs / 12.92;\n";
OS << " return pow((cs + 0.055) / 1.055, 2.4);\n";
OS << "}\n\n";

//TODO: Move all the texture read control operations here
OS << "vec4 process_texel(vec4 rgba, uint control_bits)\n";
OS << "{\n";
OS << " if (control_bits == 0) return rgba;\n\n";
OS << " if ((control_bits & 0x10) > 0)\n";
OS << " {\n";
OS << " //Alphakill\n";
OS << " if (!comparison_passes(rgba.a, 0., (control_bits >> 5) & 0x7))\n";
OS << " {\n";
OS << " discard;\n";
OS << " return rgba;\n";
OS << " }\n";
OS << " }\n\n";
OS << " //TODO: Verify gamma control bit ordering, looks to be 0x7 for rgb, 0xF for rgba\n";
OS << " uint srgb_in = (control_bits & 0xF);\n";
OS << " if ((srgb_in & 0x1) > 0) rgba.r = srgb_to_linear(rgba.r);\n";
OS << " if ((srgb_in & 0x2) > 0) rgba.g = srgb_to_linear(rgba.g);\n";
OS << " if ((srgb_in & 0x4) > 0) rgba.b = srgb_to_linear(rgba.b);\n";
OS << " if ((srgb_in & 0x8) > 0) rgba.a = srgb_to_linear(rgba.a);\n";
OS << " return rgba;\n";
OS << "}\n\n";

OS << "#define TEX1D(index, tex, coord1) process_texel(texture(tex, coord1 * texture_parameters[index].x), uint(texture_parameters[index].w))\n";
OS << "#define TEX1D_BIAS(index, tex, coord1, bias) process_texel(texture(tex, coord1 * texture_parameters[index].x, bias), uint(texture_parameters[index].w))\n";
OS << "#define TEX1D_LOD(index, tex, coord1, lod) process_texel(textureLod(tex, coord1 * texture_parameters[index].x, lod), uint(texture_parameters[index].w))\n";
OS << "#define TEX1D_GRAD(index, tex, coord1, dpdx, dpdy) process_texel(textureGrad(tex, coord1 * texture_parameters[index].x, dpdx, dpdy), uint(texture_parameters[index].w))\n";
OS << "#define TEX1D_PROJ(index, tex, coord2) process_texel(textureGrad(tex, coord2 * vec2(texture_parameters[index].x, 1.)), uint(texture_parameters[index].w))\n";

OS << "#define TEX2D(index, tex, coord2) process_texel(texture(tex, coord2 * texture_parameters[index].xy), uint(texture_parameters[index].w))\n";
OS << "#define TEX2D_BIAS(index, tex, coord2, bias) process_texel(texture(tex, coord2 * texture_parameters[index].xy, bias), uint(texture_parameters[index].w))\n";
OS << "#define TEX2D_LOD(index, tex, coord2, lod) process_texel(textureLod(tex, coord2 * texture_parameters[index].xy, lod), uint(texture_parameters[index].w))\n";
OS << "#define TEX2D_GRAD(index, tex, coord2, dpdx, dpdy) process_texel(textureGrad(tex, coord2 * texture_parameters[index].xy, dpdx, dpdy), uint(texture_parameters[index].w))\n";
OS << "#define TEX2D_PROJ(index, tex, coord4) process_texel(textureProj(tex, coord4 * vec4(texture_parameters[index].xy, 1., 1.)), uint(texture_parameters[index].w))\n";

OS << "#define TEX2D_DEPTH_RGBA8(index, tex, coord2) process_texel(texture2DReconstruct(tex, coord2 * texture_parameters[index].xy, texture_parameters[index].z), uint(texture_parameters[index].w))\n";
OS << "#define TEX2D_SHADOW(index, tex, coord3) texture(tex, coord3 * vec3(texture_parameters[index].xy, 1.))\n";
OS << "#define TEX2D_SHADOWPROJ(index, tex, coord4) textureProj(tex, coord4 * vec4(texture_parameters[index].xy, 1., 1.))\n";

OS << "#define TEX3D(index, tex, coord3) process_texel(texture(tex, coord3), uint(texture_parameters[index].w))\n";
OS << "#define TEX3D_BIAS(index, tex, coord3, bias) process_texel(texture(tex, coord3, bias), uint(texture_parameters[index].w))\n";
OS << "#define TEX3D_LOD(index, tex, coord3, lod) process_texel(textureLod(tex, coord3, lod), uint(texture_parameters[index].w))\n";
OS << "#define TEX3D_GRAD(index, tex, coord3, dpdx, dpdy) process_texel(textureGrad(tex, coord3, dpdx, dpdy), uint(texture_parameters[index].w))\n";
OS << "#define TEX3D_PROJ(index, tex, coord4) process_texel(textureProj(tex, coord4), uint(texture_parameters[index].w))\n\n";
}

if (require_wpos)
{
OS << "vec4 get_wpos()\n";
Expand Down Expand Up @@ -434,49 +533,57 @@ namespace glsl
case FUNCTION::FUNCTION_REFL:
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "texture($t, $0.x)";
return "TEX1D($_i, $t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_BIAS:
return "TEX1D_BIAS($_i, $t, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
return "TEX1D_PROJ($_i, $t, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "textureLod($t, $0.x, $1.x)";
return "TEX1D_LOD($_i, $t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
return "textureGrad($t, $0.x, $1.x, $2.x)";
return "TEX1D_GRAD($_i, $t, $0.x, $1.x, $2.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "texture($t, $0.xy * texture_parameters[$_i].xy)";
return "TEX2D($_i, $t, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_BIAS:
return "TEX2D_BIAS($_i, $t, $0.xy, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "textureProj($t, $0 * vec4(texture_parameters[$_i].xy, 1., 1.), $1.x)"; // Note: $1.x is bias
return "TEX2D_PROJ($_i, $t, $0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "textureLod($t, $0.xy * texture_parameters[$_i].xy, $1.x)";
return "TEX2D_LOD($_i, $t, $0.xy, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
return "textureGrad($t, $0.xy * texture_parameters[$_i].xy , $1.xy, $2.xy)";
return "TEX2D_GRAD($_i, $t, $0.xy, $1.xy, $2.xy)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
return "texture($t, $0.xyz * vec3(texture_parameters[$_i].xy, 1.))";
return "TEX2D_SHADOW($_i, $t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
return "textureProj($t, $0 * vec4(texture_parameters[$_i].xy, 1., 1.), $1.x)"; // Note: $1.x is bias
return "TEX2D_SHADOWPROJ($_i, $t, $0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "texture($t, $0.xyz)";
return "TEX3D($_i, $t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_BIAS:
return "TEX3D_BIAS($_i, $t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "texture($t, ($0.xyz / $0.w))";
return "TEX3D($_i, $t, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "textureLod($t, $0.xyz, $1.x)";
return "TEX3D_LOD($_i, $t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
return "TEX3D_GRAD($_i, $t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
return "texture($t, $0.xyz)";
return "TEX3D($_i, $t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_BIAS:
return "TEX3D_BIAS($_i, $t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
return "TEX3D_PROJ($_i, $t, $0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
return "textureLod($t, $0.xyz, $1.x)";
return "TEX3D_LOD($_i, $t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
return "TEX3D_GRAD($_i, $t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY:
return "dFdy($0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
return "textureLod($t, $0.xy, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "texture2DReconstruct($t, $0.xy * texture_parameters[$_i].xy, texture_parameters[$_i].z)";
return "TEX2D_DEPTH_RGBA8($_i, $t, $0.xy)";
}
}
}
7 changes: 4 additions & 3 deletions rpcs3/Emu/RSX/Common/ProgramStateCache.h
Expand Up @@ -349,9 +349,10 @@ class program_state_cache
}
else if (sanitize)
{
//Lower NaNs to 0
const auto mask = _mm_cmpunord_ps((__m128&)shuffled_vector, _mm_set1_ps(1.f));
const auto result = _mm_andnot_ps(mask, (__m128&)shuffled_vector);
//Convert NaNs and Infs to 0
const auto masked = _mm_and_si128((__m128i&)shuffled_vector, _mm_set1_epi32(0x7fffffff));
const auto valid = _mm_cmplt_epi32(masked, _mm_set1_epi32(0x7f800000));
const auto result = _mm_and_si128((__m128i&)shuffled_vector, valid);
_mm_stream_si128((__m128i*)dst, (__m128i&)result);
}
else
Expand Down
4 changes: 4 additions & 0 deletions rpcs3/Emu/RSX/Common/ShaderParam.h
Expand Up @@ -18,20 +18,24 @@ enum class FUNCTION {
FUNCTION_DFDY,
FUNCTION_REFL,
FUNCTION_TEXTURE_SAMPLE1D,
FUNCTION_TEXTURE_SAMPLE1D_BIAS,
FUNCTION_TEXTURE_SAMPLE1D_PROJ,
FUNCTION_TEXTURE_SAMPLE1D_LOD,
FUNCTION_TEXTURE_SAMPLE1D_GRAD,
FUNCTION_TEXTURE_SAMPLE2D,
FUNCTION_TEXTURE_SAMPLE2D_BIAS,
FUNCTION_TEXTURE_SAMPLE2D_PROJ,
FUNCTION_TEXTURE_SAMPLE2D_LOD,
FUNCTION_TEXTURE_SAMPLE2D_GRAD,
FUNCTION_TEXTURE_SHADOW2D,
FUNCTION_TEXTURE_SHADOW2D_PROJ,
FUNCTION_TEXTURE_SAMPLECUBE,
FUNCTION_TEXTURE_SAMPLECUBE_BIAS,
FUNCTION_TEXTURE_SAMPLECUBE_PROJ,
FUNCTION_TEXTURE_SAMPLECUBE_LOD,
FUNCTION_TEXTURE_SAMPLECUBE_GRAD,
FUNCTION_TEXTURE_SAMPLE3D,
FUNCTION_TEXTURE_SAMPLE3D_BIAS,
FUNCTION_TEXTURE_SAMPLE3D_PROJ,
FUNCTION_TEXTURE_SAMPLE3D_LOD,
FUNCTION_TEXTURE_SAMPLE3D_GRAD,
Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Emu/RSX/Common/TextureUtils.h
Expand Up @@ -15,6 +15,12 @@ namespace rsx
framebuffer_storage = 3
};

enum texture_colorspace
{
rgb_linear = 0,
srgb_nonlinear = 1
};

//Sampled image descriptor
struct sampled_image_descriptor_base
{
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/Common/surface_store.h
Expand Up @@ -64,7 +64,7 @@ namespace rsx
GcmTileInfo *tile = nullptr;
rsx::surface_antialiasing aa_mode = rsx::surface_antialiasing::center_1_sample;

virtual image_storage_type get_surface() const = 0;
virtual image_storage_type get_surface() = 0;
virtual u16 get_surface_width() const = 0;
virtual u16 get_surface_height() const = 0;
virtual u16 get_rsx_pitch() const = 0;
Expand Down