rsx: Vertex program output fixes

This commit is contained in:
kd-11 2017-05-11 01:42:55 +03:00
parent 07f0c7b4a5
commit c5975d5f66
8 changed files with 120 additions and 103 deletions

View File

@ -245,3 +245,17 @@ public:
return name + "." + fmt::merge({ swizzles }, ".");
}
};
struct vertex_reg_info
{
std::string name; //output name
bool need_declare; //needs explicit declaration as output (not language in-built)
std::string src_reg; //reg to get data from
std::string src_reg_mask; //input swizzle mask
bool need_cast; //needs casting
std::string cond; //update on condition
std::string default_val; //fallback value on cond fail
std::string dst_alias; //output name override
bool check_mask; //check program output control mask for this output
u32 check_mask_value; //program output control mask for testing
};

View File

@ -89,8 +89,7 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 512));
fill_scale_offset_data(mapped_buffer, true, false);
fill_user_clip_data((char*)mapped_buffer + 64);
fill_fragment_state_buffer((char *)mapped_buffer + 96, m_fragment_program);
fill_fragment_state_buffer((char *)mapped_buffer + 128, m_fragment_program);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 512));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {

View File

@ -38,7 +38,8 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
OS << "cbuffer SCALE_OFFSET : register(b0)" << std::endl;
OS << "{" << std::endl;
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " float4 userClip[2];" << std::endl;
OS << " int4 userClipEnabled[2];" << std::endl;
OS << " float4 userClipFactor[2];" << std::endl;
OS << " float fog_param0;\n";
OS << " float fog_param1;\n";
OS << " int isAlphaTested;" << std::endl;

View File

@ -31,7 +31,8 @@ void D3D12VertexProgramDecompiler::insertHeader(std::stringstream &OS)
OS << "cbuffer SCALE_OFFSET : register(b0)" << std::endl;
OS << "{" << std::endl;
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " float4 userClip[2];" << std::endl;
OS << " int4 userClipEnabled[2];" << std::endl;
OS << " float4 userClipFactor[2];" << std::endl;
OS << " float fog_param0;" << std::endl;
OS << " float fog_param1;" << std::endl;
OS << " int isAlphaTested;" << std::endl;
@ -110,31 +111,21 @@ void D3D12VertexProgramDecompiler::insertOutputs(std::stringstream & OS, const s
OS << "};" << std::endl;
}
struct reg_info
{
std::string name;
bool need_declare;
std::string src_reg;
std::string src_reg_mask;
bool need_cast;
};
static const reg_info reg_table[] =
static const vertex_reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
{ "diff_color", true, "dst_reg1", "", false },
{ "spec_color", true, "dst_reg2", "", false },
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fogc", true, "dst_reg5", ".x", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w", false },
// TODO: Handle user clip distance properly
/* { "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w", false },*/
{ "fogc", true, "dst_reg5", ".xxxx", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClipFactor[0].x", false, "userClipEnabled[0].x > 0", "0.5", "Out.dst_userClip0.x" },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".z * userClipFactor[0].y", false, "userClipEnabled[0].y > 0", "0.5", "Out.dst_userClip0.y" },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".w * userClipFactor[0].z", false, "userClipEnabled[0].z > 0", "0.5", "Out.dst_userClip0.z" },
//{ "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_ClipDistance[0]", false, "dst_reg6", ".y * userClipFactor[0].w", false, "userClipEnabled[0].w > 0", "0.5", "Out.dst_userClip0.w" },
{ "gl_ClipDistance[0]", false, "dst_reg6", ".z * userClipFactor[1].x", false, "userClipEnabled[1].x > 0", "0.5", "Out.dst_userClip1.x" },
{ "gl_ClipDistance[0]", false, "dst_reg6", ".w * userClipFactor[1].y", false, "userClipEnabled[1].y > 0", "0.5", "Out.dst_userClip1.y" },
{ "tc9", false, "dst_reg6", "", false },
{ "tc0", true, "dst_reg7", "", false },
{ "tc1", true, "dst_reg8", "", false },
@ -229,7 +220,19 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
if (i.name == "front_spec_color")
insert_front_specular = false;
OS << " Out." << i.src_reg << " = " << i.src_reg << ";" << std::endl;
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
std::string output_name = i.dst_alias.empty() ? "Out." + i.src_reg : i.dst_alias;
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << output_name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
}
else
{
//Condition and fallback values provided
OS << " " << output_name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";" << std::endl;
}
}
}
@ -242,20 +245,6 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
if (m_parr.HasParam(PF_PARAM_NONE, "float4", "dst_reg2"))
OS << " Out.dst_reg4 = dst_reg2;\n";
// user clip
if ((rsx_vertex_program.output_mask & (CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2)) != 0)
{
OS << " Out.dst_userClip0.x = dst_reg5.y * userClip[0].x;\n";
OS << " Out.dst_userClip0.y = dst_reg5.z * userClip[0].y;\n";
OS << " Out.dst_userClip0.z = dst_reg5.w * userClip[0].z;\n";
}
if ((rsx_vertex_program.output_mask & (CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5)) != 0)
{
OS << " Out.dst_userClip0.w = dst_reg6.y * userClip[0].w;\n";
OS << " Out.dst_userClip1.x = dst_reg6.z * userClip[1].x;\n";
OS << " Out.dst_userClip1.y = dst_reg6.w * userClip[1].y;\n";
}
OS << " Out.dst_reg0 = mul(Out.dst_reg0, scaleOffsetMat);" << std::endl;
OS << " return Out;" << std::endl;
OS << "}" << std::endl;

