From 0f23359a44d9258efa0c0cd50243cd0efaf80235 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 13 Nov 2019 00:27:12 -0300 Subject: gl_rasterizer: Bind graphics images to draw commands Images were not being bound to draw invocations because these would require a cache invalidation. --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 80 +++++++++++++--------- src/video_core/renderer_opengl/gl_rasterizer.h | 4 ++ src/video_core/renderer_opengl/gl_shader_cache.cpp | 1 + .../renderer_opengl/gl_shader_disk_cache.cpp | 2 +- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d890076f8..9ce20f8f4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -49,8 +49,26 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); MICROPROFILE_DEFINE(OpenGL_PrimitiveAssembly, "OpenGL", "Prim Asmbl", MP_RGB(255, 100, 100)); -static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer, - const GLShader::ConstBufferEntry& entry) { +namespace { + +template +Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, + Tegra::Engines::ShaderType shader_type) { + if (entry.IsBindless()) { + const Tegra::Texture::TextureHandle tex_handle = + engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); + return engine.GetTextureInfo(tex_handle); + } + if constexpr (std::is_same_v) { + const auto stage = static_cast(shader_type); + return engine.GetStageTexture(stage, entry.GetOffset()); + } else { + return engine.GetTexture(entry.GetOffset()); + } +} + +std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer, + const GLShader::ConstBufferEntry& entry) { if (!entry.IsIndirect()) { return entry.GetSize(); } @@ -64,6 +82,8 @@ static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buf return buffer.size; } +} // Anonymous namespace + RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, ScreenInfo& info) : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device}, @@ -272,6 +292,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { SetupDrawConstBuffers(stage, shader); SetupDrawGlobalMemory(stage, shader); SetupDrawTextures(stage, shader, base_bindings); + SetupDrawImages(stage, shader, base_bindings); const ProgramVariant variant(base_bindings, primitive_mode); const auto [program_handle, next_bindings] = shader->GetHandle(variant); @@ -921,18 +942,11 @@ void RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage, const Shade ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.textures), "Exceeded the number of active textures."); - for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { + const auto num_entries = static_cast(entries.size()); + for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) { const auto& entry = entries[bindpoint]; - const auto texture = [&] { - if (!entry.IsBindless()) { - return maxwell3d.GetStageTexture(stage, entry.GetOffset()); - } - const auto shader_type = static_cast(stage); - const Tegra::Texture::TextureHandle tex_handle = - maxwell3d.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); - return maxwell3d.GetTextureInfo(tex_handle); - }(); - + const auto shader_type = static_cast(stage); + const auto texture = GetTextureInfo(maxwell3d, entry, shader_type); SetupTexture(base_bindings.sampler + bindpoint, texture, entry); } } @@ -945,17 +959,10 @@ void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) { ASSERT_MSG(entries.size() <= std::size(state.textures), "Exceeded the number of active textures."); - for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { + const auto num_entries = static_cast(entries.size()); + for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) { const auto& entry = entries[bindpoint]; - const auto texture = [&] { - if (!entry.IsBindless()) { - return compute.GetTexture(entry.GetOffset()); - } - const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( - Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); - return compute.GetTextureInfo(tex_handle); - }(); - + const auto texture = GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute); SetupTexture(bindpoint, texture, entry); } } @@ -981,19 +988,28 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu texture.tic.w_source); } +void RasterizerOpenGL::SetupDrawImages(Maxwell::ShaderStage stage, const Shader& shader, + BaseBindings base_bindings) { + const auto& maxwell3d = system.GPU().Maxwell3D(); + const auto& entries = shader->GetShaderEntries().images; + + const auto num_entries = static_cast(entries.size()); + for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) { + const auto& entry = entries[bindpoint]; + const auto shader_type = static_cast(stage); + const auto tic = GetTextureInfo(maxwell3d, entry, shader_type).tic; + SetupImage(base_bindings.image + bindpoint, tic, entry); + } +} + void RasterizerOpenGL::SetupComputeImages(const Shader& shader) { const auto& compute = system.GPU().KeplerCompute(); const auto& entries = shader->GetShaderEntries().images; - for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { + + const auto num_entries = static_cast(entries.size()); + for (u32 bindpoint = 0; bindpoint < num_entries; ++bindpoint) { const auto& entry = entries[bindpoint]; - const auto tic = [&] { - if (!entry.IsBindless()) { - return compute.GetTexture(entry.GetOffset()).tic; - } - const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( - Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); - return compute.GetTextureInfo(tex_handle).tic; - }(); + const auto tic = GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute).tic; SetupImage(bindpoint, tic, entry); } } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 0e0819d59..267ed7803 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -118,6 +118,10 @@ private: void SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture, const GLShader::SamplerEntry& entry); + /// Configures images in a graphics shader. + void SetupDrawImages(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader, + BaseBindings base_bindings); + /// Configures images in a compute shader. void SetupComputeImages(const Shader& shader); diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index b23a982d7..e7c92e45d 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -449,6 +449,7 @@ std::tuple CachedShader::GetHandle(const ProgramVariant& v base_bindings.cbuf += STAGE_RESERVED_UBOS; base_bindings.gmem += static_cast(entries.global_memory_entries.size()); base_bindings.sampler += static_cast(entries.samplers.size()); + base_bindings.image += static_cast(entries.images.size()); return {program->handle, base_bindings}; } diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 5ebcbbbba..ccf530367 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -52,7 +52,7 @@ struct BindlessSamplerKey { Tegra::Engines::SamplerDescriptor sampler{}; }; -constexpr u32 NativeVersion = 9; +constexpr u32 NativeVersion = 10; // Making sure sizes doesn't change by accident static_assert(sizeof(BaseBindings) == 16); -- cgit v1.2.3