summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h2
-rw-r--r--src/video_core/engines/shader_header.h11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp66
3 files changed, 58 insertions, 21 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 7e8449bc4..639bedb80 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -82,6 +82,8 @@ union Attribute {
Position = 7,
Attribute_0 = 8,
Attribute_31 = 39,
+ ClipDistances0123 = 44,
+ ClipDistances4567 = 45,
PointCoord = 46,
// 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
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
index a0e015c4b..99c34649f 100644
--- a/src/video_core/engines/shader_header.h
+++ b/src/video_core/engines/shader_header.h
@@ -62,7 +62,16 @@ struct Header {
INSERT_PADDING_BYTES(1); // ImapSystemValuesB
INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
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(1); // ImapReserved
INSERT_PADDING_BYTES(3); // OmapSystemValuesA
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 97b9028c5..3b7841715 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -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)};