View File

@ -289,13 +289,6 @@ void GLGSRender::begin()
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
__glcheck enable(true, GL_CLIP_DISTANCE0 + 0);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 1);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 2);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 3);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 4);
__glcheck enable(true, GL_CLIP_DISTANCE0 + 5);
std::chrono::time_point<steady_clock> now = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
}
@ -573,6 +566,14 @@ void GLGSRender::on_init_thread()
m_gl_sampler_states[i].bind(i);
}
//Clip planes are shader controlled; enable all planes driver-side
glEnable(GL_CLIP_DISTANCE0 + 0);
glEnable(GL_CLIP_DISTANCE0 + 1);
glEnable(GL_CLIP_DISTANCE0 + 2);
glEnable(GL_CLIP_DISTANCE0 + 3);
glEnable(GL_CLIP_DISTANCE0 + 4);
glEnable(GL_CLIP_DISTANCE0 + 5);
m_gl_texture_cache.initialize(this);
}

View File

@ -34,7 +34,8 @@ void GLVertexDecompilerThread::insertHeader(std::stringstream &OS)
OS << "layout(std140, binding = 0) uniform ScaleOffsetBuffer" << std::endl;
OS << "{" << std::endl;
OS << " mat4 scaleOffsetMat;" << std::endl;
OS << " vec4 userClip[2];" << std::endl;
OS << " ivec4 userClipEnabled[2];" << std::endl;
OS << " vec4 userClipFactor[2];" << std::endl;
OS << "};" << std::endl;
}
@ -81,11 +82,6 @@ void GLVertexDecompilerThread::insertInputs(std::stringstream & OS, const std::v
}
}
}
for (int i = 0; i <= 5; i++)
{
OS << "uniform int uc_m" + std::to_string(i) + "= 0;\n";
}
}
void GLVertexDecompilerThread::insertConstants(std::stringstream & OS, const std::vector<ParamType> & constants)
@ -108,30 +104,22 @@ void GLVertexDecompilerThread::insertConstants(std::stringstream & OS, const std
}
}
struct reg_info
{
std::string name;
bool need_declare;
std::string src_reg;
std::string src_reg_mask;
bool need_cast;
};
static const reg_info reg_table[] =
static const vertex_reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
{ "diff_color", true, "dst_reg1", "", false },
{ "spec_color", true, "dst_reg2", "", false },
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClip[0].x", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClip[0].y", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClip[0].z", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FOG },
//Warning: Always define all 3 clip plane groups together to avoid flickering with openGL
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClipFactor[0].x", false, "userClipEnabled[0].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClipFactor[0].y", false, "userClipEnabled[0].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClipFactor[0].z", false, "userClipEnabled[0].z > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClip[0].w", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClip[1].x", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClip[1].y", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClipFactor[0].w", false, "userClipEnabled[0].w > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClipFactor[1].x", false, "userClipEnabled[1].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClipFactor[1].y", false, "userClipEnabled[1].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "tc0", true, "dst_reg7", "", false },
{ "tc1", true, "dst_reg8", "", false },
{ "tc2", true, "dst_reg9", "", false },
@ -141,7 +129,7 @@ static const reg_info reg_table[] =
{ "tc6", true, "dst_reg13", "", false },
{ "tc7", true, "dst_reg14", "", false },
{ "tc8", true, "dst_reg15", "", false },
{ "tc9", true, "dst_reg6", "", false } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
{ "tc9", true, "dst_reg6", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
};
void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector<ParamType> & outputs)
@ -159,6 +147,9 @@ void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg) && i.need_declare)
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
@ -333,6 +324,9 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg))
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
@ -340,6 +334,7 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
insert_front_specular = false;
std::string name = i.name;
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (front_back_diffuse && name == "diff_color")
name = "back_diff_color";
@ -347,7 +342,16 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
if (front_back_specular && name == "spec_color")
name = "back_spec_color";
OS << " " << name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
}
else
{
//Insert if-else condition
OS << " " << name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";" << std::endl;
}
}
}

