summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp50
-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.cpp19
-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.cpp2
9 files changed, 57 insertions, 76 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e560d70d5..53ee754ff 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) {
continue;
}
- const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5
-
GLShader::MaxwellUniformData ubo{};
- ubo.SetFromRegs(gpu, stage);
+ ubo.SetFromRegs(gpu);
const auto [buffer, offset] =
buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
@@ -269,10 +267,11 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
Shader shader{shader_cache.GetStageProgram(program)};
- const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage);
- SetupDrawConstBuffers(stage_enum, shader);
- SetupDrawGlobalMemory(stage_enum, shader);
- const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)};
+ // Stage indices are 0 - 5
+ const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1);
+ SetupDrawConstBuffers(stage, shader);
+ SetupDrawGlobalMemory(stage, shader);
+ const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)};
const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage};
const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant);
@@ -1055,6 +1054,15 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
}
state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;
state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
+
+ bool flip_y = false;
+ if (regs.viewport_transform[0].scale_y < 0.0) {
+ flip_y = !flip_y;
+ }
+ if (regs.screen_y_control.y_negate != 0) {
+ flip_y = !flip_y;
+ }
+ state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
}
void RasterizerOpenGL::SyncClipEnabled(
@@ -1077,26 +1085,24 @@ void RasterizerOpenGL::SyncClipCoef() {
}
void RasterizerOpenGL::SyncCullMode() {
- auto& maxwell3d = system.GPU().Maxwell3D();
-
- const auto& regs = maxwell3d.regs;
+ const auto& regs = system.GPU().Maxwell3D().regs;
state.cull.enabled = regs.cull.enabled != 0;
if (state.cull.enabled) {
- state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
+ }
+
+ state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
- const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 ||
- regs.viewport_transform[0].scale_y < 0.0f};
-
- // If the GPU is configured to flip the rasterized triangles, then we need to flip the
- // notion of front and back. Note: We flip the triangles when the value of the register is 0
- // because OpenGL already does it for us.
- if (flip_triangles) {
- if (state.cull.front_face == GL_CCW)
- state.cull.front_face = GL_CW;
- else if (state.cull.front_face == GL_CW)
- state.cull.front_face = GL_CCW;
+ // If the GPU is configured to flip the rasterized triangles, then we need to flip the
+ // notion of front and back.
+ const bool flip_triangles{regs.screen_y_control.triangle_rast_flip != 0 &&
+ regs.viewport_transform[0].scale_y > 0.0f};
+ if (flip_triangles) {
+ if (state.cull.front_face == GL_CCW) {
+ state.cull.front_face = GL_CW;
+ } else if (state.cull.front_face == GL_CW) {
+ state.cull.front_face = GL_CCW;
}
}
}
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 92ee8459e..8dcbeefc0 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1872,10 +1872,6 @@ private:
Expression EmitVertex(Operation operation) {
ASSERT_MSG(stage == ProgramType::Geometry,
"EmitVertex is expected to be used in a geometry shader.");
-
- // If a geometry shader is attached, it will always flip (it's the last stage before
- // fragment). For more info about flipping, refer to gl_shader_gen.cpp.
- code.AddLine("gl_Position.xy *= viewport_flip.xy;");
code.AddLine("EmitVertex();");
return {};
}
@@ -1883,14 +1879,12 @@ private:
Expression EndPrimitive(Operation operation) {
ASSERT_MSG(stage == ProgramType::Geometry,
"EndPrimitive is expected to be used in a geometry shader.");
-
code.AddLine("EndPrimitive();");
return {};
}
Expression YNegate(Operation operation) {
- // Config pack's third value is Y_NEGATE's state.
- return {"config_pack[2]", Type::Uint};
+ return {"y_negate", Type::Float};
}
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
std::string out = GetCommonDeclarations();
out += R"(
layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
- vec4 viewport_flip;
- uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
+ float y_direction;
};
)";
@@ -35,23 +34,10 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
void main() {
execute_vertex();
)";
-
if (ir_b) {
out += " execute_vertex_b();";
}
-
- out += R"(
-
- // Set Position Y direction
- gl_Position.y *= utof(config_pack[2]);
- // Check if the flip stage is VertexB
- // Config pack's second value is flip_stage
- if (config_pack[1] == 1) {
- // Viewport can be flipped, which is unsupported by glViewport
- gl_Position.xy *= viewport_flip.xy;
- }
-}
-)";
+ out += "}\n";
return out;
}
@@ -59,8 +45,7 @@ std::string GenerateGeometryShader(const Device& device, const ShaderIR& ir) {
std::string out = GetCommonDeclarations();
out += R"(
layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
- vec4 viewport_flip;
- uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
+ float y_direction;
};
)";
@@ -87,8 +72,7 @@ layout (location = 6) out vec4 FragColor6;
layout (location = 7) out vec4 FragColor7;
layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
- vec4 viewport_flip;
- uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
+ float y_direction;
};
)";
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index b05f90f20..cd729d978 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -40,27 +40,12 @@ void ProgramManager::UpdatePipeline() {
old_state = current_state;
}
-void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) {
+void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {
const auto& regs = maxwell.regs;
const auto& state = maxwell.state;
- // TODO(bunnei): Support more than one viewport
- viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
- viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
-
- instance_id = state.current_instance;
-
- // Assign in which stage the position has to be flipped
- // (the last stage before the fragment shader).
- constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
- if (maxwell.regs.shader_config[geometry_index].enable) {
- flip_stage = geometry_index;
- } else {
- flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
- }
-
// Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
- y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f;
+ y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f;
}
} // 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 {
/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
/// Not following that rule will cause problems on some AMD drivers.
-struct MaxwellUniformData {
- void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage);
-
- alignas(16) GLvec4 viewport_flip;
- struct alignas(16) {
- GLuint instance_id;
- GLuint flip_stage;
- GLfloat y_direction;
- };
+struct alignas(16) MaxwellUniformData {
+ void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell);
+
+ GLfloat y_direction;
};
-static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect");
+static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
static_assert(sizeof(MaxwellUniformData) < 16384,
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
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() {
}
}
+void OpenGLState::ApplyClipControl() {
+ if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) {
+ glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE);
+ }
+}
+
void OpenGLState::ApplyTextures() {
if (const auto update = UpdateArray(cur_state.textures, textures)) {
glBindTextures(update->first, update->second, textures.data() + update->first);
@@ -453,6 +459,7 @@ void OpenGLState::Apply() {
ApplyImages();
ApplyPolygonOffset();
ApplyAlphaTest();
+ ApplyClipControl();
}
void 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:
std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE
+ struct {
+ GLenum origin = GL_LOWER_LEFT;
+ } clip_control;
+
OpenGLState();
/// Get the currently active OpenGL state
@@ -182,6 +186,7 @@ public:
void ApplyDepthClamp();
void ApplyPolygonOffset();
void ApplyAlphaTest();
+ void ApplyClipControl();
/// Resets any references to the given resource
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() {
if (!GLAD_GL_ARB_multi_bind) {
unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
}
+ if (!GLAD_GL_ARB_clip_control) {
+ unsupported_ext.append(QStringLiteral("ARB_clip_control"));
+ }
// Extensions required to support some texture formats.
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..075a7074f 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -62,6 +62,8 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
if (!GLAD_GL_ARB_multi_bind)
unsupported_ext.push_back("ARB_multi_bind");
+ if (!GLAD_GL_ARB_clip_control)
+ unsupported_ext.push_back("ARB_clip_control");
// Extensions required to support some texture formats.
if (!GLAD_GL_EXT_texture_compression_s3tc)