diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 54bdabea78dd..faace8b3bf7f 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -504,6 +504,11 @@ void GLGSRender::on_init_thread() LOG_WARNING(RSX, "High precision Z buffer requested but your GPU does not support GL_ARB_depth_buffer_float. Option ignored."); } + if (!gl_caps.ARB_texture_barrier_supported && !gl_caps.NV_texture_barrier_supported && !g_cfg.video.strict_rendering_mode) + { + LOG_WARNING(RSX, "Texture barriers are not supported by your GPU. Feedback loops will have undefined results."); + } + //Use industry standard resource alignment values as defaults m_uniform_buffer_offset_align = 256; m_min_texbuffer_alignment = 256; diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 9ccabb4a3f05..2f49865b2dd3 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -79,11 +79,13 @@ namespace gl bool ARB_texture_buffer_supported = false; bool ARB_shader_draw_parameters_supported = false; bool ARB_depth_buffer_float_supported = false; + bool ARB_texture_barrier_supported = false; + bool NV_texture_barrier_supported = false; bool initialized = false; void initialize() { - int find_count = 6; + int find_count = 8; int ext_count = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count); @@ -135,6 +137,20 @@ namespace gl find_count--; continue; } + + if (ext_name == "GL_ARB_texture_barrier") + { + ARB_texture_barrier_supported = true; + find_count--; + continue; + } + + if (ext_name == "GL_NV_texture_barrier") + { + NV_texture_barrier_supported = true; + find_count--; + continue; + } } //Workaround for intel drivers which have terrible capability reporting diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index e2f216059040..f7873d505c51 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -204,6 +204,10 @@ OPENGL_PROC(PFNGLTEXSTORAGE1DPROC, TexStorage1D); OPENGL_PROC(PFNGLTEXSTORAGE2DPROC, TexStorage2D); OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D); OPENGL_PROC(PFNGLTEXSUBIMAGE3DPROC, TexSubImage3D); + +//Texture_Barrier +OPENGL_PROC(PFNGLTEXTUREBARRIERPROC, TextureBarrier); +OPENGL_PROC(PFNGLTEXTUREBARRIERNVPROC, TextureBarrierNV); //... #if !defined(__GNUG__) || defined(__MINGW32__) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 64f97101b8bb..7b1a0243071b 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -11,10 +11,10 @@ #include #include +#include "Emu/System.h" #include "GLRenderTargets.h" #include "../Common/TextureUtils.h" #include "../../Memory/vm.h" - #include "../rsx_utils.h" class GLGSRender; @@ -666,13 +666,28 @@ namespace gl gl::render_target *texptr = nullptr; if (texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr)) { - for (auto tex : m_rtts.m_bound_render_targets) + for (const auto& tex : m_rtts.m_bound_render_targets) { if (std::get<0>(tex) == texaddr) { - LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); - create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height()); - return; + if (g_cfg.video.strict_rendering_mode) + { + LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); + create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height()); + return; + } + else + { + //issue a texture barrier to ensure previous writes are visible + auto &caps = gl::get_driver_caps(); + + if (caps.ARB_texture_barrier_supported) + glTextureBarrier(); + else if (caps.NV_texture_barrier_supported) + glTextureBarrierNV(); + + break; + } } } @@ -684,9 +699,22 @@ namespace gl { if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil)) { - LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr); - create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height()); - return; + if (g_cfg.video.strict_rendering_mode) + { + LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr); + create_temporary_subresource(texptr->id(), (GLenum)texptr->get_compatible_internal_format(), 0, 0, texptr->width(), texptr->height()); + return; + } + else + { + //issue a texture barrier to ensure previous writes are visible + auto &caps = gl::get_driver_caps(); + + if (caps.ARB_texture_barrier_supported) + glTextureBarrier(); + else if (caps.NV_texture_barrier_supported) + glTextureBarrierNV(); + } } texptr->bind(); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 9c65f996086b..94a176aea772 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -2,6 +2,7 @@ #include "stdafx.h" #include "VKRenderTargets.h" #include "VKGSRender.h" +#include "Emu/System.h" #include "../Common/TextureUtils.h" #include "../rsx_utils.h" @@ -473,12 +474,15 @@ namespace vk vk::image *rtt_texture = nullptr; if (rtt_texture = m_rtts.get_texture_from_render_target_if_applicable(texaddr)) { - for (auto tex : m_rtts.m_bound_render_targets) + if (g_cfg.video.strict_rendering_mode) { - if (std::get<0>(tex) == texaddr) + for (const auto& tex : m_rtts.m_bound_render_targets) { - LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); - return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping); + if (std::get<0>(tex) == texaddr) + { + LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); + return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping); + } } } @@ -490,10 +494,13 @@ namespace vk if (rtt_texture = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr)) { - if (std::get<0>(m_rtts.m_bound_depth_stencil) == texaddr) + if (g_cfg.video.strict_rendering_mode) { - LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr); - return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping); + if (std::get<0>(m_rtts.m_bound_depth_stencil) == texaddr) + { + LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr); + return create_temporary_subresource(cmd, rtt_texture, 0, 0, rtt_texture->width(), rtt_texture->height(), memory_type_mapping); + } } m_temporary_image_view.push_back(std::make_unique(*vk::get_current_renderer(), rtt_texture->value, VK_IMAGE_VIEW_TYPE_2D, rtt_texture->info.format, diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 5a2424ca22d9..1c5e6393ced3 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -307,10 +307,11 @@ struct cfg_root : cfg::node cfg::_bool vsync{this, "VSync"}; cfg::_bool debug_output{this, "Debug output"}; cfg::_bool overlay{this, "Debug overlay"}; - cfg::_bool gl_legacy_buffers{this, "Use Legacy OpenGL Buffers (Debug)"}; + cfg::_bool gl_legacy_buffers{this, "Use Legacy OpenGL Buffers"}; cfg::_bool use_gpu_texture_scaling{this, "Use GPU texture scaling", true}; cfg::_bool force_high_precision_z_buffer{this, "Force High Precision Z buffer"}; cfg::_bool invalidate_surface_cache_every_frame{this, "Invalidate Cache Every Frame", true}; + cfg::_bool strict_rendering_mode{this, "Strict Rendering Mode"}; struct node_d3d12 : cfg::node { diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index ccfecf1eb00b..e1b70028fc61 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -65,6 +65,7 @@ class emu_settings : public QObject VulkanAdapter, ForceHighpZ, AutoInvalidateCache, + StrictRenderingMode, // Audio AudioRenderer, @@ -150,12 +151,13 @@ public slots: { VSync, { "Video", "VSync"}}, { DebugOutput, { "Video", "Debug output"}}, { DebugOverlay, { "Video", "Debug overlay"}}, - { LegacyBuffers, { "Video", "Use Legacy OpenGL Buffers (Debug)"}}, + { LegacyBuffers, { "Video", "Use Legacy OpenGL Buffers"}}, { GPUTextureScaling,{ "Video", "Use GPU texture scaling"}}, { ForceHighpZ, { "Video", "Force High Precision Z buffer"}}, - { AutoInvalidateCache, {"Video", "Invalidate Cache Every Frame"}}, - { D3D12Adapter, { "Video", "D3D12", "Adapter"}}, - { VulkanAdapter, { "Video", "Vulkan", "Adapter"}}, + { AutoInvalidateCache, { "Video", "Invalidate Cache Every Frame"}}, + { StrictRenderingMode, { "Video", "Strict Rendering Mode"}}, + { D3D12Adapter, { "Video", "D3D12", "Adapter"}}, + { VulkanAdapter, { "Video", "Vulkan", "Adapter"}}, // Audio { AudioRenderer, { "Audio", "Renderer"}}, diff --git a/rpcs3/rpcs3qt/graphics_tab.cpp b/rpcs3/rpcs3qt/graphics_tab.cpp index 9fb63d9d146a..9d4d55921e0d 100644 --- a/rpcs3/rpcs3qt/graphics_tab.cpp +++ b/rpcs3/rpcs3qt/graphics_tab.cpp @@ -237,6 +237,7 @@ graphics_tab::graphics_tab(std::shared_ptr xSettings, Render_Creat QCheckBox *gpuTextureScaling = xemu_settings->CreateEnhancedCheckBox(emu_settings::GPUTextureScaling, this); QCheckBox *forceHighpZ = xemu_settings->CreateEnhancedCheckBox(emu_settings::ForceHighpZ, this); QCheckBox *autoInvalidateCache = xemu_settings->CreateEnhancedCheckBox(emu_settings::AutoInvalidateCache, this); + QCheckBox *scrictModeRendering = xemu_settings->CreateEnhancedCheckBox(emu_settings::StrictRenderingMode, this); // Combobox Part QHBoxLayout *hbox1 = new QHBoxLayout(); @@ -257,28 +258,47 @@ graphics_tab::graphics_tab(std::shared_ptr xSettings, Render_Creat hbox1->addLayout(vbox12); // Checkbox Part - QHBoxLayout *hbox2 = new QHBoxLayout(); + QGroupBox *mainOptions = new QGroupBox(tr("Main Options")); + QHBoxLayout *hbox2 = new QHBoxLayout(); //main options QVBoxLayout *vbox21 = new QVBoxLayout(); vbox21->addWidget(dumpColor); vbox21->addWidget(readColor); vbox21->addWidget(dumpDepth); vbox21->addWidget(readDepth); - vbox21->addWidget(glLegacyBuffers); - vbox21->addWidget(autoInvalidateCache); QVBoxLayout *vbox22 = new QVBoxLayout(); - vbox22->addWidget(debugOutput); - vbox22->addWidget(debugOverlay); - vbox22->addWidget(logProg); vbox22->addWidget(vsync); + vbox22->addWidget(autoInvalidateCache); vbox22->addWidget(gpuTextureScaling); - vbox22->addWidget(forceHighpZ); + vbox22->addSpacing(20); + hbox2->addLayout(vbox21); hbox2->addLayout(vbox22); + QGroupBox *debugOptions = new QGroupBox(tr("Debugging Options")); + QHBoxLayout *hbox3 = new QHBoxLayout(); + QBoxLayout *vbox31 = new QVBoxLayout(); + vbox31->addWidget(glLegacyBuffers); + vbox31->addWidget(scrictModeRendering); + vbox31->addWidget(forceHighpZ); + QVBoxLayout *vbox32 = new QVBoxLayout(); + vbox32->addWidget(debugOutput); + vbox32->addWidget(debugOverlay); + vbox32->addWidget(logProg); + + hbox3->addLayout(vbox31); + hbox3->addLayout(vbox32); + + mainOptions->setLayout(hbox2); + debugOptions->setLayout(hbox3); + + QVBoxLayout *options_container = new QVBoxLayout(); + options_container->addWidget(mainOptions); + options_container->addWidget(debugOptions); + QVBoxLayout *vbox = new QVBoxLayout(); vbox->addLayout(hbox1); vbox->addSpacing(10); - vbox->addLayout(hbox2); + vbox->addLayout(options_container); vbox->addStretch(); setLayout(vbox);