summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorRodrigo Locatti <reinuseslisp@airmail.cc>2020-03-13 20:44:06 +0100
committerGitHub <noreply@github.com>2020-03-13 20:44:06 +0100
commit244fe132199cb3c67dd9e612d2be856895f8a868 (patch)
treed0f968d06b2bbc6e378a5a0632cd2d6322fe4e6d /src/video_core/renderer_opengl
parentgl_shader_decompiler: Initialize gl_Position on vertex shaders (diff)
parentMerge pull request #3491 from ReinUsesLisp/polygon-modes (diff)
downloadyuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar.gz
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar.bz2
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar.lz
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar.xz
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.tar.zst
yuzu-244fe132199cb3c67dd9e612d2be856895f8a868.zip
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp44
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp31
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h29
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.h11
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h13
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp5
8 files changed, 118 insertions, 28 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 385a31ef6..8a2db8e36 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -484,6 +484,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
SyncViewport();
SyncRasterizeEnable();
+ SyncPolygonModes();
SyncColorMask();
SyncFragmentColorClampState();
SyncMultiSampleState();
@@ -562,7 +563,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
bind_ubo_pushbuffer.Bind();
bind_ssbo_pushbuffer.Bind();
- program_manager.Update();
+ program_manager.BindGraphicsPipeline();
if (texture_cache.TextureBarrier()) {
glTextureBarrier();
@@ -619,7 +620,7 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
auto kernel = shader_cache.GetComputeKernel(code_addr);
SetupComputeTextures(kernel);
SetupComputeImages(kernel);
- glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, kernel->GetHandle());
+ program_manager.BindComputeShader(kernel->GetHandle());
const std::size_t buffer_size =
Tegra::Engines::KeplerCompute::NumConstBuffers *
@@ -1089,6 +1090,45 @@ void RasterizerOpenGL::SyncRasterizeEnable() {
oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0);
}
+void RasterizerOpenGL::SyncPolygonModes() {
+ auto& gpu = system.GPU().Maxwell3D();
+ auto& flags = gpu.dirty.flags;
+ if (!flags[Dirty::PolygonModes]) {
+ return;
+ }
+ flags[Dirty::PolygonModes] = false;
+
+ if (gpu.regs.fill_rectangle) {
+ if (!GLAD_GL_NV_fill_rectangle) {
+ LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ return;
+ }
+
+ flags[Dirty::PolygonModeFront] = true;
+ flags[Dirty::PolygonModeBack] = true;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
+ return;
+ }
+
+ if (gpu.regs.polygon_mode_front == gpu.regs.polygon_mode_back) {
+ flags[Dirty::PolygonModeFront] = false;
+ flags[Dirty::PolygonModeBack] = false;
+ glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
+ return;
+ }
+
+ if (flags[Dirty::PolygonModeFront]) {
+ flags[Dirty::PolygonModeFront] = false;
+ glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
+ }
+
+ if (flags[Dirty::PolygonModeBack]) {
+ flags[Dirty::PolygonModeBack] = false;
+ glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_back));
+ }
+}
+
void RasterizerOpenGL::SyncColorMask() {
auto& gpu = system.GPU().Maxwell3D();
auto& flags = gpu.dirty.flags;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index e83c5ebdc..e6424f5d2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -177,6 +177,9 @@ private:
/// Syncs the rasterizer enable state to match the guest state
void SyncRasterizeEnable();
+ /// Syncs polygon modes to match the guest state
+ void SyncPolygonModes();
+
/// Syncs Color Mask
void SyncColorMask();
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 15f3cd066..9c7b0adbd 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -2,21 +2,29 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <glad/glad.h>
+
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
namespace OpenGL::GLShader {
-using Tegra::Engines::Maxwell3D;
+ProgramManager::ProgramManager() = default;
ProgramManager::~ProgramManager() = default;
void ProgramManager::Create() {
- pipeline.Create();
+ graphics_pipeline.Create();
+ glBindProgramPipeline(graphics_pipeline.handle);
}
-void ProgramManager::Update() {
+void ProgramManager::BindGraphicsPipeline() {
+ if (!is_graphics_bound) {
+ is_graphics_bound = true;
+ glUseProgram(0);
+ }
+
// Avoid updating the pipeline when values have no changed
if (old_state == current_state) {
return;
@@ -25,16 +33,21 @@ void ProgramManager::Update() {
// Workaround for AMD bug
static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT |
GL_FRAGMENT_SHADER_BIT};
- glUseProgramStages(pipeline.handle, all_used_stages, 0);
-
- glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader);
- glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader);
- glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader);
+ const GLuint handle = graphics_pipeline.handle;
+ glUseProgramStages(handle, all_used_stages, 0);
+ glUseProgramStages(handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader);
+ glUseProgramStages(handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader);
+ glUseProgramStages(handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader);
old_state = current_state;
}
-void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {
+void ProgramManager::BindComputeShader(GLuint program) {
+ is_graphics_bound = false;
+ glUseProgram(program);
+}
+
+void MaxwellUniformData::SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell) {
const auto& regs = maxwell.regs;
// Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index e94cd75aa..d2e47f2a9 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -28,11 +28,16 @@ static_assert(sizeof(MaxwellUniformData) < 16384,
class ProgramManager {
public:
+ explicit ProgramManager();
~ProgramManager();
void Create();
- void Update();
+ /// Updates the graphics pipeline and binds it.
+ void BindGraphicsPipeline();
+
+ /// Binds a compute shader.
+ void BindComputeShader(GLuint program);
void UseVertexShader(GLuint program) {
current_state.vertex_shader = program;
@@ -46,33 +51,27 @@ public:
current_state.fragment_shader = program;
}
- GLuint GetHandle() const {
- return pipeline.handle;
- }
-
- void UseTrivialFragmentShader() {
- current_state.fragment_shader = 0;
- }
-
private:
struct PipelineState {
- bool operator==(const PipelineState& rhs) const {
+ bool operator==(const PipelineState& rhs) const noexcept {
return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader &&
geometry_shader == rhs.geometry_shader;
}
- bool operator!=(const PipelineState& rhs) const {
+ bool operator!=(const PipelineState& rhs) const noexcept {
return !operator==(rhs);
}
- GLuint vertex_shader{};
- GLuint fragment_shader{};
- GLuint geometry_shader{};
+ GLuint vertex_shader = 0;
+ GLuint fragment_shader = 0;
+ GLuint geometry_shader = 0;
};
- OGLPipeline pipeline;
+ OGLPipeline graphics_pipeline;
+ OGLPipeline compute_pipeline;
PipelineState current_state;
PipelineState old_state;
+ bool is_graphics_bound = true;
};
} // namespace OpenGL::GLShader
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index 1e43c9ec0..3f3bdf812 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -94,6 +94,15 @@ void SetupDirtyShaders(Tables& tables) {
Shaders);
}
+void SetupDirtyPolygonModes(Tables& tables) {
+ tables[0][OFF(polygon_mode_front)] = PolygonModeFront;
+ tables[0][OFF(polygon_mode_back)] = PolygonModeBack;
+
+ tables[1][OFF(polygon_mode_front)] = PolygonModes;
+ tables[1][OFF(polygon_mode_back)] = PolygonModes;
+ tables[0][OFF(fill_rectangle)] = PolygonModes;
+}
+
void SetupDirtyDepthTest(Tables& tables) {
auto& table = tables[0];
table[OFF(depth_test_enable)] = DepthTest;
@@ -211,6 +220,7 @@ void StateTracker::Initialize() {
SetupDirtyVertexArrays(tables);
SetupDirtyVertexFormat(tables);
SetupDirtyShaders(tables);
+ SetupDirtyPolygonModes(tables);
SetupDirtyDepthTest(tables);
SetupDirtyStencilTest(tables);
SetupDirtyAlphaTest(tables);
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h
index e08482911..b882d75c3 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.h
+++ b/src/video_core/renderer_opengl/gl_state_tracker.h
@@ -59,6 +59,10 @@ enum : u8 {
Shaders,
ClipDistances,
+ PolygonModes,
+ PolygonModeFront,
+ PolygonModeBack,
+
ColorMask,
FrontFace,
CullTest,
@@ -111,6 +115,13 @@ public:
flags[OpenGL::Dirty::VertexInstance0 + 1] = true;
}
+ void NotifyPolygonModes() {
+ auto& flags = system.GPU().Maxwell3D().dirty.flags;
+ flags[OpenGL::Dirty::PolygonModes] = true;
+ flags[OpenGL::Dirty::PolygonModeFront] = true;
+ flags[OpenGL::Dirty::PolygonModeBack] = true;
+ }
+
void NotifyViewport0() {
auto& flags = system.GPU().Maxwell3D().dirty.flags;
flags[OpenGL::Dirty::Viewports] = true;
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 494e38e7a..89f0e04ef 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -488,5 +488,18 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
return GL_COPY;
}
+inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) {
+ switch (polygon_mode) {
+ case Maxwell::PolygonMode::Point:
+ return GL_POINT;
+ case Maxwell::PolygonMode::Line:
+ return GL_LINE;
+ case Maxwell::PolygonMode::Fill:
+ return GL_FILL;
+ }
+ UNREACHABLE_MSG("Invalid polygon mode={}", static_cast<int>(polygon_mode));
+ return GL_FILL;
+}
+
} // namespace MaxwellToGL
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a51410660..12333e8c9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -443,7 +443,6 @@ void RendererOpenGL::InitOpenGLObjects() {
// Create program pipeline
program_manager.Create();
- glBindProgramPipeline(program_manager.GetHandle());
// Generate VBO handle for drawing
vertex_buffer.Create();
@@ -577,6 +576,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
// TODO: Signal state tracker about these changes
state_tracker.NotifyScreenDrawVertexArray();
+ state_tracker.NotifyPolygonModes();
state_tracker.NotifyViewport0();
state_tracker.NotifyScissor0();
state_tracker.NotifyColorMask0();
@@ -596,7 +596,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
program_manager.UseVertexShader(vertex_program.handle);
program_manager.UseGeometryShader(0);
program_manager.UseFragmentShader(fragment_program.handle);
- program_manager.Update();
+ program_manager.BindGraphicsPipeline();
glEnable(GL_CULL_FACE);
if (screen_info.display_srgb) {
@@ -612,6 +612,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
glDisable(GL_ALPHA_TEST);
glDisablei(GL_BLEND, 0);
glDisablei(GL_SCISSOR_TEST, 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);