1
0
Fork 0
forked from suyu/suyu

Merge pull request #1783 from ReinUsesLisp/clip-distances

gl_shader_decompiler: Implement clip distances
This commit is contained in:
bunnei 2018-11-25 22:35:30 -05:00 committed by GitHub
commit 8ce90a4f0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 21 deletions

View file

@ -82,6 +82,8 @@ union Attribute {
Position = 7, Position = 7,
Attribute_0 = 8, Attribute_0 = 8,
Attribute_31 = 39, Attribute_31 = 39,
ClipDistances0123 = 44,
ClipDistances4567 = 45,
PointCoord = 46, PointCoord = 46,
// This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval

View file

@ -62,7 +62,16 @@ struct Header {
INSERT_PADDING_BYTES(1); // ImapSystemValuesB INSERT_PADDING_BYTES(1); // ImapSystemValuesB
INSERT_PADDING_BYTES(16); // ImapGenericVector[32] INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
INSERT_PADDING_BYTES(2); // ImapColor INSERT_PADDING_BYTES(2); // ImapColor
INSERT_PADDING_BYTES(2); // ImapSystemValuesC union {
BitField<0, 8, u16> clip_distances;
BitField<8, 1, u16> point_sprite_s;
BitField<9, 1, u16> point_sprite_t;
BitField<10, 1, u16> fog_coordinate;
BitField<12, 1, u16> tessellation_eval_point_u;
BitField<13, 1, u16> tessellation_eval_point_v;
BitField<14, 1, u16> instance_id;
BitField<15, 1, u16> vertex_id;
};
INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10] INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10]
INSERT_PADDING_BYTES(1); // ImapReserved INSERT_PADDING_BYTES(1); // ImapReserved
INSERT_PADDING_BYTES(3); // OmapSystemValuesA INSERT_PADDING_BYTES(3); // OmapSystemValuesA

View file

@ -500,27 +500,42 @@ public:
const Register& buf_reg) { const Register& buf_reg) {
const std::string dest = GetOutputAttribute(attribute); const std::string dest = GetOutputAttribute(attribute);
const std::string src = GetRegisterAsFloat(val_reg); const std::string src = GetRegisterAsFloat(val_reg);
if (dest.empty())
return;
if (!dest.empty()) { // Can happen with unknown/unimplemented output attributes, in which case we ignore the
// Can happen with unknown/unimplemented output attributes, in which case we ignore the // instruction for now.
// instruction for now. if (stage == Maxwell3D::Regs::ShaderStage::Geometry) {
if (stage == Maxwell3D::Regs::ShaderStage::Geometry) { // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry
// TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry // shader. These instructions use a dirty register as buffer index, to avoid some
// shader. These instructions use a dirty register as buffer index, to avoid some // drivers from complaining about out of boundary writes, guard them.
// drivers from complaining about out of boundary writes, guard them. const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " +
const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " + std::to_string(MAX_GEOMETRY_BUFFERS) + ')'};
std::to_string(MAX_GEOMETRY_BUFFERS) + ')'}; shader.AddLine("amem[" + buf_index + "][" +
shader.AddLine("amem[" + buf_index + "][" + std::to_string(static_cast<u32>(attribute)) + ']' + GetSwizzle(elem) +
std::to_string(static_cast<u32>(attribute)) + ']' + " = " + src + ';');
GetSwizzle(elem) + " = " + src + ';'); return;
} else { }
if (attribute == Attribute::Index::PointSize) {
fixed_pipeline_output_attributes_used.insert(attribute); switch (attribute) {
shader.AddLine(dest + " = " + src + ';'); case Attribute::Index::ClipDistances0123:
} else { case Attribute::Index::ClipDistances4567: {
shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); const u64 index = attribute == Attribute::Index::ClipDistances4567 ? 4 : 0 + elem;
} UNIMPLEMENTED_IF_MSG(
} ((header.vtg.clip_distances >> index) & 1) == 0,
"Shader is setting gl_ClipDistance{} without enabling it in the header", index);
fixed_pipeline_output_attributes_used.insert(attribute);
shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';');
break;
}
case Attribute::Index::PointSize:
fixed_pipeline_output_attributes_used.insert(attribute);
shader.AddLine(dest + " = " + src + ';');
break;
default:
shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';');
break;
} }
} }
@ -740,12 +755,19 @@ private:
void GenerateVertex() { void GenerateVertex() {
if (stage != Maxwell3D::Regs::ShaderStage::Vertex) if (stage != Maxwell3D::Regs::ShaderStage::Vertex)
return; return;
bool clip_distances_declared = false;
declarations.AddLine("out gl_PerVertex {"); declarations.AddLine("out gl_PerVertex {");
++declarations.scope; ++declarations.scope;
declarations.AddLine("vec4 gl_Position;"); declarations.AddLine("vec4 gl_Position;");
for (auto& o : fixed_pipeline_output_attributes_used) { for (auto& o : fixed_pipeline_output_attributes_used) {
if (o == Attribute::Index::PointSize) if (o == Attribute::Index::PointSize)
declarations.AddLine("float gl_PointSize;"); declarations.AddLine("float gl_PointSize;");
if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 ||
o == Attribute::Index::ClipDistances4567)) {
declarations.AddLine("float gl_ClipDistance[];");
clip_distances_declared = true;
}
} }
--declarations.scope; --declarations.scope;
declarations.AddLine("};"); declarations.AddLine("};");
@ -916,6 +938,10 @@ private:
return "gl_PointSize"; return "gl_PointSize";
case Attribute::Index::Position: case Attribute::Index::Position:
return "position"; return "position";
case Attribute::Index::ClipDistances0123:
case Attribute::Index::ClipDistances4567: {
return "gl_ClipDistance";
}
default: default:
const u32 index{static_cast<u32>(attribute) - const u32 index{static_cast<u32>(attribute) -
static_cast<u32>(Attribute::Index::Attribute_0)}; static_cast<u32>(Attribute::Index::Attribute_0)};