summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2019-11-15 12:09:19 -0500
committerGravatar GitHub2019-11-15 12:09:19 -0500
commita8295d2c533d1628887bd45d3bfd8adb66281834 (patch)
treeddfd5d15ff0a055cdd4b4aa5df85c0b2bfc56713 /src
parentMerge pull request #3091 from lioncash/core-conversion (diff)
parentgl_rasterizer: Remove front facing hack (diff)
downloadyuzu-a8295d2c533d1628887bd45d3bfd8adb66281834.tar.gz
yuzu-a8295d2c533d1628887bd45d3bfd8adb66281834.tar.xz
yuzu-a8295d2c533d1628887bd45d3bfd8adb66281834.zip
Merge pull request #3047 from ReinUsesLisp/clip-control
gl_rasterizer: Emulate viewport flipping with ARB_clip_control
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp42
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp24
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h15
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_state.h5
-rw-r--r--src/yuzu/main.cpp3
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp8
9 files changed, 50 insertions, 82 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e43ba9d6b..05f8e511b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -257,10 +257,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
257 continue; 257 continue;
258 } 258 }
259 259
260 const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5
261
262 GLShader::MaxwellUniformData ubo{}; 260 GLShader::MaxwellUniformData ubo{};
263 ubo.SetFromRegs(gpu, stage); 261 ubo.SetFromRegs(gpu);
264 const auto [buffer, offset] = 262 const auto [buffer, offset] =
265 buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); 263 buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
266 264
@@ -269,10 +267,11 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
269 267
270 Shader shader{shader_cache.GetStageProgram(program)}; 268 Shader shader{shader_cache.GetStageProgram(program)};
271 269
272 const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); 270 // Stage indices are 0 - 5
273 SetupDrawConstBuffers(stage_enum, shader); 271 const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1);
274 SetupDrawGlobalMemory(stage_enum, shader); 272 SetupDrawConstBuffers(stage, shader);
275 const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)}; 273 SetupDrawGlobalMemory(stage, shader);
274 const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)};
276 275
277 const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage}; 276 const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage};
278 const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant); 277 const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant);
@@ -1055,6 +1054,15 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
1055 } 1054 }
1056 state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0; 1055 state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;
1057 state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; 1056 state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
1057
1058 bool flip_y = false;
1059 if (regs.viewport_transform[0].scale_y < 0.0) {
1060 flip_y = !flip_y;
1061 }
1062 if (regs.screen_y_control.y_negate != 0) {
1063 flip_y = !flip_y;
1064 }
1065 state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
1058} 1066}
1059 1067
1060void RasterizerOpenGL::SyncClipEnabled( 1068void RasterizerOpenGL::SyncClipEnabled(
@@ -1077,28 +1085,14 @@ void RasterizerOpenGL::SyncClipCoef() {
1077} 1085}
1078 1086
1079void RasterizerOpenGL::SyncCullMode() { 1087void RasterizerOpenGL::SyncCullMode() {
1080 auto& maxwell3d = system.GPU().Maxwell3D(); 1088 const auto& regs = system.GPU().Maxwell3D().regs;
1081
1082 const auto& regs = maxwell3d.regs;
1083 1089
1084 state.cull.enabled = regs.cull.enabled != 0; 1090 state.cull.enabled = regs.cull.enabled != 0;
1085 if (state.cull.enabled) { 1091 if (state.cull.enabled) {
1086 state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
1087 state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); 1092 state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
1088
1089 const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 ||
1090 regs.viewport_transform[0].scale_y < 0.0f};
1091
1092 // If the GPU is configured to flip the rasterized triangles, then we need to flip the
1093 // notion of front and back. Note: We flip the triangles when the value of the register is 0
1094 // because OpenGL already does it for us.
1095 if (flip_triangles) {
1096 if (state.cull.front_face == GL_CCW)
1097 state.cull.front_face = GL_CW;
1098 else if (state.cull.front_face == GL_CW)
1099 state.cull.front_face = GL_CCW;
1100 }
1101 } 1093 }
1094
1095 state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
1102} 1096}
1103 1097
1104void RasterizerOpenGL::SyncPrimitiveRestart() { 1098void RasterizerOpenGL::SyncPrimitiveRestart() {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index e56ed51de..4f2b49170 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1892,10 +1892,6 @@ private:
1892 Expression EmitVertex(Operation operation) { 1892 Expression EmitVertex(Operation operation) {
1893 ASSERT_MSG(stage == ProgramType::Geometry, 1893 ASSERT_MSG(stage == ProgramType::Geometry,
1894 "EmitVertex is expected to be used in a geometry shader."); 1894 "EmitVertex is expected to be used in a geometry shader.");
1895
1896 // If a geometry shader is attached, it will always flip (it's the last stage before
1897 // fragment). For more info about flipping, refer to gl_shader_gen.cpp.
1898 code.AddLine("gl_Position.xy *= viewport_flip.xy;");
1899 code.AddLine("EmitVertex();"); 1895 code.AddLine("EmitVertex();");
1900 return {}; 1896 return {};
1901 } 1897 }
@@ -1903,14 +1899,12 @@ private:
1903 Expression EndPrimitive(Operation operation) { 1899 Expression EndPrimitive(Operation operation) {
1904 ASSERT_MSG(stage == ProgramType::Geometry, 1900 ASSERT_MSG(stage == ProgramType::Geometry,
1905 "EndPrimitive is expected to be used in a geometry shader."); 1901 "EndPrimitive is expected to be used in a geometry shader.");
1906
1907 code.AddLine("EndPrimitive();"); 1902 code.AddLine("EndPrimitive();");
1908 return {}; 1903 return {};
1909 } 1904 }
1910 1905
1911 Expression YNegate(Operation operation) { 1906 Expression YNegate(Operation operation) {
1912 // Config pack's third value is Y_NEGATE's state. 1907 return {"y_direction", Type::Float};
1913 return {"config_pack[2]", Type::Uint};
1914 } 1908 }
1915 1909
1916 template <u32 element> 1910 template <u32 element>
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 0e22eede9..af17216bd 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -20,8 +20,7 @@ std::string GenerateVertexShader(const Device& device, const ShaderIR& ir, const
20 std::string out = GetCommonDeclarations(); 20 std::string out = GetCommonDeclarations();
21 out += R"( 21 out += R"(
22layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { 22layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
23 vec4 viewport_flip; 23 float y_direction;
24 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
25}; 24};
26 25
27)"; 26)";
@@ -35,23 +34,10 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
35void main() { 34void main() {
36 execute_vertex(); 35 execute_vertex();
37)"; 36)";
38
39 if (ir_b) { 37 if (ir_b) {
40 out += " execute_vertex_b();"; 38 out += " execute_vertex_b();";
41 } 39 }
42 40 out += "}\n";
43 out += R"(
44
45 // Set Position Y direction
46 gl_Position.y *= utof(config_pack[2]);
47 // Check if the flip stage is VertexB
48 // Config pack's second value is flip_stage
49 if (config_pack[1] == 1) {
50 // Viewport can be flipped, which is unsupported by glViewport
51 gl_Position.xy *= viewport_flip.xy;
52 }
53}
54)";
55 return out; 41 return out;
56} 42}
57 43
@@ -59,8 +45,7 @@ std::string GenerateGeometryShader(const Device& device, const ShaderIR& ir) {
59 std::string out = GetCommonDeclarations(); 45 std::string out = GetCommonDeclarations();
60 out += R"( 46 out += R"(
61layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { 47layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
62 vec4 viewport_flip; 48 float y_direction;
63 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
64}; 49};
65 50
66)"; 51)";
@@ -87,8 +72,7 @@ layout (location = 6) out vec4 FragColor6;
87layout (location = 7) out vec4 FragColor7; 72layout (location = 7) out vec4 FragColor7;
88 73
89layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { 74layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
90 vec4 viewport_flip; 75 float y_direction;
91 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
92}; 76};
93 77
94)"; 78)";
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index b05f90f20..75d3fac04 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -40,27 +40,11 @@ void ProgramManager::UpdatePipeline() {
40 old_state = current_state; 40 old_state = current_state;
41} 41}
42 42
43void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { 43void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {
44 const auto& regs = maxwell.regs; 44 const auto& regs = maxwell.regs;
45 const auto& state = maxwell.state;
46
47 // TODO(bunnei): Support more than one viewport
48 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
49 viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
50
51 instance_id = state.current_instance;
52
53 // Assign in which stage the position has to be flipped
54 // (the last stage before the fragment shader).
55 constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
56 if (maxwell.regs.shader_config[geometry_index].enable) {
57 flip_stage = geometry_index;
58 } else {
59 flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
60 }
61 45
62 // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. 46 // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
63 y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f; 47 y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f;
64} 48}
65 49
66} // namespace OpenGL::GLShader 50} // namespace OpenGL::GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 6961e702a..3703e7018 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -18,17 +18,12 @@ namespace OpenGL::GLShader {
18/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at 18/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
19/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. 19/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
20/// Not following that rule will cause problems on some AMD drivers. 20/// Not following that rule will cause problems on some AMD drivers.
21struct MaxwellUniformData { 21struct alignas(16) MaxwellUniformData {
22 void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage); 22 void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell);
23 23
24 alignas(16) GLvec4 viewport_flip; 24 GLfloat y_direction;
25 struct alignas(16) {
26 GLuint instance_id;
27 GLuint flip_stage;
28 GLfloat y_direction;
29 };
30}; 25};
31static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect"); 26static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
32static_assert(sizeof(MaxwellUniformData) < 16384, 27static_assert(sizeof(MaxwellUniformData) < 16384,
33 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); 28 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
34 29
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index f25148362..ccbe5912e 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -410,6 +410,12 @@ void OpenGLState::ApplyAlphaTest() {
410 } 410 }
411} 411}
412 412
413void OpenGLState::ApplyClipControl() {
414 if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) {
415 glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE);
416 }
417}
418
413void OpenGLState::ApplyTextures() { 419void OpenGLState::ApplyTextures() {
414 if (const auto update = UpdateArray(cur_state.textures, textures)) { 420 if (const auto update = UpdateArray(cur_state.textures, textures)) {
415 glBindTextures(update->first, update->second, textures.data() + update->first); 421 glBindTextures(update->first, update->second, textures.data() + update->first);
@@ -453,6 +459,7 @@ void OpenGLState::Apply() {
453 ApplyImages(); 459 ApplyImages();
454 ApplyPolygonOffset(); 460 ApplyPolygonOffset();
455 ApplyAlphaTest(); 461 ApplyAlphaTest();
462 ApplyClipControl();
456} 463}
457 464
458void OpenGLState::EmulateViewportWithScissor() { 465void OpenGLState::EmulateViewportWithScissor() {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index cca25206b..eaff22bda 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -146,6 +146,10 @@ public:
146 146
147 std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE 147 std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE
148 148
149 struct {
150 GLenum origin = GL_LOWER_LEFT;
151 } clip_control;
152
149 OpenGLState(); 153 OpenGLState();
150 154
151 /// Get the currently active OpenGL state 155 /// Get the currently active OpenGL state
@@ -182,6 +186,7 @@ public:
182 void ApplyDepthClamp(); 186 void ApplyDepthClamp();
183 void ApplyPolygonOffset(); 187 void ApplyPolygonOffset();
184 void ApplyAlphaTest(); 188 void ApplyAlphaTest();
189 void ApplyClipControl();
185 190
186 /// Resets any references to the given resource 191 /// Resets any references to the given resource
187 OpenGLState& UnbindTexture(GLuint handle); 192 OpenGLState& UnbindTexture(GLuint handle);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 160613ee1..867f8e913 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -817,6 +817,9 @@ QStringList GMainWindow::GetUnsupportedGLExtensions() {
817 if (!GLAD_GL_ARB_multi_bind) { 817 if (!GLAD_GL_ARB_multi_bind) {
818 unsupported_ext.append(QStringLiteral("ARB_multi_bind")); 818 unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
819 } 819 }
820 if (!GLAD_GL_ARB_clip_control) {
821 unsupported_ext.append(QStringLiteral("ARB_clip_control"));
822 }
820 823
821 // Extensions required to support some texture formats. 824 // Extensions required to support some texture formats.
822 if (!GLAD_GL_EXT_texture_compression_s3tc) { 825 if (!GLAD_GL_EXT_texture_compression_s3tc) {
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index f91b071bf..6fde694a2 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -50,7 +50,7 @@ private:
50}; 50};
51 51
52bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { 52bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
53 std::vector<std::string> unsupported_ext; 53 std::vector<std::string_view> unsupported_ext;
54 54
55 if (!GLAD_GL_ARB_buffer_storage) 55 if (!GLAD_GL_ARB_buffer_storage)
56 unsupported_ext.push_back("ARB_buffer_storage"); 56 unsupported_ext.push_back("ARB_buffer_storage");
@@ -62,6 +62,8 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
62 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge"); 62 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
63 if (!GLAD_GL_ARB_multi_bind) 63 if (!GLAD_GL_ARB_multi_bind)
64 unsupported_ext.push_back("ARB_multi_bind"); 64 unsupported_ext.push_back("ARB_multi_bind");
65 if (!GLAD_GL_ARB_clip_control)
66 unsupported_ext.push_back("ARB_clip_control");
65 67
66 // Extensions required to support some texture formats. 68 // Extensions required to support some texture formats.
67 if (!GLAD_GL_EXT_texture_compression_s3tc) 69 if (!GLAD_GL_EXT_texture_compression_s3tc)
@@ -71,8 +73,8 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
71 if (!GLAD_GL_ARB_depth_buffer_float) 73 if (!GLAD_GL_ARB_depth_buffer_float)
72 unsupported_ext.push_back("ARB_depth_buffer_float"); 74 unsupported_ext.push_back("ARB_depth_buffer_float");
73 75
74 for (const std::string& ext : unsupported_ext) 76 for (const auto& extension : unsupported_ext)
75 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext); 77 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension);
76 78
77 return unsupported_ext.empty(); 79 return unsupported_ext.empty();
78} 80}