summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-11-11 08:28:20 -0800
committerGravatar GitHub2018-11-11 08:28:20 -0800
commiteaee73f95d4785c36a7e81f1f087e0be52de7e17 (patch)
tree7350b90238e7fc2325bb8ca1eeab34858c2b595b /src
parentMerge pull request #1663 from lioncash/raster (diff)
parentgl_shader_decompiler: Guard out of bound geometry shader input reads (diff)
downloadyuzu-eaee73f95d4785c36a7e81f1f087e0be52de7e17.tar.gz
yuzu-eaee73f95d4785c36a7e81f1f087e0be52de7e17.tar.xz
yuzu-eaee73f95d4785c36a7e81f1f087e0be52de7e17.zip
Merge pull request #1669 from ReinUsesLisp/fixup-gs
gl_shader_decompiler: Guard out of bound geometry shader input reads
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h13
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp4
4 files changed, 24 insertions, 15 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index d7fb50a85..a85a7c0c5 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -121,12 +121,16 @@ GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) {
121} 121}
122 122
123GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, 123GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program,
124 const std::string& glsl_topology, 124 const std::string& glsl_topology, u32 max_vertices,
125 const std::string& debug_name) { 125 const std::string& debug_name) {
126 if (target_program.handle != 0) { 126 if (target_program.handle != 0) {
127 return target_program.handle; 127 return target_program.handle;
128 } 128 }
129 const std::string source{geometry_programs.code + "layout (" + glsl_topology + ") in;\n"}; 129 std::string source = "#version 430 core\n";
130 source += "layout (" + glsl_topology + ") in;\n";
131 source += "#define MAX_VERTEX_INPUT " + std::to_string(max_vertices) + '\n';
132 source += geometry_programs.code;
133
130 OGLShader shader; 134 OGLShader shader;
131 shader.Create(source.c_str(), GL_GEOMETRY_SHADER); 135 shader.Create(source.c_str(), GL_GEOMETRY_SHADER);
132 target_program.Create(true, shader.handle); 136 target_program.Create(true, shader.handle);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 016ab18f9..ffbf21831 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -48,22 +48,23 @@ public:
48 } 48 }
49 switch (primitive_mode) { 49 switch (primitive_mode) {
50 case GL_POINTS: 50 case GL_POINTS:
51 return LazyGeometryProgram(geometry_programs.points, "points", "ShaderPoints"); 51 return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints");
52 case GL_LINES: 52 case GL_LINES:
53 case GL_LINE_STRIP: 53 case GL_LINE_STRIP:
54 return LazyGeometryProgram(geometry_programs.lines, "lines", "ShaderLines"); 54 return LazyGeometryProgram(geometry_programs.lines, "lines", 2, "ShaderLines");
55 case GL_LINES_ADJACENCY: 55 case GL_LINES_ADJACENCY:
56 case GL_LINE_STRIP_ADJACENCY: 56 case GL_LINE_STRIP_ADJACENCY:
57 return LazyGeometryProgram(geometry_programs.lines_adjacency, "lines_adjacency", 57 return LazyGeometryProgram(geometry_programs.lines_adjacency, "lines_adjacency", 4,
58 "ShaderLinesAdjacency"); 58 "ShaderLinesAdjacency");
59 case GL_TRIANGLES: 59 case GL_TRIANGLES:
60 case GL_TRIANGLE_STRIP: 60 case GL_TRIANGLE_STRIP:
61 case GL_TRIANGLE_FAN: 61 case GL_TRIANGLE_FAN:
62 return LazyGeometryProgram(geometry_programs.triangles, "triangles", "ShaderTriangles"); 62 return LazyGeometryProgram(geometry_programs.triangles, "triangles", 3,
63 "ShaderTriangles");
63 case GL_TRIANGLES_ADJACENCY: 64 case GL_TRIANGLES_ADJACENCY:
64 case GL_TRIANGLE_STRIP_ADJACENCY: 65 case GL_TRIANGLE_STRIP_ADJACENCY:
65 return LazyGeometryProgram(geometry_programs.triangles_adjacency, "triangles_adjacency", 66 return LazyGeometryProgram(geometry_programs.triangles_adjacency, "triangles_adjacency",
66 "ShaderLines"); 67 6, "ShaderTrianglesAdjacency");
67 default: 68 default:
68 UNREACHABLE_MSG("Unknown primitive mode."); 69 UNREACHABLE_MSG("Unknown primitive mode.");
69 } 70 }
@@ -78,7 +79,7 @@ public:
78private: 79private:
79 /// Generates a geometry shader or returns one that already exists. 80 /// Generates a geometry shader or returns one that already exists.
80 GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology, 81 GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
81 const std::string& debug_name); 82 u32 max_vertices, const std::string& debug_name);
82 83
83 VAddr addr; 84 VAddr addr;
84 Maxwell::ShaderProgram program_type; 85 Maxwell::ShaderProgram program_type;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index f6a879a7b..5fde22ad4 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -494,10 +494,10 @@ public:
494 // instruction for now. 494 // instruction for now.
495 if (stage == Maxwell3D::Regs::ShaderStage::Geometry) { 495 if (stage == Maxwell3D::Regs::ShaderStage::Geometry) {
496 // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry 496 // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry
497 // shader. These instructions use a dirty register as buffer index. To avoid some 497 // shader. These instructions use a dirty register as buffer index, to avoid some
498 // drivers from complaining for the out of boundary writes, guard them. 498 // drivers from complaining about out of boundary writes, guard them.
499 const std::string buf_index{"min(" + GetRegisterAsInteger(buf_reg) + ", " + 499 const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " +
500 std::to_string(MAX_GEOMETRY_BUFFERS - 1) + ')'}; 500 std::to_string(MAX_GEOMETRY_BUFFERS) + ')'};
501 shader.AddLine("amem[" + buf_index + "][" + 501 shader.AddLine("amem[" + buf_index + "][" +
502 std::to_string(static_cast<u32>(attribute)) + ']' + 502 std::to_string(static_cast<u32>(attribute)) + ']' +
503 GetSwizzle(elem) + " = " + src + ';'); 503 GetSwizzle(elem) + " = " + src + ';');
@@ -811,7 +811,11 @@ private:
811 std::optional<Register> vertex = {}) { 811 std::optional<Register> vertex = {}) {
812 auto GeometryPass = [&](const std::string& name) { 812 auto GeometryPass = [&](const std::string& name) {
813 if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) { 813 if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) {
814 return "gs_" + name + '[' + GetRegisterAsInteger(*vertex, 0, false) + ']'; 814 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games set
815 // an 0x80000000 index for those and the shader fails to build. Find out why this
816 // happens and what's its intent.
817 return "gs_" + name + '[' + GetRegisterAsInteger(*vertex, 0, false) +
818 " % MAX_VERTEX_INPUT]";
815 } 819 }
816 return name; 820 return name;
817 }; 821 };
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 9d17edd63..eea090e52 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -82,8 +82,8 @@ void main() {
82} 82}
83 83
84ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { 84ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
85 std::string out = "#version 430 core\n"; 85 // Version is intentionally skipped in shader generation, it's added by the lazy compilation.
86 out += "#extension GL_ARB_separate_shader_objects : enable\n\n"; 86 std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
87 out += Decompiler::GetCommonDeclarations(); 87 out += Decompiler::GetCommonDeclarations();
88 out += "bool exec_geometry();\n"; 88 out += "bool exec_geometry();\n";
89 89