summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-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 83a6fd875..c0275afb5 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -82,6 +82,8 @@ union Attribute {
82 Position = 7, 82 Position = 7,
83 Attribute_0 = 8, 83 Attribute_0 = 8,
84 Attribute_31 = 39, 84 Attribute_31 = 39,
85 ClipDistances0123 = 44,
86 ClipDistances4567 = 45,
85 PointCoord = 46, 87 PointCoord = 46,
86 // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex 88 // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
87 // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval 89 // 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 {
62 INSERT_PADDING_BYTES(1); // ImapSystemValuesB 62 INSERT_PADDING_BYTES(1); // ImapSystemValuesB
63 INSERT_PADDING_BYTES(16); // ImapGenericVector[32] 63 INSERT_PADDING_BYTES(16); // ImapGenericVector[32]
64 INSERT_PADDING_BYTES(2); // ImapColor 64 INSERT_PADDING_BYTES(2); // ImapColor
65 INSERT_PADDING_BYTES(2); // ImapSystemValuesC 65 union {
66 BitField<0, 8, u16> clip_distances;
67 BitField<8, 1, u16> point_sprite_s;
68 BitField<9, 1, u16> point_sprite_t;
69 BitField<10, 1, u16> fog_coordinate;
70 BitField<12, 1, u16> tessellation_eval_point_u;
71 BitField<13, 1, u16> tessellation_eval_point_v;
72 BitField<14, 1, u16> instance_id;
73 BitField<15, 1, u16> vertex_id;
74 };
66 INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10] 75 INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10]
67 INSERT_PADDING_BYTES(1); // ImapReserved 76 INSERT_PADDING_BYTES(1); // ImapReserved
68 INSERT_PADDING_BYTES(3); // OmapSystemValuesA 77 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 90a88b91a..1ae25c7b3 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -485,27 +485,42 @@ public:
485 const Register& buf_reg) { 485 const Register& buf_reg) {
486 const std::string dest = GetOutputAttribute(attribute); 486 const std::string dest = GetOutputAttribute(attribute);
487 const std::string src = GetRegisterAsFloat(val_reg); 487 const std::string src = GetRegisterAsFloat(val_reg);
488 if (dest.empty())
489 return;
488 490
489 if (!dest.empty()) { 491 // Can happen with unknown/unimplemented output attributes, in which case we ignore the
490 // Can happen with unknown/unimplemented output attributes, in which case we ignore the 492 // instruction for now.
491 // instruction for now. 493 if (stage == Maxwell3D::Regs::ShaderStage::Geometry) {
492 if (stage == Maxwell3D::Regs::ShaderStage::Geometry) { 494 // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry
493 // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry 495 // shader. These instructions use a dirty register as buffer index, to avoid some
494 // shader. These instructions use a dirty register as buffer index, to avoid some 496 // drivers from complaining about out of boundary writes, guard them.
495 // drivers from complaining about out of boundary writes, guard them. 497 const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " +
496 const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " + 498 std::to_string(MAX_GEOMETRY_BUFFERS) + ')'};
497 std::to_string(MAX_GEOMETRY_BUFFERS) + ')'}; 499 shader.AddLine("amem[" + buf_index + "][" +
498 shader.AddLine("amem[" + buf_index + "][" + 500 std::to_string(static_cast<u32>(attribute)) + ']' + GetSwizzle(elem) +
499 std::to_string(static_cast<u32>(attribute)) + ']' + 501 " = " + src + ';');
500 GetSwizzle(elem) + " = " + src + ';'); 502 return;
501 } else { 503 }
502 if (attribute == Attribute::Index::PointSize) { 504
503 fixed_pipeline_output_attributes_used.insert(attribute); 505 switch (attribute) {
504 shader.AddLine(dest + " = " + src + ';'); 506 case Attribute::Index::ClipDistances0123:
505 } else { 507 case Attribute::Index::ClipDistances4567: {
506 shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); 508 const u64 index = attribute == Attribute::Index::ClipDistances4567 ? 4 : 0 + elem;
507 } 509 UNIMPLEMENTED_IF_MSG(
508 } 510 ((header.vtg.clip_distances >> index) & 1) == 0,
511 "Shader is setting gl_ClipDistance{} without enabling it in the header", index);
512
513 fixed_pipeline_output_attributes_used.insert(attribute);
514 shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';');
515 break;
516 }
517 case Attribute::Index::PointSize:
518 fixed_pipeline_output_attributes_used.insert(attribute);
519 shader.AddLine(dest + " = " + src + ';');
520 break;
521 default:
522 shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';');
523 break;
509 } 524 }
510 } 525 }
511 526
@@ -725,12 +740,19 @@ private:
725 void GenerateVertex() { 740 void GenerateVertex() {
726 if (stage != Maxwell3D::Regs::ShaderStage::Vertex) 741 if (stage != Maxwell3D::Regs::ShaderStage::Vertex)
727 return; 742 return;
743 bool clip_distances_declared = false;
744
728 declarations.AddLine("out gl_PerVertex {"); 745 declarations.AddLine("out gl_PerVertex {");
729 ++declarations.scope; 746 ++declarations.scope;
730 declarations.AddLine("vec4 gl_Position;"); 747 declarations.AddLine("vec4 gl_Position;");
731 for (auto& o : fixed_pipeline_output_attributes_used) { 748 for (auto& o : fixed_pipeline_output_attributes_used) {
732 if (o == Attribute::Index::PointSize) 749 if (o == Attribute::Index::PointSize)
733 declarations.AddLine("float gl_PointSize;"); 750 declarations.AddLine("float gl_PointSize;");
751 if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 ||
752 o == Attribute::Index::ClipDistances4567)) {
753 declarations.AddLine("float gl_ClipDistance[];");
754 clip_distances_declared = true;
755 }
734 } 756 }
735 --declarations.scope; 757 --declarations.scope;
736 declarations.AddLine("};"); 758 declarations.AddLine("};");
@@ -901,6 +923,10 @@ private:
901 return "gl_PointSize"; 923 return "gl_PointSize";
902 case Attribute::Index::Position: 924 case Attribute::Index::Position:
903 return "position"; 925 return "position";
926 case Attribute::Index::ClipDistances0123:
927 case Attribute::Index::ClipDistances4567: {
928 return "gl_ClipDistance";
929 }
904 default: 930 default:
905 const u32 index{static_cast<u32>(attribute) - 931 const u32 index{static_cast<u32>(attribute) -
906 static_cast<u32>(Attribute::Index::Attribute_0)}; 932 static_cast<u32>(Attribute::Index::Attribute_0)};