summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_rasterizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp59
1 files changed, 46 insertions, 13 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 8d5f277e2..be51c5215 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -424,6 +424,13 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
// Used when just a single color attachment is enabled, e.g. for clearing a color buffer
Surface color_surface =
res_cache.GetColorBufferSurface(*single_color_target, preserve_contents);
+
+ if (color_surface) {
+ // Assume that a surface will be written to if it is used as a framebuffer, even if
+ // the shader doesn't actually write to it.
+ color_surface->MarkAsModified(true, res_cache);
+ }
+
glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D,
@@ -434,6 +441,13 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
std::array<GLenum, Maxwell::NumRenderTargets> buffers;
for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
+
+ if (color_surface) {
+ // Assume that a surface will be written to if it is used as a framebuffer, even
+ // if the shader doesn't actually write to it.
+ color_surface->MarkAsModified(true, res_cache);
+ }
+
buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
@@ -453,6 +467,10 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
}
if (depth_surface) {
+ // Assume that a surface will be written to if it is used as a framebuffer, even if
+ // the shader doesn't actually write to it.
+ depth_surface->MarkAsModified(true, res_cache);
+
if (regs.stencil_enable) {
// Attach both depth and stencil
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
@@ -552,10 +570,11 @@ void RasterizerOpenGL::DrawArrays() {
SyncBlendState();
SyncLogicOpState();
SyncCullMode();
- SyncAlphaTest();
SyncScissorTest();
+ // Alpha Testing is synced on shaders.
SyncTransformFeedback();
SyncPointState();
+ CheckAlphaTests();
// TODO(bunnei): Sync framebuffer_scale uniform here
// TODO(bunnei): Sync scissorbox uniform(s) here
@@ -617,7 +636,14 @@ void RasterizerOpenGL::DrawArrays() {
void RasterizerOpenGL::FlushAll() {}
-void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {}
+void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
+ MICROPROFILE_SCOPE(OpenGL_CacheManagement);
+
+ if (Settings::values.use_accurate_gpu_emulation) {
+ // Only flush if use_accurate_gpu_emulation is enabled, as it incurs a performance hit
+ res_cache.FlushRegion(addr, size);
+ }
+}
void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
@@ -627,12 +653,19 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
}
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
+ FlushRegion(addr, size);
InvalidateRegion(addr, size);
}
bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
const Tegra::Engines::Fermi2D::Regs::Surface& dst) {
MICROPROFILE_SCOPE(OpenGL_Blits);
+
+ if (Settings::values.use_accurate_gpu_emulation) {
+ // Skip the accelerated copy and perform a slow but more accurate copy
+ return false;
+ }
+
res_cache.FermiCopySurface(src, dst);
return true;
}
@@ -975,17 +1008,6 @@ void RasterizerOpenGL::SyncLogicOpState() {
state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
}
-void RasterizerOpenGL::SyncAlphaTest() {
- const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
-
- // TODO(Rodrigo): Alpha testing is a legacy OpenGL feature, but it can be
- // implemented with a test+discard in fragment shaders.
- if (regs.alpha_test_enabled != 0) {
- LOG_CRITICAL(Render_OpenGL, "Alpha testing is not implemented");
- UNREACHABLE();
- }
-}
-
void RasterizerOpenGL::SyncScissorTest() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
@@ -1020,4 +1042,15 @@ void RasterizerOpenGL::SyncPointState() {
state.point.size = regs.point_size == 0 ? 1 : regs.point_size;
}
+void RasterizerOpenGL::CheckAlphaTests() {
+ const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+
+ if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
+ LOG_CRITICAL(
+ Render_OpenGL,
+ "Alpha Testing is enabled with Multiple Render Targets, this behavior is undefined.");
+ UNREACHABLE();
+ }
+}
+
} // namespace OpenGL