summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_rasterizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp148
1 files changed, 97 insertions, 51 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a0527fe57..a99f2b1f9 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -33,7 +33,8 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs;
using PixelFormat = VideoCore::Surface::PixelFormat;
using SurfaceType = VideoCore::Surface::SurfaceType;
-MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Array Setup", MP_RGB(128, 128, 192));
+MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Format Setup", MP_RGB(128, 128, 192));
+MICROPROFILE_DEFINE(OpenGL_VB, "OpenGL", "Vertex Buffer Setup", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_Shader, "OpenGL", "Shader Setup", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_UBO, "OpenGL", "Const Buffer Setup", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_Index, "OpenGL", "Index Buffer Setup", MP_RGB(128, 128, 192));
@@ -79,7 +80,8 @@ struct DrawParameters {
};
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info)
- : emu_window{window}, screen_info{info}, buffer_cache(STREAM_BUFFER_SIZE) {
+ : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info},
+ buffer_cache(*this, STREAM_BUFFER_SIZE) {
// Create sampler objects
for (std::size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
@@ -122,11 +124,16 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
RasterizerOpenGL::~RasterizerOpenGL() {}
-void RasterizerOpenGL::SetupVertexArrays() {
- MICROPROFILE_SCOPE(OpenGL_VAO);
- const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
+void RasterizerOpenGL::SetupVertexFormat() {
+ auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
const auto& regs = gpu.regs;
+ if (!gpu.dirty_flags.vertex_attrib_format)
+ return;
+ gpu.dirty_flags.vertex_attrib_format = false;
+
+ MICROPROFILE_SCOPE(OpenGL_VAO);
+
auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format);
auto& VAO = iter->second;
@@ -175,8 +182,13 @@ void RasterizerOpenGL::SetupVertexArrays() {
}
}
state.draw.vertex_array = VAO.handle;
- state.draw.vertex_buffer = buffer_cache.GetHandle();
state.Apply();
+}
+
+void RasterizerOpenGL::SetupVertexBuffer() {
+ MICROPROFILE_SCOPE(OpenGL_VB);
+ const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
+ const auto& regs = gpu.regs;
// Upload all guest vertex arrays sequentially to our buffer
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
@@ -203,6 +215,9 @@ void RasterizerOpenGL::SetupVertexArrays() {
glVertexBindingDivisor(index, 0);
}
}
+
+ // Implicit set by glBindVertexBuffer. Stupid glstate handling...
+ state.draw.vertex_buffer = buffer_cache.GetHandle();
}
DrawParameters RasterizerOpenGL::SetupDraw() {
@@ -511,10 +526,10 @@ void RasterizerOpenGL::Clear() {
OpenGLState clear_state;
clear_state.draw.draw_framebuffer = framebuffer.handle;
- clear_state.color_mask.red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
- clear_state.color_mask.green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
- clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
- clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
+ clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
+ clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
+ clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
+ clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
regs.clear_buffers.A) {
@@ -573,14 +588,13 @@ void RasterizerOpenGL::DrawArrays() {
ScopeAcquireGLContext acquire_context{emu_window};
ConfigureFramebuffers();
-
+ SyncColorMask();
SyncDepthTestState();
SyncStencilTestState();
SyncBlendState();
SyncLogicOpState();
SyncCullMode();
SyncPrimitiveRestart();
- SyncDepthRange();
SyncScissorTest();
// Alpha Testing is synced on shaders.
SyncTransformFeedback();
@@ -621,7 +635,8 @@ void RasterizerOpenGL::DrawArrays() {
buffer_cache.Map(buffer_size);
- SetupVertexArrays();
+ SetupVertexFormat();
+ SetupVertexBuffer();
DrawParameters params = SetupDraw();
SetupShaders(params.primitive_mode);
@@ -899,12 +914,16 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
void RasterizerOpenGL::SyncViewport() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
- const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
-
- state.viewport.x = viewport_rect.left;
- state.viewport.y = viewport_rect.bottom;
- state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
- state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
+ for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
+ const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
+ auto& viewport = state.viewports[i];
+ viewport.x = viewport_rect.left;
+ viewport.y = viewport_rect.bottom;
+ viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth());
+ viewport.height = static_cast<GLfloat>(viewport_rect.GetHeight());
+ viewport.depth_range_far = regs.viewport[i].depth_range_far;
+ viewport.depth_range_near = regs.viewport[i].depth_range_near;
+ }
}
void RasterizerOpenGL::SyncClipEnabled() {
@@ -946,13 +965,6 @@ void RasterizerOpenGL::SyncPrimitiveRestart() {
state.primitive_restart.index = regs.primitive_restart.index;
}
-void RasterizerOpenGL::SyncDepthRange() {
- const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
-
- state.depth.depth_range_near = regs.viewport->depth_range_near;
- state.depth.depth_range_far = regs.viewport->depth_range_far;
-}
-
void RasterizerOpenGL::SyncDepthTestState() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
@@ -993,26 +1005,60 @@ void RasterizerOpenGL::SyncStencilTestState() {
state.stencil.back.write_mask = regs.stencil_back_mask;
}
-void RasterizerOpenGL::SyncBlendState() {
+void RasterizerOpenGL::SyncColorMask() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+ for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
+ const auto& source = regs.color_mask[regs.color_mask_common ? 0 : i];
+ auto& dest = state.color_mask[i];
+ dest.red_enabled = (source.R == 0) ? GL_FALSE : GL_TRUE;
+ dest.green_enabled = (source.G == 0) ? GL_FALSE : GL_TRUE;
+ dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE;
+ dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;
+ }
+}
- // TODO(Subv): Support more than just render target 0.
- state.blend.enabled = regs.blend.enable[0] != 0;
+void RasterizerOpenGL::SyncBlendState() {
+ const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
- if (!state.blend.enabled)
+ state.blend_color.red = regs.blend_color.r;
+ state.blend_color.green = regs.blend_color.g;
+ state.blend_color.blue = regs.blend_color.b;
+ state.blend_color.alpha = regs.blend_color.a;
+
+ state.independant_blend.enabled = regs.independent_blend_enable;
+ if (!state.independant_blend.enabled) {
+ auto& blend = state.blend[0];
+ blend.enabled = regs.blend.enable[0] != 0;
+ blend.separate_alpha = regs.blend.separate_alpha;
+ blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
+ blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
+ blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
+ if (blend.separate_alpha) {
+ blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
+ blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
+ blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
+ }
+ for (size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
+ state.blend[i].enabled = false;
+ }
return;
+ }
- ASSERT_MSG(regs.logic_op.enable == 0,
- "Blending and logic op can't be enabled at the same time.");
-
- ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented");
- ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented");
- state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb);
- state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_rgb);
- state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_rgb);
- state.blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_a);
- state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a);
- state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a);
+ for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
+ auto& blend = state.blend[i];
+ blend.enabled = regs.blend.enable[i] != 0;
+ if (!blend.enabled)
+ continue;
+ blend.separate_alpha = regs.independent_blend[i].separate_alpha;
+ blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_rgb);
+ blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_rgb);
+ blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_rgb);
+ if (blend.separate_alpha) {
+ blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_a);
+ blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_a);
+ blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_a);
+ }
+ }
}
void RasterizerOpenGL::SyncLogicOpState() {
@@ -1031,19 +1077,19 @@ void RasterizerOpenGL::SyncLogicOpState() {
}
void RasterizerOpenGL::SyncScissorTest() {
+ // TODO: what is the correct behavior here, a single scissor for all targets
+ // or scissor disabled for the rest of the targets?
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
-
state.scissor.enabled = (regs.scissor_test.enable != 0);
- // TODO(Blinkhawk): Figure if the hardware supports scissor testing per viewport and how it's
- // implemented.
- if (regs.scissor_test.enable != 0) {
- const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
- const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
- state.scissor.x = regs.scissor_test.min_x;
- state.scissor.y = regs.scissor_test.min_y;
- state.scissor.width = width;
- state.scissor.height = height;
+ if (regs.scissor_test.enable == 0) {
+ return;
}
+ const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
+ const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
+ state.scissor.x = regs.scissor_test.min_x;
+ state.scissor.y = regs.scissor_test.min_y;
+ state.scissor.width = width;
+ state.scissor.height = height;
}
void RasterizerOpenGL::SyncTransformFeedback() {