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

@ -500,27 +500,42 @@ public:
const Register& buf_reg) {
const std::string dest = GetOutputAttribute(attribute);
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
// instruction for now.
if (stage == Maxwell3D::Regs::ShaderStage::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
// drivers from complaining about out of boundary writes, guard them.
const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " +
std::to_string(MAX_GEOMETRY_BUFFERS) + ')'};
shader.AddLine("amem[" + buf_index + "][" +
std::to_string(static_cast<u32>(attribute)) + ']' +
GetSwizzle(elem) + " = " + src + ';');
} else {
if (attribute == Attribute::Index::PointSize) {
fixed_pipeline_output_attributes_used.insert(attribute);
shader.AddLine(dest + " = " + src + ';');
} else {
shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';');
}
}
// Can happen with unknown/unimplemented output attributes, in which case we ignore the
// instruction for now.
if (stage == Maxwell3D::Regs::ShaderStage::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
// drivers from complaining about out of boundary writes, guard them.
const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " +
std::to_string(MAX_GEOMETRY_BUFFERS) + ')'};
shader.AddLine("amem[" + buf_index + "][" +
std::to_string(static_cast<u32>(attribute)) + ']' + GetSwizzle(elem) +
" = " + src + ';');
return;
}
switch (attribute) {
case Attribute::Index::ClipDistances0123:
case Attribute::Index::ClipDistances4567: {
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() {
if (stage != Maxwell3D::Regs::ShaderStage::Vertex)
return;
bool clip_distances_declared = false;
declarations.AddLine("out gl_PerVertex {");
++declarations.scope;
declarations.AddLine("vec4 gl_Position;");
for (auto& o : fixed_pipeline_output_attributes_used) {
if (o == Attribute::Index::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.AddLine("};");
@ -916,6 +938,10 @@ private:
return "gl_PointSize";
case Attribute::Index::Position:
return "position";
case Attribute::Index::ClipDistances0123:
case Attribute::Index::ClipDistances4567: {
return "gl_ClipDistance";
}
default:
const u32 index{static_cast<u32>(attribute) -
static_cast<u32>(Attribute::Index::Attribute_0)};