View File

@ -601,32 +601,35 @@ namespace rsx
rsx::method_registers.clip_plane_5_enabled(),
};
std::array<f32, 8> tmp{};
s32 clip_enabled_flags[8] = {};
f32 clip_distance_factors[8] = {};
for (int index = 0; index < 6; ++index)
{
f32 value = 0;
switch (clip_plane_control[index])
{
default:
LOG_ERROR(RSX, "bad clip plane control (0x%x)", (u8)clip_plane_control[index]);
case rsx::user_clip_plane_op::disable:
value = 0.f;
clip_enabled_flags[index] = 0;
clip_distance_factors[index] = 0.f;
break;
case rsx::user_clip_plane_op::greater_or_equal:
value = 1.f;
clip_enabled_flags[index] = 1;
clip_distance_factors[index] = 1.f;
break;
case rsx::user_clip_plane_op::less_than:
value = -1.f;
clip_enabled_flags[index] = 1;
clip_distance_factors[index] = -1.f;
break;
}
tmp[index] = value;
}
stream_vector_from_memory((char*)buffer, tmp.data());
stream_vector_from_memory((char*)buffer + 16, &tmp[4]);
memcpy(buffer, clip_enabled_flags, 32);
memcpy((char*)buffer + 32, clip_distance_factors, 32);
}
/**

View File

@ -33,7 +33,8 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
OS << "layout(std140, set = 0, binding = 0) uniform ScaleOffsetBuffer" << std::endl;
OS << "{" << std::endl;
OS << " mat4 scaleOffsetMat;" << std::endl;
OS << " vec4 userClip[2];" << std::endl;
OS << " ivec4 userClipEnabled[2];" << std::endl;
OS << " vec4 userClipFactor[2];" << std::endl;
OS << "};" << std::endl;
vk::glsl::program_input in;
@ -142,34 +143,22 @@ void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std
}
}
struct reg_info
{
std::string name;
bool need_declare;
std::string src_reg;
std::string src_reg_mask;
bool need_cast;
};
static const reg_info reg_table[] =
static const vertex_reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
{ "back_diff_color", true, "dst_reg1", "", false },
{ "back_spec_color", true, "dst_reg2", "", false },
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true },
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClip[0].x", false },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClip[0].y", false },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClip[0].z", false },
{ "fog_c", true, "dst_reg5", ".xxxx", true, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FOG },
//Warning: With spir-v if you declare clip distance var, you must assign a value even when its disabled! Runtime does not assign a default value
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * userClipFactor[0].x", false, "userClipEnabled[0].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * userClipFactor[0].y", false, "userClipEnabled[0].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * userClipFactor[0].z", false, "userClipEnabled[0].z > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
//Disable user clip planes until they are properly handled
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClip[0].w", false },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClip[1].x", false },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClip[1].y", false },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * userClipFactor[0].w", false, "userClipEnabled[0].w > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * userClipFactor[1].x", false, "userClipEnabled[1].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * userClipFactor[1].y", false, "userClipEnabled[1].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "tc0", true, "dst_reg7", "", false },
{ "tc1", true, "dst_reg8", "", false },
{ "tc2", true, "dst_reg9", "", false },
@ -179,7 +168,7 @@ static const reg_info reg_table[] =
{ "tc6", true, "dst_reg13", "", false },
{ "tc7", true, "dst_reg14", "", false },
{ "tc8", true, "dst_reg15", "", false },
{ "tc9", true, "dst_reg6", "", false } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
{ "tc9", true, "dst_reg6", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
};
void VKVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector<ParamType> & outputs)
@ -194,6 +183,9 @@ void VKVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg) && i.need_declare)
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
@ -335,13 +327,27 @@ void VKVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
{
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg))
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
OS << " " << i.name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << i.name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl;
}
else
{
//Insert if-else condition
OS << " " << i.name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";" << std::endl;
}
}
}