rsx/gl/vk/dx12: Add emulated texture fetch for depth read (#2173)

* rsx/gl/vk/dx12: Add emulated texture fetch for depth read

gl/vk/dx12: Simplify reinterpretation equation

* gl: Remove unnecessary re-swizzle

* glsl: explicitly cast uint to float
This commit is contained in:
kd-11 2016-09-29 09:54:32 +03:00 committed by raven02
parent 9abb908226
commit 5430e1d310
11 changed files with 96 additions and 2 deletions

View File

@ -448,7 +448,10 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D));
return true;
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D));
if (m_prog.redirected_textures & (1 << dst.tex_num))
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA));
else
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D));
return true;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE));

View File

@ -106,7 +106,7 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con
if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode ||
binary1.back_color_diffuse_output != binary2.back_color_diffuse_output || binary1.back_color_specular_output != binary2.back_color_specular_output ||
binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func)
binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func || binary1.redirected_textures != binary2.redirected_textures)
return false;
const qword *instBuffer1 = (const qword*)binary1.addr;
const qword *instBuffer2 = (const qword*)binary2.addr;

View File

@ -37,6 +37,7 @@ enum class FUNCTION {
FUNCTION_VERTEX_TEXTURE_FETCH2D,
FUNCTION_VERTEX_TEXTURE_FETCH3D,
FUNCTION_VERTEX_TEXTURE_FETCHCUBE,
FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA
};
enum class COMPARE {

View File

@ -80,6 +80,8 @@ std::string getFunctionImp(FUNCTION f)
return "ddx($0)";
case FUNCTION::FUNCTION_DFDY:
return "ddy($0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "texture2DReconstruct($t.Sample($tsampler, $0.xy * $t_scale))";
}
}
@ -202,5 +204,14 @@ void insert_d3d12_legacy_function(std::ostream& OS)
OS << "{\n";
OS << " return unpackSnorm2x16(val) * 6.1E+5;\n";
OS << "}\n\n";
OS << "float4 texture2DReconstruct(float depth_value)\n";
OS << "{\n";
OS << " uint value = round(depth_value * 16777215);\n";
OS << " uint b = (value & 0xff);\n";
OS << " uint g = (value >> 8) & 0xff;\n";
OS << " uint r = (value >> 16) & 0xff;\n";
OS << " return float4(r/255., g/255., b/255., 1.);\n";
OS << "}\n\n";
}
#endif

View File

@ -43,6 +43,23 @@ void D3D12GSRender::load_program()
m_vertex_program = get_current_vertex_program();
m_fragment_program = get_current_fragment_program();
for (int i = 0; i < 16; ++i)
{
auto &tex = rsx::method_registers.fragment_textures[i];
if (tex.enabled())
{
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
if (m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
u32 format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
if (format == CELL_GCM_TEXTURE_A8R8G8B8 || format == CELL_GCM_TEXTURE_D8R8G8B8)
{
m_fragment_program.redirected_textures |= (1 << i);
}
}
}
}
D3D12PipelineProperties prop = {};
prop.Topology = get_primitive_topology_type(rsx::method_registers.current_draw_clause.primitive);

View File

@ -80,6 +80,8 @@ std::string getFunctionImpl(FUNCTION f)
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)";
}
}
@ -137,4 +139,15 @@ void insert_glsl_legacy_function(std::ostream& OS)
OS << " result.z = clamped_val.x > 0.0 ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.0;\n";
OS << " return result;\n";
OS << "}\n\n";
//NOTE: We lose precision if we just store depth value into 8-bit textures i.e (depth, 0, 0)
OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n";
OS << "{\n";
OS << " float depth_value = texture(tex, coord.xy).r;\n";
OS << " uint value = uint(depth_value * 16777215);\n";
OS << " uint b = (value & 0xff);\n";
OS << " uint g = (value >> 8) & 0xff;\n";
OS << " uint r = (value >> 16) & 0xff;\n";
OS << " return vec4(float(r)/255., float(g)/255., float(b)/255., 1.);\n";
OS << "}\n\n";
}

View File

@ -653,6 +653,23 @@ bool GLGSRender::load_program()
RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program = get_current_fragment_program();
for (int i = 0; i < 16; ++i)
{
auto &tex = rsx::method_registers.fragment_textures[i];
if (tex.enabled())
{
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
if (m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
u32 format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
if (format == CELL_GCM_TEXTURE_A8R8G8B8 || format == CELL_GCM_TEXTURE_D8R8G8B8)
{
fragment_program.redirected_textures |= (1 << i);
}
}
}
}
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
m_program->use();

View File

@ -221,6 +221,7 @@ struct RSXFragmentProgram
u32 offset;
u32 ctrl;
u16 unnormalized_coords;
u16 redirected_textures;
rsx::comparison_function alpha_func;
bool front_back_color_enabled : 1;
bool back_color_diffuse_output : 1;

View File

@ -828,6 +828,8 @@ namespace rsx
result.origin_mode = rsx::method_registers.shader_window_origin();
result.pixel_center_mode = rsx::method_registers.shader_window_pixel();
result.height = rsx::method_registers.shader_window_height();
result.redirected_textures = 0;
std::array<texture_dimension_extended, 16> texture_dimensions;
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)

View File

@ -75,6 +75,8 @@ namespace vk
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)";
}
}
@ -132,6 +134,16 @@ namespace vk
OS << " result.z = clamped_val.x > 0. ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.;\n";
OS << " return result;\n";
OS << "}\n\n";
OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n";
OS << "{\n";
OS << " float depth_value = texture(tex, coord.xy).r;\n";
OS << " uint value = uint(depth_value * 16777215);\n";
OS << " uint b = (value & 0xff);\n";
OS << " uint g = (value >> 8) & 0xff;\n";
OS << " uint r = (value >> 16) & 0xff;\n";
OS << " return vec4(float(r)/255., float(g)/255., float(b)/255., 1.);\n";
OS << "}\n\n";
}
void init_default_resources(TBuiltInResource &rsc)

View File

@ -975,6 +975,23 @@ bool VKGSRender::load_program()
RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program = get_current_fragment_program();
for (int i = 0; i < 16; ++i)
{
auto &tex = rsx::method_registers.fragment_textures[i];
if (tex.enabled())
{
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
if (m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
u32 format = tex.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
if (format == CELL_GCM_TEXTURE_A8R8G8B8 || format == CELL_GCM_TEXTURE_D8R8G8B8)
{
fragment_program.redirected_textures |= (1 << i);
}
}
}
}
vk::pipeline_props properties = {};
properties.ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;