diff options
| author | 2019-09-10 08:57:05 -0400 | |
|---|---|---|
| committer | 2019-09-10 08:57:05 -0400 | |
| commit | 434d0922dcf886c6bb3ac50b96a8c6091c5c6c11 (patch) | |
| tree | 7a8789ba575866a8cdc03f8b4bd6d17789659fcd | |
| parent | Merge pull request #2847 from VelocityRa/nro-nacp-fix (diff) | |
| parent | gl_shader_decompiler: Keep track of written images and mark them as modified (diff) | |
| download | yuzu-434d0922dcf886c6bb3ac50b96a8c6091c5c6c11.tar.gz yuzu-434d0922dcf886c6bb3ac50b96a8c6091c5c6c11.tar.xz yuzu-434d0922dcf886c6bb3ac50b96a8c6091c5c6c11.zip | |
Merge pull request #2759 from ReinUsesLisp/compute-images
gl_rasterizer: Bind images and samplers to compute
20 files changed, 457 insertions, 229 deletions
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index 08586d33c..63d449135 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <bitset> | ||
| 5 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| @@ -49,6 +50,33 @@ void KeplerCompute::CallMethod(const GPU::MethodCall& method_call) { | |||
| 49 | } | 50 | } |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 53 | Tegra::Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const { | ||
| 54 | const std::bitset<8> cbuf_mask = launch_description.const_buffer_enable_mask.Value(); | ||
| 55 | ASSERT(cbuf_mask[regs.tex_cb_index]); | ||
| 56 | |||
| 57 | const auto& texinfo = launch_description.const_buffer_config[regs.tex_cb_index]; | ||
| 58 | ASSERT(texinfo.Address() != 0); | ||
| 59 | |||
| 60 | const GPUVAddr address = texinfo.Address() + offset * sizeof(Texture::TextureHandle); | ||
| 61 | ASSERT(address < texinfo.Address() + texinfo.size); | ||
| 62 | |||
| 63 | const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(address)}; | ||
| 64 | return GetTextureInfo(tex_handle, offset); | ||
| 65 | } | ||
| 66 | |||
| 67 | Texture::FullTextureInfo KeplerCompute::GetTextureInfo(const Texture::TextureHandle tex_handle, | ||
| 68 | std::size_t offset) const { | ||
| 69 | return Texture::FullTextureInfo{static_cast<u32>(offset), GetTICEntry(tex_handle.tic_id), | ||
| 70 | GetTSCEntry(tex_handle.tsc_id)}; | ||
| 71 | } | ||
| 72 | |||
| 73 | u32 KeplerCompute::AccessConstBuffer32(u64 const_buffer, u64 offset) const { | ||
| 74 | const auto& buffer = launch_description.const_buffer_config[const_buffer]; | ||
| 75 | u32 result; | ||
| 76 | std::memcpy(&result, memory_manager.GetPointer(buffer.Address() + offset), sizeof(u32)); | ||
| 77 | return result; | ||
| 78 | } | ||
| 79 | |||
| 52 | void KeplerCompute::ProcessLaunch() { | 80 | void KeplerCompute::ProcessLaunch() { |
| 53 | const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address(); | 81 | const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address(); |
| 54 | memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description, | 82 | memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description, |
| @@ -60,4 +88,29 @@ void KeplerCompute::ProcessLaunch() { | |||
| 60 | rasterizer.DispatchCompute(code_addr); | 88 | rasterizer.DispatchCompute(code_addr); |
| 61 | } | 89 | } |
| 62 | 90 | ||
| 91 | Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { | ||
| 92 | const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)}; | ||
| 93 | |||
| 94 | Texture::TICEntry tic_entry; | ||
| 95 | memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry)); | ||
| 96 | |||
| 97 | const auto r_type{tic_entry.r_type.Value()}; | ||
| 98 | const auto g_type{tic_entry.g_type.Value()}; | ||
| 99 | const auto b_type{tic_entry.b_type.Value()}; | ||
| 100 | const auto a_type{tic_entry.a_type.Value()}; | ||
| 101 | |||
| 102 | // TODO(Subv): Different data types for separate components are not supported | ||
| 103 | DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type); | ||
| 104 | |||
| 105 | return tic_entry; | ||
| 106 | } | ||
| 107 | |||
| 108 | Texture::TSCEntry KeplerCompute::GetTSCEntry(u32 tsc_index) const { | ||
| 109 | const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)}; | ||
| 110 | |||
| 111 | Texture::TSCEntry tsc_entry; | ||
| 112 | memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry)); | ||
| 113 | return tsc_entry; | ||
| 114 | } | ||
| 115 | |||
| 63 | } // namespace Tegra::Engines | 116 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index 6a3309a2c..90cf650d2 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "video_core/engines/engine_upload.h" | 13 | #include "video_core/engines/engine_upload.h" |
| 14 | #include "video_core/gpu.h" | 14 | #include "video_core/gpu.h" |
| 15 | #include "video_core/textures/texture.h" | ||
| 15 | 16 | ||
| 16 | namespace Core { | 17 | namespace Core { |
| 17 | class System; | 18 | class System; |
| @@ -111,7 +112,7 @@ public: | |||
| 111 | 112 | ||
| 112 | INSERT_PADDING_WORDS(0x3FE); | 113 | INSERT_PADDING_WORDS(0x3FE); |
| 113 | 114 | ||
| 114 | u32 texture_const_buffer_index; | 115 | u32 tex_cb_index; |
| 115 | 116 | ||
| 116 | INSERT_PADDING_WORDS(0x374); | 117 | INSERT_PADDING_WORDS(0x374); |
| 117 | }; | 118 | }; |
| @@ -149,7 +150,7 @@ public: | |||
| 149 | union { | 150 | union { |
| 150 | BitField<0, 8, u32> const_buffer_enable_mask; | 151 | BitField<0, 8, u32> const_buffer_enable_mask; |
| 151 | BitField<29, 2, u32> cache_layout; | 152 | BitField<29, 2, u32> cache_layout; |
| 152 | } memory_config; | 153 | }; |
| 153 | 154 | ||
| 154 | INSERT_PADDING_WORDS(0x8); | 155 | INSERT_PADDING_WORDS(0x8); |
| 155 | 156 | ||
| @@ -194,6 +195,14 @@ public: | |||
| 194 | /// Write the value to the register identified by method. | 195 | /// Write the value to the register identified by method. |
| 195 | void CallMethod(const GPU::MethodCall& method_call); | 196 | void CallMethod(const GPU::MethodCall& method_call); |
| 196 | 197 | ||
| 198 | Tegra::Texture::FullTextureInfo GetTexture(std::size_t offset) const; | ||
| 199 | |||
| 200 | /// Given a Texture Handle, returns the TSC and TIC entries. | ||
| 201 | Texture::FullTextureInfo GetTextureInfo(const Texture::TextureHandle tex_handle, | ||
| 202 | std::size_t offset) const; | ||
| 203 | |||
| 204 | u32 AccessConstBuffer32(u64 const_buffer, u64 offset) const; | ||
| 205 | |||
| 197 | private: | 206 | private: |
| 198 | Core::System& system; | 207 | Core::System& system; |
| 199 | VideoCore::RasterizerInterface& rasterizer; | 208 | VideoCore::RasterizerInterface& rasterizer; |
| @@ -201,6 +210,12 @@ private: | |||
| 201 | Upload::State upload_state; | 210 | Upload::State upload_state; |
| 202 | 211 | ||
| 203 | void ProcessLaunch(); | 212 | void ProcessLaunch(); |
| 213 | |||
| 214 | /// Retrieves information about a specific TIC entry from the TIC buffer. | ||
| 215 | Texture::TICEntry GetTICEntry(u32 tic_index) const; | ||
| 216 | |||
| 217 | /// Retrieves information about a specific TSC entry from the TSC buffer. | ||
| 218 | Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; | ||
| 204 | }; | 219 | }; |
| 205 | 220 | ||
| 206 | #define ASSERT_REG_POSITION(field_name, position) \ | 221 | #define ASSERT_REG_POSITION(field_name, position) \ |
| @@ -218,12 +233,12 @@ ASSERT_REG_POSITION(launch, 0xAF); | |||
| 218 | ASSERT_REG_POSITION(tsc, 0x557); | 233 | ASSERT_REG_POSITION(tsc, 0x557); |
| 219 | ASSERT_REG_POSITION(tic, 0x55D); | 234 | ASSERT_REG_POSITION(tic, 0x55D); |
| 220 | ASSERT_REG_POSITION(code_loc, 0x582); | 235 | ASSERT_REG_POSITION(code_loc, 0x582); |
| 221 | ASSERT_REG_POSITION(texture_const_buffer_index, 0x982); | 236 | ASSERT_REG_POSITION(tex_cb_index, 0x982); |
| 222 | ASSERT_LAUNCH_PARAM_POSITION(program_start, 0x8); | 237 | ASSERT_LAUNCH_PARAM_POSITION(program_start, 0x8); |
| 223 | ASSERT_LAUNCH_PARAM_POSITION(grid_dim_x, 0xC); | 238 | ASSERT_LAUNCH_PARAM_POSITION(grid_dim_x, 0xC); |
| 224 | ASSERT_LAUNCH_PARAM_POSITION(shared_alloc, 0x11); | 239 | ASSERT_LAUNCH_PARAM_POSITION(shared_alloc, 0x11); |
| 225 | ASSERT_LAUNCH_PARAM_POSITION(block_dim_x, 0x12); | 240 | ASSERT_LAUNCH_PARAM_POSITION(block_dim_x, 0x12); |
| 226 | ASSERT_LAUNCH_PARAM_POSITION(memory_config, 0x14); | 241 | ASSERT_LAUNCH_PARAM_POSITION(const_buffer_enable_mask, 0x14); |
| 227 | ASSERT_LAUNCH_PARAM_POSITION(const_buffer_config, 0x1D); | 242 | ASSERT_LAUNCH_PARAM_POSITION(const_buffer_config, 0x1D); |
| 228 | 243 | ||
| 229 | #undef ASSERT_REG_POSITION | 244 | #undef ASSERT_REG_POSITION |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0184342a0..3b3c82f41 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -62,6 +62,7 @@ public: | |||
| 62 | static constexpr std::size_t NumVertexAttributes = 32; | 62 | static constexpr std::size_t NumVertexAttributes = 32; |
| 63 | static constexpr std::size_t NumVaryings = 31; | 63 | static constexpr std::size_t NumVaryings = 31; |
| 64 | static constexpr std::size_t NumTextureSamplers = 32; | 64 | static constexpr std::size_t NumTextureSamplers = 32; |
| 65 | static constexpr std::size_t NumImages = 8; // TODO(Rodrigo): Investigate this number | ||
| 65 | static constexpr std::size_t NumClipDistances = 8; | 66 | static constexpr std::size_t NumClipDistances = 8; |
| 66 | static constexpr std::size_t MaxShaderProgram = 6; | 67 | static constexpr std::size_t MaxShaderProgram = 6; |
| 67 | static constexpr std::size_t MaxShaderStage = 5; | 68 | static constexpr std::size_t MaxShaderStage = 5; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 01d89f47d..4e266cdad 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -331,7 +331,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 331 | const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); | 331 | const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); |
| 332 | SetupDrawConstBuffers(stage_enum, shader); | 332 | SetupDrawConstBuffers(stage_enum, shader); |
| 333 | SetupDrawGlobalMemory(stage_enum, shader); | 333 | SetupDrawGlobalMemory(stage_enum, shader); |
| 334 | const auto texture_buffer_usage{SetupTextures(stage_enum, shader, base_bindings)}; | 334 | const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)}; |
| 335 | 335 | ||
| 336 | const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage}; | 336 | const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage}; |
| 337 | const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant); | 337 | const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant); |
| @@ -801,7 +801,11 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | |||
| 801 | } | 801 | } |
| 802 | 802 | ||
| 803 | auto kernel = shader_cache.GetComputeKernel(code_addr); | 803 | auto kernel = shader_cache.GetComputeKernel(code_addr); |
| 804 | const auto [program, next_bindings] = kernel->GetProgramHandle({}); | 804 | ProgramVariant variant; |
| 805 | variant.texture_buffer_usage = SetupComputeTextures(kernel); | ||
| 806 | SetupComputeImages(kernel); | ||
| 807 | |||
| 808 | const auto [program, next_bindings] = kernel->GetProgramHandle(variant); | ||
| 805 | state.draw.shader_program = program; | 809 | state.draw.shader_program = program; |
| 806 | state.draw.program_pipeline = 0; | 810 | state.draw.program_pipeline = 0; |
| 807 | 811 | ||
| @@ -816,13 +820,13 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | |||
| 816 | SetupComputeConstBuffers(kernel); | 820 | SetupComputeConstBuffers(kernel); |
| 817 | SetupComputeGlobalMemory(kernel); | 821 | SetupComputeGlobalMemory(kernel); |
| 818 | 822 | ||
| 819 | // TODO(Rodrigo): Bind images and samplers | ||
| 820 | |||
| 821 | buffer_cache.Unmap(); | 823 | buffer_cache.Unmap(); |
| 822 | 824 | ||
| 823 | bind_ubo_pushbuffer.Bind(); | 825 | bind_ubo_pushbuffer.Bind(); |
| 824 | bind_ssbo_pushbuffer.Bind(); | 826 | bind_ssbo_pushbuffer.Bind(); |
| 825 | 827 | ||
| 828 | state.ApplyTextures(); | ||
| 829 | state.ApplyImages(); | ||
| 826 | state.ApplyShaderProgram(); | 830 | state.ApplyShaderProgram(); |
| 827 | state.ApplyProgramPipeline(); | 831 | state.ApplyProgramPipeline(); |
| 828 | 832 | ||
| @@ -922,7 +926,7 @@ void RasterizerOpenGL::SetupComputeConstBuffers(const Shader& kernel) { | |||
| 922 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; | 926 | const auto& launch_desc = system.GPU().KeplerCompute().launch_description; |
| 923 | for (const auto& entry : kernel->GetShaderEntries().const_buffers) { | 927 | for (const auto& entry : kernel->GetShaderEntries().const_buffers) { |
| 924 | const auto& config = launch_desc.const_buffer_config[entry.GetIndex()]; | 928 | const auto& config = launch_desc.const_buffer_config[entry.GetIndex()]; |
| 925 | const std::bitset<8> mask = launch_desc.memory_config.const_buffer_enable_mask.Value(); | 929 | const std::bitset<8> mask = launch_desc.const_buffer_enable_mask.Value(); |
| 926 | Tegra::Engines::ConstBufferInfo buffer; | 930 | Tegra::Engines::ConstBufferInfo buffer; |
| 927 | buffer.address = config.Address(); | 931 | buffer.address = config.Address(); |
| 928 | buffer.size = config.size; | 932 | buffer.size = config.size; |
| @@ -981,53 +985,125 @@ void RasterizerOpenGL::SetupGlobalMemory(const GLShader::GlobalMemoryEntry& entr | |||
| 981 | bind_ssbo_pushbuffer.Push(ssbo, buffer_offset, static_cast<GLsizeiptr>(size)); | 985 | bind_ssbo_pushbuffer.Push(ssbo, buffer_offset, static_cast<GLsizeiptr>(size)); |
| 982 | } | 986 | } |
| 983 | 987 | ||
| 984 | TextureBufferUsage RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader, | 988 | TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage, |
| 985 | BaseBindings base_bindings) { | 989 | const Shader& shader, |
| 990 | BaseBindings base_bindings) { | ||
| 986 | MICROPROFILE_SCOPE(OpenGL_Texture); | 991 | MICROPROFILE_SCOPE(OpenGL_Texture); |
| 987 | const auto& gpu = system.GPU(); | 992 | const auto& gpu = system.GPU(); |
| 988 | const auto& maxwell3d = gpu.Maxwell3D(); | 993 | const auto& maxwell3d = gpu.Maxwell3D(); |
| 989 | const auto& entries = shader->GetShaderEntries().samplers; | 994 | const auto& entries = shader->GetShaderEntries().samplers; |
| 990 | 995 | ||
| 991 | ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.texture_units), | 996 | ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.textures), |
| 992 | "Exceeded the number of active textures."); | 997 | "Exceeded the number of active textures."); |
| 993 | 998 | ||
| 994 | TextureBufferUsage texture_buffer_usage{0}; | 999 | TextureBufferUsage texture_buffer_usage{0}; |
| 995 | 1000 | ||
| 996 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | 1001 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { |
| 997 | const auto& entry = entries[bindpoint]; | 1002 | const auto& entry = entries[bindpoint]; |
| 998 | Tegra::Texture::FullTextureInfo texture; | 1003 | const auto texture = [&]() { |
| 999 | if (entry.IsBindless()) { | 1004 | if (!entry.IsBindless()) { |
| 1005 | return maxwell3d.GetStageTexture(stage, entry.GetOffset()); | ||
| 1006 | } | ||
| 1000 | const auto cbuf = entry.GetBindlessCBuf(); | 1007 | const auto cbuf = entry.GetBindlessCBuf(); |
| 1001 | Tegra::Texture::TextureHandle tex_handle; | 1008 | Tegra::Texture::TextureHandle tex_handle; |
| 1002 | tex_handle.raw = maxwell3d.AccessConstBuffer32(stage, cbuf.first, cbuf.second); | 1009 | tex_handle.raw = maxwell3d.AccessConstBuffer32(stage, cbuf.first, cbuf.second); |
| 1003 | texture = maxwell3d.GetTextureInfo(tex_handle, entry.GetOffset()); | 1010 | return maxwell3d.GetTextureInfo(tex_handle, entry.GetOffset()); |
| 1004 | } else { | 1011 | }(); |
| 1005 | texture = maxwell3d.GetStageTexture(stage, entry.GetOffset()); | 1012 | |
| 1013 | if (SetupTexture(base_bindings.sampler + bindpoint, texture, entry)) { | ||
| 1014 | texture_buffer_usage.set(bindpoint); | ||
| 1006 | } | 1015 | } |
| 1007 | const u32 current_bindpoint = base_bindings.sampler + bindpoint; | 1016 | } |
| 1008 | 1017 | ||
| 1009 | auto& unit{state.texture_units[current_bindpoint]}; | 1018 | return texture_buffer_usage; |
| 1010 | unit.sampler = sampler_cache.GetSampler(texture.tsc); | 1019 | } |
| 1011 | 1020 | ||
| 1012 | if (const auto view{texture_cache.GetTextureSurface(texture, entry)}; view) { | 1021 | TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) { |
| 1013 | if (view->GetSurfaceParams().IsBuffer()) { | 1022 | MICROPROFILE_SCOPE(OpenGL_Texture); |
| 1014 | // Record that this texture is a texture buffer. | 1023 | const auto& compute = system.GPU().KeplerCompute(); |
| 1015 | texture_buffer_usage.set(bindpoint); | 1024 | const auto& entries = kernel->GetShaderEntries().samplers; |
| 1016 | } else { | 1025 | |
| 1017 | // Apply swizzle to textures that are not buffers. | 1026 | ASSERT_MSG(entries.size() <= std::size(state.textures), |
| 1018 | view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, | 1027 | "Exceeded the number of active textures."); |
| 1019 | texture.tic.w_source); | 1028 | |
| 1029 | TextureBufferUsage texture_buffer_usage{0}; | ||
| 1030 | |||
| 1031 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | ||
| 1032 | const auto& entry = entries[bindpoint]; | ||
| 1033 | const auto texture = [&]() { | ||
| 1034 | if (!entry.IsBindless()) { | ||
| 1035 | return compute.GetTexture(entry.GetOffset()); | ||
| 1020 | } | 1036 | } |
| 1021 | state.texture_units[current_bindpoint].texture = view->GetTexture(); | 1037 | const auto cbuf = entry.GetBindlessCBuf(); |
| 1022 | } else { | 1038 | Tegra::Texture::TextureHandle tex_handle; |
| 1023 | // Can occur when texture addr is null or its memory is unmapped/invalid | 1039 | tex_handle.raw = compute.AccessConstBuffer32(cbuf.first, cbuf.second); |
| 1024 | unit.texture = 0; | 1040 | return compute.GetTextureInfo(tex_handle, entry.GetOffset()); |
| 1041 | }(); | ||
| 1042 | |||
| 1043 | if (SetupTexture(bindpoint, texture, entry)) { | ||
| 1044 | texture_buffer_usage.set(bindpoint); | ||
| 1025 | } | 1045 | } |
| 1026 | } | 1046 | } |
| 1027 | 1047 | ||
| 1028 | return texture_buffer_usage; | 1048 | return texture_buffer_usage; |
| 1029 | } | 1049 | } |
| 1030 | 1050 | ||
| 1051 | bool RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture, | ||
| 1052 | const GLShader::SamplerEntry& entry) { | ||
| 1053 | state.samplers[binding] = sampler_cache.GetSampler(texture.tsc); | ||
| 1054 | |||
| 1055 | const auto view = texture_cache.GetTextureSurface(texture.tic, entry); | ||
| 1056 | if (!view) { | ||
| 1057 | // Can occur when texture addr is null or its memory is unmapped/invalid | ||
| 1058 | state.textures[binding] = 0; | ||
| 1059 | return false; | ||
| 1060 | } | ||
| 1061 | state.textures[binding] = view->GetTexture(); | ||
| 1062 | |||
| 1063 | if (view->GetSurfaceParams().IsBuffer()) { | ||
| 1064 | return true; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | // Apply swizzle to textures that are not buffers. | ||
| 1068 | view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, | ||
| 1069 | texture.tic.w_source); | ||
| 1070 | return false; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | void RasterizerOpenGL::SetupComputeImages(const Shader& shader) { | ||
| 1074 | const auto& compute = system.GPU().KeplerCompute(); | ||
| 1075 | const auto& entries = shader->GetShaderEntries().images; | ||
| 1076 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | ||
| 1077 | const auto& entry = entries[bindpoint]; | ||
| 1078 | const auto tic = [&]() { | ||
| 1079 | if (!entry.IsBindless()) { | ||
| 1080 | return compute.GetTexture(entry.GetOffset()).tic; | ||
| 1081 | } | ||
| 1082 | const auto cbuf = entry.GetBindlessCBuf(); | ||
| 1083 | Tegra::Texture::TextureHandle tex_handle; | ||
| 1084 | tex_handle.raw = compute.AccessConstBuffer32(cbuf.first, cbuf.second); | ||
| 1085 | return compute.GetTextureInfo(tex_handle, entry.GetOffset()).tic; | ||
| 1086 | }(); | ||
| 1087 | SetupImage(bindpoint, tic, entry); | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& tic, | ||
| 1092 | const GLShader::ImageEntry& entry) { | ||
| 1093 | const auto view = texture_cache.GetImageSurface(tic, entry); | ||
| 1094 | if (!view) { | ||
| 1095 | state.images[binding] = 0; | ||
| 1096 | return; | ||
| 1097 | } | ||
| 1098 | if (!tic.IsBuffer()) { | ||
| 1099 | view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | ||
| 1100 | } | ||
| 1101 | if (entry.IsWritten()) { | ||
| 1102 | view->MarkAsModified(texture_cache.Tick()); | ||
| 1103 | } | ||
| 1104 | state.images[binding] = view->GetTexture(); | ||
| 1105 | } | ||
| 1106 | |||
| 1031 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | 1107 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { |
| 1032 | const auto& regs = system.GPU().Maxwell3D().regs; | 1108 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 1033 | const bool geometry_shaders_enabled = | 1109 | const bool geometry_shaders_enabled = |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 9d20a4fbf..eada752e0 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "video_core/renderer_opengl/gl_state.h" | 32 | #include "video_core/renderer_opengl/gl_state.h" |
| 33 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 33 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 34 | #include "video_core/renderer_opengl/utils.h" | 34 | #include "video_core/renderer_opengl/utils.h" |
| 35 | #include "video_core/textures/texture.h" | ||
| 35 | 36 | ||
| 36 | namespace Core { | 37 | namespace Core { |
| 37 | class System; | 38 | class System; |
| @@ -137,8 +138,22 @@ private: | |||
| 137 | 138 | ||
| 138 | /// Configures the current textures to use for the draw command. Returns shaders texture buffer | 139 | /// Configures the current textures to use for the draw command. Returns shaders texture buffer |
| 139 | /// usage. | 140 | /// usage. |
| 140 | TextureBufferUsage SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, | 141 | TextureBufferUsage SetupDrawTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
| 141 | const Shader& shader, BaseBindings base_bindings); | 142 | const Shader& shader, BaseBindings base_bindings); |
| 143 | |||
| 144 | /// Configures the textures used in a compute shader. Returns texture buffer usage. | ||
| 145 | TextureBufferUsage SetupComputeTextures(const Shader& kernel); | ||
| 146 | |||
| 147 | /// Configures a texture. Returns true when the texture is a texture buffer. | ||
| 148 | bool SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture, | ||
| 149 | const GLShader::SamplerEntry& entry); | ||
| 150 | |||
| 151 | /// Configures images in a compute shader. | ||
| 152 | void SetupComputeImages(const Shader& shader); | ||
| 153 | |||
| 154 | /// Configures an image. | ||
| 155 | void SetupImage(u32 binding, const Tegra::Texture::TICEntry& tic, | ||
| 156 | const GLShader::ImageEntry& entry); | ||
| 142 | 157 | ||
| 143 | /// Syncs the viewport and depth range to match the guest state | 158 | /// Syncs the viewport and depth range to match the guest state |
| 144 | void SyncViewport(OpenGLState& current_state); | 159 | void SyncViewport(OpenGLState& current_state); |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index a5cc1a86f..6edb2ca38 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -389,11 +389,10 @@ public: | |||
| 389 | for (const auto& sampler : ir.GetSamplers()) { | 389 | for (const auto& sampler : ir.GetSamplers()) { |
| 390 | entries.samplers.emplace_back(sampler); | 390 | entries.samplers.emplace_back(sampler); |
| 391 | } | 391 | } |
| 392 | for (const auto& image : ir.GetImages()) { | 392 | for (const auto& [offset, image] : ir.GetImages()) { |
| 393 | entries.images.emplace_back(image); | 393 | entries.images.emplace_back(image); |
| 394 | } | 394 | } |
| 395 | for (const auto& gmem_pair : ir.GetGlobalMemory()) { | 395 | for (const auto& [base, usage] : ir.GetGlobalMemory()) { |
| 396 | const auto& [base, usage] = gmem_pair; | ||
| 397 | entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, | 396 | entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, |
| 398 | usage.is_read, usage.is_written); | 397 | usage.is_read, usage.is_written); |
| 399 | } | 398 | } |
| @@ -706,7 +705,7 @@ private: | |||
| 706 | 705 | ||
| 707 | void DeclareImages() { | 706 | void DeclareImages() { |
| 708 | const auto& images{ir.GetImages()}; | 707 | const auto& images{ir.GetImages()}; |
| 709 | for (const auto& image : images) { | 708 | for (const auto& [offset, image] : images) { |
| 710 | const std::string image_type = [&]() { | 709 | const std::string image_type = [&]() { |
| 711 | switch (image.GetType()) { | 710 | switch (image.GetType()) { |
| 712 | case Tegra::Shader::ImageType::Texture1D: | 711 | case Tegra::Shader::ImageType::Texture1D: |
| @@ -726,9 +725,16 @@ private: | |||
| 726 | return "image1D"; | 725 | return "image1D"; |
| 727 | } | 726 | } |
| 728 | }(); | 727 | }(); |
| 729 | code.AddLine("layout (binding = IMAGE_BINDING_{}) coherent volatile writeonly uniform " | 728 | std::string qualifier = "coherent volatile"; |
| 729 | if (image.IsRead() && !image.IsWritten()) { | ||
| 730 | qualifier += " readonly"; | ||
| 731 | } else if (image.IsWritten() && !image.IsRead()) { | ||
| 732 | qualifier += " writeonly"; | ||
| 733 | } | ||
| 734 | |||
| 735 | code.AddLine("layout (binding = IMAGE_BINDING_{}) {} uniform " | ||
| 730 | "{} {};", | 736 | "{} {};", |
| 731 | image.GetIndex(), image_type, GetImage(image)); | 737 | image.GetIndex(), qualifier, image_type, GetImage(image)); |
| 732 | } | 738 | } |
| 733 | if (!images.empty()) { | 739 | if (!images.empty()) { |
| 734 | code.AddNewLine(); | 740 | code.AddNewLine(); |
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 969fe9ced..5450feedf 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -341,13 +341,16 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn | |||
| 341 | u64 index{}; | 341 | u64 index{}; |
| 342 | u32 type{}; | 342 | u32 type{}; |
| 343 | u8 is_bindless{}; | 343 | u8 is_bindless{}; |
| 344 | u8 is_read{}; | ||
| 345 | u8 is_written{}; | ||
| 344 | if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) || | 346 | if (!LoadObjectFromPrecompiled(offset) || !LoadObjectFromPrecompiled(index) || |
| 345 | !LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_bindless)) { | 347 | !LoadObjectFromPrecompiled(type) || !LoadObjectFromPrecompiled(is_bindless) || |
| 348 | !LoadObjectFromPrecompiled(is_read) || !LoadObjectFromPrecompiled(is_written)) { | ||
| 346 | return {}; | 349 | return {}; |
| 347 | } | 350 | } |
| 348 | entry.entries.images.emplace_back( | 351 | entry.entries.images.emplace_back(static_cast<u64>(offset), static_cast<std::size_t>(index), |
| 349 | static_cast<std::size_t>(offset), static_cast<std::size_t>(index), | 352 | static_cast<Tegra::Shader::ImageType>(type), |
| 350 | static_cast<Tegra::Shader::ImageType>(type), is_bindless != 0); | 353 | is_bindless != 0, is_written != 0, is_read != 0); |
| 351 | } | 354 | } |
| 352 | 355 | ||
| 353 | u32 global_memory_count{}; | 356 | u32 global_memory_count{}; |
| @@ -429,7 +432,9 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std: | |||
| 429 | if (!SaveObjectToPrecompiled(static_cast<u64>(image.GetOffset())) || | 432 | if (!SaveObjectToPrecompiled(static_cast<u64>(image.GetOffset())) || |
| 430 | !SaveObjectToPrecompiled(static_cast<u64>(image.GetIndex())) || | 433 | !SaveObjectToPrecompiled(static_cast<u64>(image.GetIndex())) || |
| 431 | !SaveObjectToPrecompiled(static_cast<u32>(image.GetType())) || | 434 | !SaveObjectToPrecompiled(static_cast<u32>(image.GetType())) || |
| 432 | !SaveObjectToPrecompiled(static_cast<u8>(image.IsBindless() ? 1 : 0))) { | 435 | !SaveObjectToPrecompiled(static_cast<u8>(image.IsBindless() ? 1 : 0)) || |
| 436 | !SaveObjectToPrecompiled(static_cast<u8>(image.IsRead() ? 1 : 0)) || | ||
| 437 | !SaveObjectToPrecompiled(static_cast<u8>(image.IsWritten() ? 1 : 0))) { | ||
| 433 | return false; | 438 | return false; |
| 434 | } | 439 | } |
| 435 | } | 440 | } |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f4777d0b0..6eabf4fac 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -34,6 +34,25 @@ bool UpdateTie(T1 current_value, const T2 new_value) { | |||
| 34 | return changed; | 34 | return changed; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | template <typename T> | ||
| 38 | std::optional<std::pair<GLuint, GLsizei>> UpdateArray(T& current_values, const T& new_values) { | ||
| 39 | std::optional<std::size_t> first; | ||
| 40 | std::size_t last; | ||
| 41 | for (std::size_t i = 0; i < std::size(current_values); ++i) { | ||
| 42 | if (!UpdateValue(current_values[i], new_values[i])) { | ||
| 43 | continue; | ||
| 44 | } | ||
| 45 | if (!first) { | ||
| 46 | first = i; | ||
| 47 | } | ||
| 48 | last = i; | ||
| 49 | } | ||
| 50 | if (!first) { | ||
| 51 | return std::nullopt; | ||
| 52 | } | ||
| 53 | return std::make_pair(static_cast<GLuint>(*first), static_cast<GLsizei>(last - *first + 1)); | ||
| 54 | } | ||
| 55 | |||
| 37 | void Enable(GLenum cap, bool enable) { | 56 | void Enable(GLenum cap, bool enable) { |
| 38 | if (enable) { | 57 | if (enable) { |
| 39 | glEnable(cap); | 58 | glEnable(cap); |
| @@ -134,10 +153,6 @@ OpenGLState::OpenGLState() { | |||
| 134 | logic_op.enabled = false; | 153 | logic_op.enabled = false; |
| 135 | logic_op.operation = GL_COPY; | 154 | logic_op.operation = GL_COPY; |
| 136 | 155 | ||
| 137 | for (auto& texture_unit : texture_units) { | ||
| 138 | texture_unit.Reset(); | ||
| 139 | } | ||
| 140 | |||
| 141 | draw.read_framebuffer = 0; | 156 | draw.read_framebuffer = 0; |
| 142 | draw.draw_framebuffer = 0; | 157 | draw.draw_framebuffer = 0; |
| 143 | draw.vertex_array = 0; | 158 | draw.vertex_array = 0; |
| @@ -496,52 +511,20 @@ void OpenGLState::ApplyAlphaTest() const { | |||
| 496 | } | 511 | } |
| 497 | 512 | ||
| 498 | void OpenGLState::ApplyTextures() const { | 513 | void OpenGLState::ApplyTextures() const { |
| 499 | bool has_delta{}; | 514 | if (const auto update = UpdateArray(cur_state.textures, textures)) { |
| 500 | std::size_t first{}; | 515 | glBindTextures(update->first, update->second, textures.data() + update->first); |
| 501 | std::size_t last{}; | ||
| 502 | std::array<GLuint, Maxwell::NumTextureSamplers> textures; | ||
| 503 | |||
| 504 | for (std::size_t i = 0; i < std::size(texture_units); ++i) { | ||
| 505 | const auto& texture_unit = texture_units[i]; | ||
| 506 | auto& cur_state_texture_unit = cur_state.texture_units[i]; | ||
| 507 | textures[i] = texture_unit.texture; | ||
| 508 | if (cur_state_texture_unit.texture == textures[i]) { | ||
| 509 | continue; | ||
| 510 | } | ||
| 511 | cur_state_texture_unit.texture = textures[i]; | ||
| 512 | if (!has_delta) { | ||
| 513 | first = i; | ||
| 514 | has_delta = true; | ||
| 515 | } | ||
| 516 | last = i; | ||
| 517 | } | ||
| 518 | if (has_delta) { | ||
| 519 | glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | ||
| 520 | textures.data() + first); | ||
| 521 | } | 516 | } |
| 522 | } | 517 | } |
| 523 | 518 | ||
| 524 | void OpenGLState::ApplySamplers() const { | 519 | void OpenGLState::ApplySamplers() const { |
| 525 | bool has_delta{}; | 520 | if (const auto update = UpdateArray(cur_state.samplers, samplers)) { |
| 526 | std::size_t first{}; | 521 | glBindSamplers(update->first, update->second, samplers.data() + update->first); |
| 527 | std::size_t last{}; | ||
| 528 | std::array<GLuint, Maxwell::NumTextureSamplers> samplers; | ||
| 529 | |||
| 530 | for (std::size_t i = 0; i < std::size(samplers); ++i) { | ||
| 531 | samplers[i] = texture_units[i].sampler; | ||
| 532 | if (cur_state.texture_units[i].sampler == texture_units[i].sampler) { | ||
| 533 | continue; | ||
| 534 | } | ||
| 535 | cur_state.texture_units[i].sampler = texture_units[i].sampler; | ||
| 536 | if (!has_delta) { | ||
| 537 | first = i; | ||
| 538 | has_delta = true; | ||
| 539 | } | ||
| 540 | last = i; | ||
| 541 | } | 522 | } |
| 542 | if (has_delta) { | 523 | } |
| 543 | glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | 524 | |
| 544 | samplers.data() + first); | 525 | void OpenGLState::ApplyImages() const { |
| 526 | if (const auto update = UpdateArray(cur_state.images, images)) { | ||
| 527 | glBindImageTextures(update->first, update->second, images.data() + update->first); | ||
| 545 | } | 528 | } |
| 546 | } | 529 | } |
| 547 | 530 | ||
| @@ -576,6 +559,7 @@ void OpenGLState::Apply() { | |||
| 576 | ApplyLogicOp(); | 559 | ApplyLogicOp(); |
| 577 | ApplyTextures(); | 560 | ApplyTextures(); |
| 578 | ApplySamplers(); | 561 | ApplySamplers(); |
| 562 | ApplyImages(); | ||
| 579 | if (dirty.polygon_offset) { | 563 | if (dirty.polygon_offset) { |
| 580 | ApplyPolygonOffset(); | 564 | ApplyPolygonOffset(); |
| 581 | dirty.polygon_offset = false; | 565 | dirty.polygon_offset = false; |
| @@ -606,18 +590,18 @@ void OpenGLState::EmulateViewportWithScissor() { | |||
| 606 | } | 590 | } |
| 607 | 591 | ||
| 608 | OpenGLState& OpenGLState::UnbindTexture(GLuint handle) { | 592 | OpenGLState& OpenGLState::UnbindTexture(GLuint handle) { |
| 609 | for (auto& unit : texture_units) { | 593 | for (auto& texture : textures) { |
| 610 | if (unit.texture == handle) { | 594 | if (texture == handle) { |
| 611 | unit.Unbind(); | 595 | texture = 0; |
| 612 | } | 596 | } |
| 613 | } | 597 | } |
| 614 | return *this; | 598 | return *this; |
| 615 | } | 599 | } |
| 616 | 600 | ||
| 617 | OpenGLState& OpenGLState::ResetSampler(GLuint handle) { | 601 | OpenGLState& OpenGLState::ResetSampler(GLuint handle) { |
| 618 | for (auto& unit : texture_units) { | 602 | for (auto& sampler : samplers) { |
| 619 | if (unit.sampler == handle) { | 603 | if (sampler == handle) { |
| 620 | unit.sampler = 0; | 604 | sampler = 0; |
| 621 | } | 605 | } |
| 622 | } | 606 | } |
| 623 | return *this; | 607 | return *this; |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index fdf9a8a12..949b13051 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -118,21 +118,9 @@ public: | |||
| 118 | GLenum operation; | 118 | GLenum operation; |
| 119 | } logic_op; | 119 | } logic_op; |
| 120 | 120 | ||
| 121 | // 3 texture units - one for each that is used in PICA fragment shader emulation | 121 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{}; |
| 122 | struct TextureUnit { | 122 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{}; |
| 123 | GLuint texture; // GL_TEXTURE_BINDING_2D | 123 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{}; |
| 124 | GLuint sampler; // GL_SAMPLER_BINDING | ||
| 125 | |||
| 126 | void Unbind() { | ||
| 127 | texture = 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | void Reset() { | ||
| 131 | Unbind(); | ||
| 132 | sampler = 0; | ||
| 133 | } | ||
| 134 | }; | ||
| 135 | std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; | ||
| 136 | 124 | ||
| 137 | struct { | 125 | struct { |
| 138 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING | 126 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING |
| @@ -220,6 +208,7 @@ public: | |||
| 220 | void ApplyLogicOp() const; | 208 | void ApplyLogicOp() const; |
| 221 | void ApplyTextures() const; | 209 | void ApplyTextures() const; |
| 222 | void ApplySamplers() const; | 210 | void ApplySamplers() const; |
| 211 | void ApplyImages() const; | ||
| 223 | void ApplyDepthClamp() const; | 212 | void ApplyDepthClamp() const; |
| 224 | void ApplyPolygonOffset() const; | 213 | void ApplyPolygonOffset() const; |
| 225 | void ApplyAlphaTest() const; | 214 | void ApplyAlphaTest() const; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 21324488a..8e13ab38b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -78,6 +78,17 @@ public: | |||
| 78 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER | 78 | /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER |
| 79 | void Attach(GLenum attachment, GLenum target) const; | 79 | void Attach(GLenum attachment, GLenum target) const; |
| 80 | 80 | ||
| 81 | void ApplySwizzle(Tegra::Texture::SwizzleSource x_source, | ||
| 82 | Tegra::Texture::SwizzleSource y_source, | ||
| 83 | Tegra::Texture::SwizzleSource z_source, | ||
| 84 | Tegra::Texture::SwizzleSource w_source); | ||
| 85 | |||
| 86 | void DecorateViewName(GPUVAddr gpu_addr, std::string prefix); | ||
| 87 | |||
| 88 | void MarkAsModified(u64 tick) { | ||
| 89 | surface.MarkAsModified(true, tick); | ||
| 90 | } | ||
| 91 | |||
| 81 | GLuint GetTexture() const { | 92 | GLuint GetTexture() const { |
| 82 | if (is_proxy) { | 93 | if (is_proxy) { |
| 83 | return surface.GetTexture(); | 94 | return surface.GetTexture(); |
| @@ -89,13 +100,6 @@ public: | |||
| 89 | return surface.GetSurfaceParams(); | 100 | return surface.GetSurfaceParams(); |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 92 | void ApplySwizzle(Tegra::Texture::SwizzleSource x_source, | ||
| 93 | Tegra::Texture::SwizzleSource y_source, | ||
| 94 | Tegra::Texture::SwizzleSource z_source, | ||
| 95 | Tegra::Texture::SwizzleSource w_source); | ||
| 96 | |||
| 97 | void DecorateViewName(GPUVAddr gpu_addr, std::string prefix); | ||
| 98 | |||
| 99 | private: | 103 | private: |
| 100 | u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, | 104 | u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, |
| 101 | Tegra::Texture::SwizzleSource y_source, | 105 | Tegra::Texture::SwizzleSource y_source, |
| @@ -111,8 +115,8 @@ private: | |||
| 111 | GLenum target{}; | 115 | GLenum target{}; |
| 112 | 116 | ||
| 113 | OGLTextureView texture_view; | 117 | OGLTextureView texture_view; |
| 114 | u32 swizzle; | 118 | u32 swizzle{}; |
| 115 | bool is_proxy; | 119 | bool is_proxy{}; |
| 116 | }; | 120 | }; |
| 117 | 121 | ||
| 118 | class TextureCacheOpenGL final : public TextureCacheBase { | 122 | class TextureCacheOpenGL final : public TextureCacheBase { |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index af9684839..839178152 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -342,7 +342,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, | |||
| 342 | ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), | 342 | ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), |
| 343 | }}; | 343 | }}; |
| 344 | 344 | ||
| 345 | state.texture_units[0].texture = screen_info.display_texture; | 345 | state.textures[0] = screen_info.display_texture; |
| 346 | // Workaround brigthness problems in SMO by enabling sRGB in the final output | 346 | // Workaround brigthness problems in SMO by enabling sRGB in the final output |
| 347 | // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 | 347 | // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 |
| 348 | state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); | 348 | state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); |
| @@ -352,7 +352,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, | |||
| 352 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 352 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 353 | // Restore default state | 353 | // Restore default state |
| 354 | state.framebuffer_srgb.enabled = false; | 354 | state.framebuffer_srgb.enabled = false; |
| 355 | state.texture_units[0].texture = 0; | 355 | state.textures[0] = 0; |
| 356 | state.AllDirty(); | 356 | state.AllDirty(); |
| 357 | state.Apply(); | 357 | state.Apply(); |
| 358 | // Clear sRGB state for the next frame | 358 | // Clear sRGB state for the next frame |
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 77151a24b..008109a99 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -61,56 +61,54 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | const auto type{instr.sust.image_type}; | 63 | const auto type{instr.sust.image_type}; |
| 64 | const auto& image{instr.sust.is_immediate ? GetImage(instr.image, type) | 64 | auto& image{instr.sust.is_immediate ? GetImage(instr.image, type) |
| 65 | : GetBindlessImage(instr.gpr39, type)}; | 65 | : GetBindlessImage(instr.gpr39, type)}; |
| 66 | image.MarkWrite(); | ||
| 67 | |||
| 66 | MetaImage meta{image, values}; | 68 | MetaImage meta{image, values}; |
| 67 | const Node store{Operation(OperationCode::ImageStore, meta, std::move(coords))}; | 69 | const Node store{Operation(OperationCode::ImageStore, meta, std::move(coords))}; |
| 68 | bb.push_back(store); | 70 | bb.push_back(store); |
| 69 | break; | 71 | break; |
| 70 | } | 72 | } |
| 71 | default: | 73 | default: |
| 72 | UNIMPLEMENTED_MSG("Unhandled conversion instruction: {}", opcode->get().GetName()); | 74 | UNIMPLEMENTED_MSG("Unhandled image instruction: {}", opcode->get().GetName()); |
| 73 | } | 75 | } |
| 74 | 76 | ||
| 75 | return pc; | 77 | return pc; |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | const Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { | 80 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { |
| 79 | const auto offset{static_cast<std::size_t>(image.index.Value())}; | 81 | const auto offset{static_cast<u64>(image.index.Value())}; |
| 80 | 82 | ||
| 81 | // If this image has already been used, return the existing mapping. | 83 | // If this image has already been used, return the existing mapping. |
| 82 | const auto itr{std::find_if(used_images.begin(), used_images.end(), | 84 | const auto it = used_images.find(offset); |
| 83 | [=](const Image& entry) { return entry.GetOffset() == offset; })}; | 85 | if (it != used_images.end()) { |
| 84 | if (itr != used_images.end()) { | 86 | ASSERT(it->second.GetType() == type); |
| 85 | ASSERT(itr->GetType() == type); | 87 | return it->second; |
| 86 | return *itr; | ||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | // Otherwise create a new mapping for this image. | 90 | // Otherwise create a new mapping for this image. |
| 90 | const std::size_t next_index{used_images.size()}; | 91 | const std::size_t next_index{used_images.size()}; |
| 91 | const Image entry{offset, next_index, type}; | 92 | return used_images.emplace(offset, Image{offset, next_index, type}).first->second; |
| 92 | return *used_images.emplace(entry).first; | ||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | const Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, | 95 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { |
| 96 | Tegra::Shader::ImageType type) { | ||
| 97 | const Node image_register{GetRegister(reg)}; | 96 | const Node image_register{GetRegister(reg)}; |
| 98 | const auto [base_image, cbuf_index, cbuf_offset]{ | 97 | const auto [base_image, cbuf_index, cbuf_offset]{ |
| 99 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; | 98 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; |
| 100 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; | 99 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; |
| 101 | 100 | ||
| 102 | // If this image has already been used, return the existing mapping. | 101 | // If this image has already been used, return the existing mapping. |
| 103 | const auto itr{std::find_if(used_images.begin(), used_images.end(), | 102 | const auto it = used_images.find(cbuf_key); |
| 104 | [=](const Image& entry) { return entry.GetOffset() == cbuf_key; })}; | 103 | if (it != used_images.end()) { |
| 105 | if (itr != used_images.end()) { | 104 | ASSERT(it->second.GetType() == type); |
| 106 | ASSERT(itr->GetType() == type); | 105 | return it->second; |
| 107 | return *itr; | ||
| 108 | } | 106 | } |
| 109 | 107 | ||
| 110 | // Otherwise create a new mapping for this image. | 108 | // Otherwise create a new mapping for this image. |
| 111 | const std::size_t next_index{used_images.size()}; | 109 | const std::size_t next_index{used_images.size()}; |
| 112 | const Image entry{cbuf_index, cbuf_offset, next_index, type}; | 110 | return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type}) |
| 113 | return *used_images.emplace(entry).first; | 111 | .first->second; |
| 114 | } | 112 | } |
| 115 | 113 | ||
| 116 | } // namespace VideoCommon::Shader | 114 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 5db9313c4..b29aedce8 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -273,46 +273,64 @@ private: | |||
| 273 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. | 273 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. |
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | class Image { | 276 | class Image final { |
| 277 | public: | 277 | public: |
| 278 | explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type) | 278 | constexpr explicit Image(u64 offset, std::size_t index, Tegra::Shader::ImageType type) |
| 279 | : offset{offset}, index{index}, type{type}, is_bindless{false} {} | 279 | : offset{offset}, index{index}, type{type}, is_bindless{false} {} |
| 280 | 280 | ||
| 281 | explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | 281 | constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, |
| 282 | Tegra::Shader::ImageType type) | 282 | Tegra::Shader::ImageType type) |
| 283 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | 283 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, |
| 284 | is_bindless{true} {} | 284 | is_bindless{true} {} |
| 285 | 285 | ||
| 286 | explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, | 286 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, |
| 287 | bool is_bindless) | 287 | bool is_bindless, bool is_written, bool is_read) |
| 288 | : offset{offset}, index{index}, type{type}, is_bindless{is_bindless} {} | 288 | : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, |
| 289 | is_written{is_written}, is_read{is_read} {} | ||
| 289 | 290 | ||
| 290 | std::size_t GetOffset() const { | 291 | void MarkRead() { |
| 292 | is_read = true; | ||
| 293 | } | ||
| 294 | |||
| 295 | void MarkWrite() { | ||
| 296 | is_written = true; | ||
| 297 | } | ||
| 298 | |||
| 299 | constexpr std::size_t GetOffset() const { | ||
| 291 | return offset; | 300 | return offset; |
| 292 | } | 301 | } |
| 293 | 302 | ||
| 294 | std::size_t GetIndex() const { | 303 | constexpr std::size_t GetIndex() const { |
| 295 | return index; | 304 | return index; |
| 296 | } | 305 | } |
| 297 | 306 | ||
| 298 | Tegra::Shader::ImageType GetType() const { | 307 | constexpr Tegra::Shader::ImageType GetType() const { |
| 299 | return type; | 308 | return type; |
| 300 | } | 309 | } |
| 301 | 310 | ||
| 302 | bool IsBindless() const { | 311 | constexpr bool IsBindless() const { |
| 303 | return is_bindless; | 312 | return is_bindless; |
| 304 | } | 313 | } |
| 305 | 314 | ||
| 306 | bool operator<(const Image& rhs) const { | 315 | constexpr bool IsRead() const { |
| 307 | return std::tie(offset, index, type, is_bindless) < | 316 | return is_read; |
| 308 | std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless); | 317 | } |
| 318 | |||
| 319 | constexpr bool IsWritten() const { | ||
| 320 | return is_written; | ||
| 321 | } | ||
| 322 | |||
| 323 | constexpr std::pair<u32, u32> GetBindlessCBuf() const { | ||
| 324 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | ||
| 309 | } | 325 | } |
| 310 | 326 | ||
| 311 | private: | 327 | private: |
| 312 | std::size_t offset{}; | 328 | u64 offset{}; |
| 313 | std::size_t index{}; | 329 | std::size_t index{}; |
| 314 | Tegra::Shader::ImageType type{}; | 330 | Tegra::Shader::ImageType type{}; |
| 315 | bool is_bindless{}; | 331 | bool is_bindless{}; |
| 332 | bool is_read{}; | ||
| 333 | bool is_written{}; | ||
| 316 | }; | 334 | }; |
| 317 | 335 | ||
| 318 | struct GlobalMemoryBase { | 336 | struct GlobalMemoryBase { |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index bcc9b79b6..0f891eace 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -95,7 +95,7 @@ public: | |||
| 95 | return used_samplers; | 95 | return used_samplers; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | const std::set<Image>& GetImages() const { | 98 | const std::map<u64, Image>& GetImages() const { |
| 99 | return used_images; | 99 | return used_images; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -272,10 +272,10 @@ private: | |||
| 272 | bool is_shadow); | 272 | bool is_shadow); |
| 273 | 273 | ||
| 274 | /// Accesses an image. | 274 | /// Accesses an image. |
| 275 | const Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); | 275 | Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); |
| 276 | 276 | ||
| 277 | /// Access a bindless image sampler. | 277 | /// Access a bindless image sampler. |
| 278 | const Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); | 278 | Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); |
| 279 | 279 | ||
| 280 | /// Extracts a sequence of bits from a node | 280 | /// Extracts a sequence of bits from a node |
| 281 | Node BitfieldExtract(Node value, u32 offset, u32 bits); | 281 | Node BitfieldExtract(Node value, u32 offset, u32 bits); |
| @@ -356,7 +356,7 @@ private: | |||
| 356 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; | 356 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; |
| 357 | std::map<u32, ConstBuffer> used_cbufs; | 357 | std::map<u32, ConstBuffer> used_cbufs; |
| 358 | std::set<Sampler> used_samplers; | 358 | std::set<Sampler> used_samplers; |
| 359 | std::set<Image> used_images; | 359 | std::map<u64, Image> used_images; |
| 360 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | 360 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; |
| 361 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; | 361 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; |
| 362 | bool uses_layer{}; | 362 | bool uses_layer{}; |
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index bcce8d863..5e497e49f 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h | |||
| @@ -195,18 +195,18 @@ public: | |||
| 195 | 195 | ||
| 196 | virtual void DownloadTexture(std::vector<u8>& staging_buffer) = 0; | 196 | virtual void DownloadTexture(std::vector<u8>& staging_buffer) = 0; |
| 197 | 197 | ||
| 198 | void MarkAsModified(const bool is_modified_, const u64 tick) { | 198 | void MarkAsModified(bool is_modified_, u64 tick) { |
| 199 | is_modified = is_modified_ || is_target; | 199 | is_modified = is_modified_ || is_target; |
| 200 | modification_tick = tick; | 200 | modification_tick = tick; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | void MarkAsRenderTarget(const bool is_target, const u32 index) { | 203 | void MarkAsRenderTarget(bool is_target_, u32 index_) { |
| 204 | this->is_target = is_target; | 204 | is_target = is_target_; |
| 205 | this->index = index; | 205 | index = index_; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | void MarkAsPicked(const bool is_picked) { | 208 | void MarkAsPicked(bool is_picked_) { |
| 209 | this->is_picked = is_picked; | 209 | is_picked = is_picked_; |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | bool IsModified() const { | 212 | bool IsModified() const { |
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp index fd5472451..1e4d3fb79 100644 --- a/src/video_core/texture_cache/surface_params.cpp +++ b/src/video_core/texture_cache/surface_params.cpp | |||
| @@ -24,55 +24,62 @@ using VideoCore::Surface::SurfaceTarget; | |||
| 24 | using VideoCore::Surface::SurfaceTargetFromTextureType; | 24 | using VideoCore::Surface::SurfaceTargetFromTextureType; |
| 25 | using VideoCore::Surface::SurfaceType; | 25 | using VideoCore::Surface::SurfaceType; |
| 26 | 26 | ||
| 27 | SurfaceTarget TextureType2SurfaceTarget(Tegra::Shader::TextureType type, bool is_array) { | 27 | namespace { |
| 28 | |||
| 29 | SurfaceTarget TextureTypeToSurfaceTarget(Tegra::Shader::TextureType type, bool is_array) { | ||
| 28 | switch (type) { | 30 | switch (type) { |
| 29 | case Tegra::Shader::TextureType::Texture1D: { | 31 | case Tegra::Shader::TextureType::Texture1D: |
| 30 | if (is_array) | 32 | return is_array ? SurfaceTarget::Texture1DArray : SurfaceTarget::Texture1D; |
| 31 | return SurfaceTarget::Texture1DArray; | 33 | case Tegra::Shader::TextureType::Texture2D: |
| 32 | else | 34 | return is_array ? SurfaceTarget::Texture2DArray : SurfaceTarget::Texture2D; |
| 33 | return SurfaceTarget::Texture1D; | 35 | case Tegra::Shader::TextureType::Texture3D: |
| 34 | } | ||
| 35 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 36 | if (is_array) | ||
| 37 | return SurfaceTarget::Texture2DArray; | ||
| 38 | else | ||
| 39 | return SurfaceTarget::Texture2D; | ||
| 40 | } | ||
| 41 | case Tegra::Shader::TextureType::Texture3D: { | ||
| 42 | ASSERT(!is_array); | 36 | ASSERT(!is_array); |
| 43 | return SurfaceTarget::Texture3D; | 37 | return SurfaceTarget::Texture3D; |
| 44 | } | 38 | case Tegra::Shader::TextureType::TextureCube: |
| 45 | case Tegra::Shader::TextureType::TextureCube: { | 39 | return is_array ? SurfaceTarget::TextureCubeArray : SurfaceTarget::TextureCubemap; |
| 46 | if (is_array) | 40 | default: |
| 47 | return SurfaceTarget::TextureCubeArray; | ||
| 48 | else | ||
| 49 | return SurfaceTarget::TextureCubemap; | ||
| 50 | } | ||
| 51 | default: { | ||
| 52 | UNREACHABLE(); | 41 | UNREACHABLE(); |
| 53 | return SurfaceTarget::Texture2D; | 42 | return SurfaceTarget::Texture2D; |
| 54 | } | 43 | } |
| 44 | } | ||
| 45 | |||
| 46 | SurfaceTarget ImageTypeToSurfaceTarget(Tegra::Shader::ImageType type) { | ||
| 47 | switch (type) { | ||
| 48 | case Tegra::Shader::ImageType::Texture1D: | ||
| 49 | return SurfaceTarget::Texture1D; | ||
| 50 | case Tegra::Shader::ImageType::TextureBuffer: | ||
| 51 | return SurfaceTarget::TextureBuffer; | ||
| 52 | case Tegra::Shader::ImageType::Texture1DArray: | ||
| 53 | return SurfaceTarget::Texture1DArray; | ||
| 54 | case Tegra::Shader::ImageType::Texture2D: | ||
| 55 | return SurfaceTarget::Texture2D; | ||
| 56 | case Tegra::Shader::ImageType::Texture2DArray: | ||
| 57 | return SurfaceTarget::Texture2DArray; | ||
| 58 | case Tegra::Shader::ImageType::Texture3D: | ||
| 59 | return SurfaceTarget::Texture3D; | ||
| 60 | default: | ||
| 61 | UNREACHABLE(); | ||
| 62 | return SurfaceTarget::Texture2D; | ||
| 55 | } | 63 | } |
| 56 | } | 64 | } |
| 57 | 65 | ||
| 58 | namespace { | ||
| 59 | constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { | 66 | constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { |
| 60 | return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile); | 67 | return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile); |
| 61 | } | 68 | } |
| 69 | |||
| 62 | } // Anonymous namespace | 70 | } // Anonymous namespace |
| 63 | 71 | ||
| 64 | SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, | 72 | SurfaceParams SurfaceParams::CreateForTexture(const Tegra::Texture::TICEntry& tic, |
| 65 | const Tegra::Texture::FullTextureInfo& config, | ||
| 66 | const VideoCommon::Shader::Sampler& entry) { | 73 | const VideoCommon::Shader::Sampler& entry) { |
| 67 | SurfaceParams params; | 74 | SurfaceParams params; |
| 68 | params.is_tiled = config.tic.IsTiled(); | 75 | params.is_tiled = tic.IsTiled(); |
| 69 | params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); | 76 | params.srgb_conversion = tic.IsSrgbConversionEnabled(); |
| 70 | params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0, | 77 | params.block_width = params.is_tiled ? tic.BlockWidth() : 0, |
| 71 | params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, | 78 | params.block_height = params.is_tiled ? tic.BlockHeight() : 0, |
| 72 | params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0, | 79 | params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, |
| 73 | params.tile_width_spacing = params.is_tiled ? (1 << config.tic.tile_width_spacing.Value()) : 1; | 80 | params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; |
| 74 | params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), | 81 | params.pixel_format = |
| 75 | params.srgb_conversion); | 82 | PixelFormatFromTextureFormat(tic.format, tic.r_type.Value(), params.srgb_conversion); |
| 76 | params.type = GetFormatType(params.pixel_format); | 83 | params.type = GetFormatType(params.pixel_format); |
| 77 | if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { | 84 | if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { |
| 78 | switch (params.pixel_format) { | 85 | switch (params.pixel_format) { |
| @@ -92,31 +99,72 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, | |||
| 92 | } | 99 | } |
| 93 | params.type = GetFormatType(params.pixel_format); | 100 | params.type = GetFormatType(params.pixel_format); |
| 94 | } | 101 | } |
| 95 | params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); | 102 | params.component_type = ComponentTypeFromTexture(tic.r_type.Value()); |
| 96 | params.type = GetFormatType(params.pixel_format); | 103 | params.type = GetFormatType(params.pixel_format); |
| 97 | // TODO: on 1DBuffer we should use the tic info. | 104 | // TODO: on 1DBuffer we should use the tic info. |
| 98 | if (!config.tic.IsBuffer()) { | 105 | if (tic.IsBuffer()) { |
| 99 | params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray()); | 106 | params.target = SurfaceTarget::TextureBuffer; |
| 100 | params.width = config.tic.Width(); | 107 | params.width = tic.Width(); |
| 101 | params.height = config.tic.Height(); | 108 | params.pitch = params.width * params.GetBytesPerPixel(); |
| 102 | params.depth = config.tic.Depth(); | 109 | params.height = 1; |
| 103 | params.pitch = params.is_tiled ? 0 : config.tic.Pitch(); | 110 | params.depth = 1; |
| 111 | params.num_levels = 1; | ||
| 112 | params.emulated_levels = 1; | ||
| 113 | params.is_layered = false; | ||
| 114 | } else { | ||
| 115 | params.target = TextureTypeToSurfaceTarget(entry.GetType(), entry.IsArray()); | ||
| 116 | params.width = tic.Width(); | ||
| 117 | params.height = tic.Height(); | ||
| 118 | params.depth = tic.Depth(); | ||
| 119 | params.pitch = params.is_tiled ? 0 : tic.Pitch(); | ||
| 104 | if (params.target == SurfaceTarget::TextureCubemap || | 120 | if (params.target == SurfaceTarget::TextureCubemap || |
| 105 | params.target == SurfaceTarget::TextureCubeArray) { | 121 | params.target == SurfaceTarget::TextureCubeArray) { |
| 106 | params.depth *= 6; | 122 | params.depth *= 6; |
| 107 | } | 123 | } |
| 108 | params.num_levels = config.tic.max_mip_level + 1; | 124 | params.num_levels = tic.max_mip_level + 1; |
| 109 | params.emulated_levels = std::min(params.num_levels, params.MaxPossibleMipmap()); | 125 | params.emulated_levels = std::min(params.num_levels, params.MaxPossibleMipmap()); |
| 110 | params.is_layered = params.IsLayered(); | 126 | params.is_layered = params.IsLayered(); |
| 111 | } else { | 127 | } |
| 128 | return params; | ||
| 129 | } | ||
| 130 | |||
| 131 | SurfaceParams SurfaceParams::CreateForImage(const Tegra::Texture::TICEntry& tic, | ||
| 132 | const VideoCommon::Shader::Image& entry) { | ||
| 133 | SurfaceParams params; | ||
| 134 | params.is_tiled = tic.IsTiled(); | ||
| 135 | params.srgb_conversion = tic.IsSrgbConversionEnabled(); | ||
| 136 | params.block_width = params.is_tiled ? tic.BlockWidth() : 0, | ||
| 137 | params.block_height = params.is_tiled ? tic.BlockHeight() : 0, | ||
| 138 | params.block_depth = params.is_tiled ? tic.BlockDepth() : 0, | ||
| 139 | params.tile_width_spacing = params.is_tiled ? (1 << tic.tile_width_spacing.Value()) : 1; | ||
| 140 | params.pixel_format = | ||
| 141 | PixelFormatFromTextureFormat(tic.format, tic.r_type.Value(), params.srgb_conversion); | ||
| 142 | params.type = GetFormatType(params.pixel_format); | ||
| 143 | params.component_type = ComponentTypeFromTexture(tic.r_type.Value()); | ||
| 144 | params.type = GetFormatType(params.pixel_format); | ||
| 145 | params.target = ImageTypeToSurfaceTarget(entry.GetType()); | ||
| 146 | // TODO: on 1DBuffer we should use the tic info. | ||
| 147 | if (tic.IsBuffer()) { | ||
| 112 | params.target = SurfaceTarget::TextureBuffer; | 148 | params.target = SurfaceTarget::TextureBuffer; |
| 113 | params.width = config.tic.Width(); | 149 | params.width = tic.Width(); |
| 114 | params.pitch = params.width * params.GetBytesPerPixel(); | 150 | params.pitch = params.width * params.GetBytesPerPixel(); |
| 115 | params.height = 1; | 151 | params.height = 1; |
| 116 | params.depth = 1; | 152 | params.depth = 1; |
| 117 | params.num_levels = 1; | 153 | params.num_levels = 1; |
| 118 | params.emulated_levels = 1; | 154 | params.emulated_levels = 1; |
| 119 | params.is_layered = false; | 155 | params.is_layered = false; |
| 156 | } else { | ||
| 157 | params.width = tic.Width(); | ||
| 158 | params.height = tic.Height(); | ||
| 159 | params.depth = tic.Depth(); | ||
| 160 | params.pitch = params.is_tiled ? 0 : tic.Pitch(); | ||
| 161 | if (params.target == SurfaceTarget::TextureCubemap || | ||
| 162 | params.target == SurfaceTarget::TextureCubeArray) { | ||
| 163 | params.depth *= 6; | ||
| 164 | } | ||
| 165 | params.num_levels = tic.max_mip_level + 1; | ||
| 166 | params.emulated_levels = std::min(params.num_levels, params.MaxPossibleMipmap()); | ||
| 167 | params.is_layered = params.IsLayered(); | ||
| 120 | } | 168 | } |
| 121 | return params; | 169 | return params; |
| 122 | } | 170 | } |
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h index e7ef66ee2..c58e7f8a4 100644 --- a/src/video_core/texture_cache/surface_params.h +++ b/src/video_core/texture_cache/surface_params.h | |||
| @@ -4,8 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <map> | ||
| 8 | |||
| 9 | #include "common/alignment.h" | 7 | #include "common/alignment.h" |
| 10 | #include "common/bit_util.h" | 8 | #include "common/bit_util.h" |
| 11 | #include "common/cityhash.h" | 9 | #include "common/cityhash.h" |
| @@ -23,10 +21,13 @@ using VideoCore::Surface::SurfaceCompression; | |||
| 23 | class SurfaceParams { | 21 | class SurfaceParams { |
| 24 | public: | 22 | public: |
| 25 | /// Creates SurfaceCachedParams from a texture configuration. | 23 | /// Creates SurfaceCachedParams from a texture configuration. |
| 26 | static SurfaceParams CreateForTexture(Core::System& system, | 24 | static SurfaceParams CreateForTexture(const Tegra::Texture::TICEntry& tic, |
| 27 | const Tegra::Texture::FullTextureInfo& config, | ||
| 28 | const VideoCommon::Shader::Sampler& entry); | 25 | const VideoCommon::Shader::Sampler& entry); |
| 29 | 26 | ||
| 27 | /// Creates SurfaceCachedParams from an image configuration. | ||
| 28 | static SurfaceParams CreateForImage(const Tegra::Texture::TICEntry& tic, | ||
| 29 | const VideoCommon::Shader::Image& entry); | ||
| 30 | |||
| 30 | /// Creates SurfaceCachedParams for a depth buffer configuration. | 31 | /// Creates SurfaceCachedParams for a depth buffer configuration. |
| 31 | static SurfaceParams CreateForDepthBuffer( | 32 | static SurfaceParams CreateForDepthBuffer( |
| 32 | Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format, | 33 | Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format, |
diff --git a/src/video_core/texture_cache/surface_view.cpp b/src/video_core/texture_cache/surface_view.cpp index 467696a4c..57a1f5803 100644 --- a/src/video_core/texture_cache/surface_view.cpp +++ b/src/video_core/texture_cache/surface_view.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | namespace VideoCommon { | 10 | namespace VideoCommon { |
| 11 | 11 | ||
| 12 | std::size_t ViewParams::Hash() const { | 12 | std::size_t ViewParams::Hash() const { |
| 13 | return static_cast<std::size_t>(base_layer) ^ static_cast<std::size_t>(num_layers << 16) ^ | 13 | return static_cast<std::size_t>(base_layer) ^ (static_cast<std::size_t>(num_layers) << 16) ^ |
| 14 | (static_cast<std::size_t>(base_level) << 24) ^ | 14 | (static_cast<std::size_t>(base_level) << 24) ^ |
| 15 | (static_cast<std::size_t>(num_levels) << 32) ^ (static_cast<std::size_t>(target) << 36); | 15 | (static_cast<std::size_t>(num_levels) << 32) ^ (static_cast<std::size_t>(target) << 36); |
| 16 | } | 16 | } |
diff --git a/src/video_core/texture_cache/surface_view.h b/src/video_core/texture_cache/surface_view.h index 04ca5639b..b17fd11a9 100644 --- a/src/video_core/texture_cache/surface_view.h +++ b/src/video_core/texture_cache/surface_view.h | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | namespace VideoCommon { | 13 | namespace VideoCommon { |
| 14 | 14 | ||
| 15 | struct ViewParams { | 15 | struct ViewParams { |
| 16 | ViewParams(VideoCore::Surface::SurfaceTarget target, u32 base_layer, u32 num_layers, | 16 | constexpr explicit ViewParams(VideoCore::Surface::SurfaceTarget target, u32 base_layer, |
| 17 | u32 base_level, u32 num_levels) | 17 | u32 num_layers, u32 base_level, u32 num_levels) |
| 18 | : target{target}, base_layer{base_layer}, num_layers{num_layers}, base_level{base_level}, | 18 | : target{target}, base_layer{base_layer}, num_layers{num_layers}, base_level{base_level}, |
| 19 | num_levels{num_levels} {} | 19 | num_levels{num_levels} {} |
| 20 | 20 | ||
| @@ -22,12 +22,6 @@ struct ViewParams { | |||
| 22 | 22 | ||
| 23 | bool operator==(const ViewParams& rhs) const; | 23 | bool operator==(const ViewParams& rhs) const; |
| 24 | 24 | ||
| 25 | VideoCore::Surface::SurfaceTarget target{}; | ||
| 26 | u32 base_layer{}; | ||
| 27 | u32 num_layers{}; | ||
| 28 | u32 base_level{}; | ||
| 29 | u32 num_levels{}; | ||
| 30 | |||
| 31 | bool IsLayered() const { | 25 | bool IsLayered() const { |
| 32 | switch (target) { | 26 | switch (target) { |
| 33 | case VideoCore::Surface::SurfaceTarget::Texture1DArray: | 27 | case VideoCore::Surface::SurfaceTarget::Texture1DArray: |
| @@ -39,13 +33,19 @@ struct ViewParams { | |||
| 39 | return false; | 33 | return false; |
| 40 | } | 34 | } |
| 41 | } | 35 | } |
| 36 | |||
| 37 | VideoCore::Surface::SurfaceTarget target{}; | ||
| 38 | u32 base_layer{}; | ||
| 39 | u32 num_layers{}; | ||
| 40 | u32 base_level{}; | ||
| 41 | u32 num_levels{}; | ||
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | class ViewBase { | 44 | class ViewBase { |
| 45 | public: | 45 | public: |
| 46 | ViewBase(const ViewParams& params) : params{params} {} | 46 | constexpr explicit ViewBase(const ViewParams& params) : params{params} {} |
| 47 | 47 | ||
| 48 | const ViewParams& GetViewParams() const { | 48 | constexpr const ViewParams& GetViewParams() const { |
| 49 | return params; | 49 | return params; |
| 50 | } | 50 | } |
| 51 | 51 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 2ec0203d1..877c6635d 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -89,14 +89,29 @@ public: | |||
| 89 | } | 89 | } |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | TView GetTextureSurface(const Tegra::Texture::FullTextureInfo& config, | 92 | TView GetTextureSurface(const Tegra::Texture::TICEntry& tic, |
| 93 | const VideoCommon::Shader::Sampler& entry) { | 93 | const VideoCommon::Shader::Sampler& entry) { |
| 94 | std::lock_guard lock{mutex}; | 94 | std::lock_guard lock{mutex}; |
| 95 | const auto gpu_addr{config.tic.Address()}; | 95 | const auto gpu_addr{tic.Address()}; |
| 96 | if (!gpu_addr) { | 96 | if (!gpu_addr) { |
| 97 | return {}; | 97 | return {}; |
| 98 | } | 98 | } |
| 99 | const auto params{SurfaceParams::CreateForTexture(system, config, entry)}; | 99 | const auto params{SurfaceParams::CreateForTexture(tic, entry)}; |
| 100 | const auto [surface, view] = GetSurface(gpu_addr, params, true, false); | ||
| 101 | if (guard_samplers) { | ||
| 102 | sampled_textures.push_back(surface); | ||
| 103 | } | ||
| 104 | return view; | ||
| 105 | } | ||
| 106 | |||
| 107 | TView GetImageSurface(const Tegra::Texture::TICEntry& tic, | ||
| 108 | const VideoCommon::Shader::Image& entry) { | ||
| 109 | std::lock_guard lock{mutex}; | ||
| 110 | const auto gpu_addr{tic.Address()}; | ||
| 111 | if (!gpu_addr) { | ||
| 112 | return {}; | ||
| 113 | } | ||
| 114 | const auto params{SurfaceParams::CreateForImage(tic, entry)}; | ||
| 100 | const auto [surface, view] = GetSurface(gpu_addr, params, true, false); | 115 | const auto [surface, view] = GetSurface(gpu_addr, params, true, false); |
| 101 | if (guard_samplers) { | 116 | if (guard_samplers) { |
| 102 | sampled_textures.push_back(surface); | 117 | sampled_textures.push_back(surface); |