|
@@ -105,6 +105,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
|
|
|
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
|
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
|
|
state.draw.shader_program = 0;
|
|
state.draw.shader_program = 0;
|
|
|
state.Apply();
|
|
state.Apply();
|
|
|
|
|
+ clear_framebuffer.Create();
|
|
|
|
|
|
|
|
LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
|
|
LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
|
|
|
CheckExtensions();
|
|
CheckExtensions();
|
|
@@ -124,10 +125,10 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
|
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
|
const auto& regs = gpu.regs;
|
|
const auto& regs = gpu.regs;
|
|
|
|
|
|
|
|
- if (!gpu.dirty_flags.vertex_attrib_format) {
|
|
|
|
|
|
|
+ if (!gpu.dirty.vertex_attrib_format) {
|
|
|
return state.draw.vertex_array;
|
|
return state.draw.vertex_array;
|
|
|
}
|
|
}
|
|
|
- gpu.dirty_flags.vertex_attrib_format = false;
|
|
|
|
|
|
|
+ gpu.dirty.vertex_attrib_format = false;
|
|
|
|
|
|
|
|
MICROPROFILE_SCOPE(OpenGL_VAO);
|
|
MICROPROFILE_SCOPE(OpenGL_VAO);
|
|
|
|
|
|
|
@@ -181,7 +182,7 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Rebinding the VAO invalidates the vertex buffer bindings.
|
|
// Rebinding the VAO invalidates the vertex buffer bindings.
|
|
|
- gpu.dirty_flags.vertex_array.set();
|
|
|
|
|
|
|
+ gpu.dirty.ResetVertexArrays();
|
|
|
|
|
|
|
|
state.draw.vertex_array = vao_entry.handle;
|
|
state.draw.vertex_array = vao_entry.handle;
|
|
|
return vao_entry.handle;
|
|
return vao_entry.handle;
|
|
@@ -189,17 +190,20 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
|
- const auto& regs = gpu.regs;
|
|
|
|
|
-
|
|
|
|
|
- if (gpu.dirty_flags.vertex_array.none())
|
|
|
|
|
|
|
+ if (!gpu.dirty.vertex_array_buffers)
|
|
|
return;
|
|
return;
|
|
|
|
|
+ gpu.dirty.vertex_array_buffers = false;
|
|
|
|
|
+
|
|
|
|
|
+ const auto& regs = gpu.regs;
|
|
|
|
|
|
|
|
MICROPROFILE_SCOPE(OpenGL_VB);
|
|
MICROPROFILE_SCOPE(OpenGL_VB);
|
|
|
|
|
|
|
|
// Upload all guest vertex arrays sequentially to our buffer
|
|
// Upload all guest vertex arrays sequentially to our buffer
|
|
|
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
|
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
|
|
- if (!gpu.dirty_flags.vertex_array[index])
|
|
|
|
|
|
|
+ if (!gpu.dirty.vertex_array[index])
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ gpu.dirty.vertex_array[index] = false;
|
|
|
|
|
+ gpu.dirty.vertex_instance[index] = false;
|
|
|
|
|
|
|
|
const auto& vertex_array = regs.vertex_array[index];
|
|
const auto& vertex_array = regs.vertex_array[index];
|
|
|
if (!vertex_array.IsEnabled())
|
|
if (!vertex_array.IsEnabled())
|
|
@@ -224,8 +228,32 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
|
glVertexArrayBindingDivisor(vao, index, 0);
|
|
glVertexArrayBindingDivisor(vao, index, 0);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
|
|
|
|
|
+ auto& gpu = system.GPU().Maxwell3D();
|
|
|
|
|
+
|
|
|
|
|
+ if (!gpu.dirty.vertex_instances)
|
|
|
|
|
+ return;
|
|
|
|
|
+ gpu.dirty.vertex_instances = false;
|
|
|
|
|
|
|
|
- gpu.dirty_flags.vertex_array.reset();
|
|
|
|
|
|
|
+ const auto& regs = gpu.regs;
|
|
|
|
|
+ // Upload all guest vertex arrays sequentially to our buffer
|
|
|
|
|
+ for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
|
|
|
|
+ if (!gpu.dirty.vertex_instance[index])
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ gpu.dirty.vertex_instance[index] = false;
|
|
|
|
|
+
|
|
|
|
|
+ if (regs.instanced_arrays.IsInstancingEnabled(index) &&
|
|
|
|
|
+ regs.vertex_array[index].divisor != 0) {
|
|
|
|
|
+ // Enable vertex buffer instancing with the specified divisor.
|
|
|
|
|
+ glVertexArrayBindingDivisor(vao, index, regs.vertex_array[index].divisor);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Disable the vertex buffer instancing.
|
|
|
|
|
+ glVertexArrayBindingDivisor(vao, index, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GLintptr RasterizerOpenGL::SetupIndexBuffer() {
|
|
GLintptr RasterizerOpenGL::SetupIndexBuffer() {
|
|
@@ -341,7 +369,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
|
|
|
|
|
|
|
SyncClipEnabled(clip_distances);
|
|
SyncClipEnabled(clip_distances);
|
|
|
|
|
|
|
|
- gpu.dirty_flags.shaders = false;
|
|
|
|
|
|
|
+ gpu.dirty.shaders = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
|
|
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
|
|
@@ -424,13 +452,13 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
|
|
|
|
|
|
|
|
const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents,
|
|
const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents,
|
|
|
single_color_target};
|
|
single_color_target};
|
|
|
- if (fb_config_state == current_framebuffer_config_state &&
|
|
|
|
|
- gpu.dirty_flags.color_buffer.none() && !gpu.dirty_flags.zeta_buffer) {
|
|
|
|
|
|
|
+ if (fb_config_state == current_framebuffer_config_state && !gpu.dirty.render_settings) {
|
|
|
// Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or
|
|
// Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or
|
|
|
// single color targets). This is done because the guest registers may not change but the
|
|
// single color targets). This is done because the guest registers may not change but the
|
|
|
// host framebuffer may contain different attachments
|
|
// host framebuffer may contain different attachments
|
|
|
return current_depth_stencil_usage;
|
|
return current_depth_stencil_usage;
|
|
|
}
|
|
}
|
|
|
|
|
+ gpu.dirty.render_settings = false;
|
|
|
current_framebuffer_config_state = fb_config_state;
|
|
current_framebuffer_config_state = fb_config_state;
|
|
|
|
|
|
|
|
texture_cache.GuardRenderTargets(true);
|
|
texture_cache.GuardRenderTargets(true);
|
|
@@ -519,13 +547,65 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
|
|
|
return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};
|
|
return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb,
|
|
|
|
|
+ bool using_depth_fb, bool using_stencil_fb) {
|
|
|
|
|
+ auto& gpu = system.GPU().Maxwell3D();
|
|
|
|
|
+ const auto& regs = gpu.regs;
|
|
|
|
|
+
|
|
|
|
|
+ texture_cache.GuardRenderTargets(true);
|
|
|
|
|
+ View color_surface{};
|
|
|
|
|
+ if (using_color_fb) {
|
|
|
|
|
+ color_surface = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT, false);
|
|
|
|
|
+ }
|
|
|
|
|
+ View depth_surface{};
|
|
|
|
|
+ if (using_depth_fb || using_stencil_fb) {
|
|
|
|
|
+ depth_surface = texture_cache.GetDepthBufferSurface(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ texture_cache.GuardRenderTargets(false);
|
|
|
|
|
+
|
|
|
|
|
+ current_state.draw.draw_framebuffer = clear_framebuffer.handle;
|
|
|
|
|
+ current_state.ApplyFramebufferState();
|
|
|
|
|
+
|
|
|
|
|
+ if (color_surface) {
|
|
|
|
|
+ color_surface->Attach(GL_COLOR_ATTACHMENT0, GL_DRAW_FRAMEBUFFER);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (depth_surface) {
|
|
|
|
|
+ const auto& params = depth_surface->GetSurfaceParams();
|
|
|
|
|
+ switch (params.type) {
|
|
|
|
|
+ case VideoCore::Surface::SurfaceType::Depth: {
|
|
|
|
|
+ depth_surface->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
|
|
|
|
|
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ case VideoCore::Surface::SurfaceType::DepthStencil: {
|
|
|
|
|
+ depth_surface->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ default: { UNIMPLEMENTED(); }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
|
|
|
|
|
+ 0);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void RasterizerOpenGL::Clear() {
|
|
void RasterizerOpenGL::Clear() {
|
|
|
const auto& regs = system.GPU().Maxwell3D().regs;
|
|
const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
bool use_color{};
|
|
bool use_color{};
|
|
|
bool use_depth{};
|
|
bool use_depth{};
|
|
|
bool use_stencil{};
|
|
bool use_stencil{};
|
|
|
|
|
|
|
|
- OpenGLState clear_state;
|
|
|
|
|
|
|
+ OpenGLState prev_state{OpenGLState::GetCurState()};
|
|
|
|
|
+ SCOPE_EXIT({
|
|
|
|
|
+ prev_state.AllDirty();
|
|
|
|
|
+ prev_state.Apply();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ OpenGLState clear_state{OpenGLState::GetCurState()};
|
|
|
|
|
+ clear_state.SetDefaultViewports();
|
|
|
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
|
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
|
|
regs.clear_buffers.A) {
|
|
regs.clear_buffers.A) {
|
|
|
use_color = true;
|
|
use_color = true;
|
|
@@ -545,6 +625,7 @@ void RasterizerOpenGL::Clear() {
|
|
|
// true.
|
|
// true.
|
|
|
clear_state.depth.test_enabled = true;
|
|
clear_state.depth.test_enabled = true;
|
|
|
clear_state.depth.test_func = GL_ALWAYS;
|
|
clear_state.depth.test_func = GL_ALWAYS;
|
|
|
|
|
+ clear_state.depth.write_mask = GL_TRUE;
|
|
|
}
|
|
}
|
|
|
if (regs.clear_buffers.S) {
|
|
if (regs.clear_buffers.S) {
|
|
|
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
|
|
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
|
|
@@ -581,8 +662,9 @@ void RasterizerOpenGL::Clear() {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const auto [clear_depth, clear_stencil] = ConfigureFramebuffers(
|
|
|
|
|
- clear_state, use_color, use_depth || use_stencil, false, regs.clear_buffers.RT.Value());
|
|
|
|
|
|
|
+ ConfigureClearFramebuffer(clear_state, use_color, use_depth, use_stencil);
|
|
|
|
|
+
|
|
|
|
|
+ SyncViewport(clear_state);
|
|
|
if (regs.clear_flags.scissor) {
|
|
if (regs.clear_flags.scissor) {
|
|
|
SyncScissorTest(clear_state);
|
|
SyncScissorTest(clear_state);
|
|
|
}
|
|
}
|
|
@@ -591,21 +673,18 @@ void RasterizerOpenGL::Clear() {
|
|
|
clear_state.EmulateViewportWithScissor();
|
|
clear_state.EmulateViewportWithScissor();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- clear_state.ApplyColorMask();
|
|
|
|
|
- clear_state.ApplyDepth();
|
|
|
|
|
- clear_state.ApplyStencilTest();
|
|
|
|
|
- clear_state.ApplyViewport();
|
|
|
|
|
- clear_state.ApplyFramebufferState();
|
|
|
|
|
|
|
+ clear_state.AllDirty();
|
|
|
|
|
+ clear_state.Apply();
|
|
|
|
|
|
|
|
if (use_color) {
|
|
if (use_color) {
|
|
|
- glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
|
|
|
|
|
|
|
+ glClearBufferfv(GL_COLOR, 0, regs.clear_color);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (clear_depth && clear_stencil) {
|
|
|
|
|
|
|
+ if (use_depth && use_stencil) {
|
|
|
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
|
|
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
|
|
|
- } else if (clear_depth) {
|
|
|
|
|
|
|
+ } else if (use_depth) {
|
|
|
glClearBufferfv(GL_DEPTH, 0, ®s.clear_depth);
|
|
glClearBufferfv(GL_DEPTH, 0, ®s.clear_depth);
|
|
|
- } else if (clear_stencil) {
|
|
|
|
|
|
|
+ } else if (use_stencil) {
|
|
|
glClearBufferiv(GL_STENCIL, 0, ®s.clear_stencil);
|
|
glClearBufferiv(GL_STENCIL, 0, ®s.clear_stencil);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -661,6 +740,7 @@ void RasterizerOpenGL::DrawArrays() {
|
|
|
|
|
|
|
|
// Upload vertex and index data.
|
|
// Upload vertex and index data.
|
|
|
SetupVertexBuffer(vao);
|
|
SetupVertexBuffer(vao);
|
|
|
|
|
+ SetupVertexInstances(vao);
|
|
|
const GLintptr index_buffer_offset = SetupIndexBuffer();
|
|
const GLintptr index_buffer_offset = SetupIndexBuffer();
|
|
|
|
|
|
|
|
// Setup draw parameters. It will automatically choose what glDraw* method to use.
|
|
// Setup draw parameters. It will automatically choose what glDraw* method to use.
|
|
@@ -687,7 +767,7 @@ void RasterizerOpenGL::DrawArrays() {
|
|
|
|
|
|
|
|
if (invalidate) {
|
|
if (invalidate) {
|
|
|
// As all cached buffers are invalidated, we need to recheck their state.
|
|
// As all cached buffers are invalidated, we need to recheck their state.
|
|
|
- gpu.dirty_flags.vertex_array.set();
|
|
|
|
|
|
|
+ gpu.dirty.ResetVertexArrays();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
shader_program_manager->ApplyTo(state);
|
|
shader_program_manager->ApplyTo(state);
|
|
@@ -700,6 +780,7 @@ void RasterizerOpenGL::DrawArrays() {
|
|
|
params.DispatchDraw();
|
|
params.DispatchDraw();
|
|
|
|
|
|
|
|
accelerate_draw = AccelDraw::Disabled;
|
|
accelerate_draw = AccelDraw::Disabled;
|
|
|
|
|
+ gpu.dirty.memory_general = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::FlushAll() {}
|
|
void RasterizerOpenGL::FlushAll() {}
|
|
@@ -907,10 +988,11 @@ void RasterizerOpenGL::SyncClipCoef() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncCullMode() {
|
|
void RasterizerOpenGL::SyncCullMode() {
|
|
|
- const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
|
|
|
|
+ auto& maxwell3d = system.GPU().Maxwell3D();
|
|
|
|
|
|
|
|
- state.cull.enabled = regs.cull.enabled != 0;
|
|
|
|
|
|
|
+ const auto& regs = maxwell3d.regs;
|
|
|
|
|
|
|
|
|
|
+ state.cull.enabled = regs.cull.enabled != 0;
|
|
|
if (state.cull.enabled) {
|
|
if (state.cull.enabled) {
|
|
|
state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
|
|
state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
|
|
|
state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
|
|
state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
|
|
@@ -943,16 +1025,21 @@ void RasterizerOpenGL::SyncDepthTestState() {
|
|
|
state.depth.test_enabled = regs.depth_test_enable != 0;
|
|
state.depth.test_enabled = regs.depth_test_enable != 0;
|
|
|
state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE;
|
|
state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE;
|
|
|
|
|
|
|
|
- if (!state.depth.test_enabled)
|
|
|
|
|
|
|
+ if (!state.depth.test_enabled) {
|
|
|
return;
|
|
return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
|
|
state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncStencilTestState() {
|
|
void RasterizerOpenGL::SyncStencilTestState() {
|
|
|
- const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
|
|
- state.stencil.test_enabled = regs.stencil_enable != 0;
|
|
|
|
|
|
|
+ auto& maxwell3d = system.GPU().Maxwell3D();
|
|
|
|
|
+ if (!maxwell3d.dirty.stencil_test) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const auto& regs = maxwell3d.regs;
|
|
|
|
|
|
|
|
|
|
+ state.stencil.test_enabled = regs.stencil_enable != 0;
|
|
|
if (!regs.stencil_enable) {
|
|
if (!regs.stencil_enable) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -981,10 +1068,17 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
|
|
state.stencil.back.action_depth_fail = GL_KEEP;
|
|
state.stencil.back.action_depth_fail = GL_KEEP;
|
|
|
state.stencil.back.action_depth_pass = GL_KEEP;
|
|
state.stencil.back.action_depth_pass = GL_KEEP;
|
|
|
}
|
|
}
|
|
|
|
|
+ state.MarkDirtyStencilState();
|
|
|
|
|
+ maxwell3d.dirty.stencil_test = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncColorMask() {
|
|
void RasterizerOpenGL::SyncColorMask() {
|
|
|
- const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
|
|
|
|
+ auto& maxwell3d = system.GPU().Maxwell3D();
|
|
|
|
|
+ if (!maxwell3d.dirty.color_mask) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const auto& regs = maxwell3d.regs;
|
|
|
|
|
+
|
|
|
const std::size_t count =
|
|
const std::size_t count =
|
|
|
regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1;
|
|
regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1;
|
|
|
for (std::size_t i = 0; i < count; i++) {
|
|
for (std::size_t i = 0; i < count; i++) {
|
|
@@ -995,6 +1089,9 @@ void RasterizerOpenGL::SyncColorMask() {
|
|
|
dest.blue_enabled = (source.B == 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;
|
|
dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ state.MarkDirtyColorMask();
|
|
|
|
|
+ maxwell3d.dirty.color_mask = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncMultiSampleState() {
|
|
void RasterizerOpenGL::SyncMultiSampleState() {
|
|
@@ -1009,7 +1106,11 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncBlendState() {
|
|
void RasterizerOpenGL::SyncBlendState() {
|
|
|
- const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
|
|
|
|
+ auto& maxwell3d = system.GPU().Maxwell3D();
|
|
|
|
|
+ if (!maxwell3d.dirty.blend_state) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const auto& regs = maxwell3d.regs;
|
|
|
|
|
|
|
|
state.blend_color.red = regs.blend_color.r;
|
|
state.blend_color.red = regs.blend_color.r;
|
|
|
state.blend_color.green = regs.blend_color.g;
|
|
state.blend_color.green = regs.blend_color.g;
|
|
@@ -1032,6 +1133,8 @@ void RasterizerOpenGL::SyncBlendState() {
|
|
|
for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
|
for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
|
|
state.blend[i].enabled = false;
|
|
state.blend[i].enabled = false;
|
|
|
}
|
|
}
|
|
|
|
|
+ maxwell3d.dirty.blend_state = false;
|
|
|
|
|
+ state.MarkDirtyBlendState();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1048,6 +1151,9 @@ void RasterizerOpenGL::SyncBlendState() {
|
|
|
blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a);
|
|
blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a);
|
|
|
blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a);
|
|
blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ state.MarkDirtyBlendState();
|
|
|
|
|
+ maxwell3d.dirty.blend_state = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncLogicOpState() {
|
|
void RasterizerOpenGL::SyncLogicOpState() {
|
|
@@ -1099,13 +1205,21 @@ void RasterizerOpenGL::SyncPointState() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncPolygonOffset() {
|
|
void RasterizerOpenGL::SyncPolygonOffset() {
|
|
|
- const auto& regs = system.GPU().Maxwell3D().regs;
|
|
|
|
|
|
|
+ auto& maxwell3d = system.GPU().Maxwell3D();
|
|
|
|
|
+ if (!maxwell3d.dirty.polygon_offset) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const auto& regs = maxwell3d.regs;
|
|
|
|
|
+
|
|
|
state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0;
|
|
state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0;
|
|
|
state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0;
|
|
state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0;
|
|
|
state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0;
|
|
state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0;
|
|
|
state.polygon_offset.units = regs.polygon_offset_units;
|
|
state.polygon_offset.units = regs.polygon_offset_units;
|
|
|
state.polygon_offset.factor = regs.polygon_offset_factor;
|
|
state.polygon_offset.factor = regs.polygon_offset_factor;
|
|
|
state.polygon_offset.clamp = regs.polygon_offset_clamp;
|
|
state.polygon_offset.clamp = regs.polygon_offset_clamp;
|
|
|
|
|
+
|
|
|
|
|
+ state.MarkDirtyPolygonOffset();
|
|
|
|
|
+ maxwell3d.dirty.polygon_offset = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RasterizerOpenGL::SyncAlphaTest() {
|
|
void RasterizerOpenGL::SyncAlphaTest() {
|