From 33fcec3502f5dd5a99b7a8337128b7c99bfba908 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 09:53:18 -0400 Subject: Shader_IR: allow lookup of texture samplers within the shader_ir for instructions that don't provide it --- .../engines/const_buffer_engine_interface.h | 95 +++++++++++++++++- src/video_core/engines/kepler_compute.cpp | 18 ++++ src/video_core/engines/kepler_compute.h | 13 ++- src/video_core/engines/maxwell_3d.cpp | 18 ++++ src/video_core/engines/maxwell_3d.h | 11 ++- src/video_core/shader/const_buffer_locker.cpp | 110 ++++++++++++++++++--- src/video_core/shader/const_buffer_locker.h | 60 ++++++++++- src/video_core/shader/decode/texture.cpp | 72 ++++++++++---- src/video_core/shader/shader_ir.h | 12 ++- 9 files changed, 363 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/video_core/engines/const_buffer_engine_interface.h b/src/video_core/engines/const_buffer_engine_interface.h index cc41a9cac..c0e3a3a17 100644 --- a/src/video_core/engines/const_buffer_engine_interface.h +++ b/src/video_core/engines/const_buffer_engine_interface.h @@ -4,7 +4,10 @@ #pragma once +#include "common/bit_field.h" #include "common/common_types.h" +#include "video_core/engines/shader_bytecode.h" +#include "video_core/textures/texture.h" namespace Tegra::Engines { @@ -17,10 +20,100 @@ enum class ShaderType : u32 { Compute = 5, }; +struct SamplerDescriptor { + union { + BitField<0, 20, Tegra::Shader::TextureType> texture_type; + BitField<20, 1, u32> is_array; + BitField<21, 1, u32> is_buffer; + BitField<22, 1, u32> is_shadow; + u32 raw{}; + }; + + static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) { + SamplerDescriptor result{}; + switch (tic_texture_type) { + case Tegra::Texture::TextureType::Texture1D: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture2D: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture3D: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture3D); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::TextureCubemap: { + result.texture_type.Assign(Tegra::Shader::TextureType::TextureCube); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture1DArray: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D); + result.is_array.Assign(1); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture2DArray: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); + result.is_array.Assign(1); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture1DBuffer: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D); + result.is_array.Assign(0); + result.is_buffer.Assign(1); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::Texture2DNoMipmap: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + case Tegra::Texture::TextureType::TextureCubeArray: { + result.texture_type.Assign(Tegra::Shader::TextureType::TextureCube); + result.is_array.Assign(1); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + default: { + result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); + result.is_array.Assign(0); + result.is_buffer.Assign(0); + result.is_shadow.Assign(0); + return result; + } + } + } +}; + class ConstBufferEngineInterface { public: virtual ~ConstBufferEngineInterface() {} virtual u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const = 0; + virtual SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const = 0; + virtual SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer, + u64 offset) const = 0; + virtual u32 GetBoundBuffer() const = 0; }; -} +} // namespace Tegra::Engines diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index ba97c2894..6f00db1c1 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp @@ -78,6 +78,24 @@ u32 KeplerCompute::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 o return result; } +SamplerDescriptor KeplerCompute::AccessBoundSampler(ShaderType stage, u64 offset) const { + return AccessBindlessSampler(stage, regs.tex_cb_index, offset * sizeof(Texture::TextureHandle)); +} + +SamplerDescriptor KeplerCompute::AccessBindlessSampler(ShaderType stage, u64 const_buffer, + u64 offset) const { + ASSERT(stage == ShaderType::Compute); + const auto& tex_info_buffer = launch_description.const_buffer_config[const_buffer]; + const GPUVAddr tex_info_address = + tex_info_buffer.Address() + offset; + + const Texture::TextureHandle tex_handle{memory_manager.Read(tex_info_address)}; + const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle, offset); + SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value()); + result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value()); + return result; +} + void KeplerCompute::ProcessLaunch() { const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address(); memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description, diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index d7e0dfcd6..8e7182727 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h @@ -10,8 +10,8 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "video_core/engines/engine_upload.h" #include "video_core/engines/const_buffer_engine_interface.h" +#include "video_core/engines/engine_upload.h" #include "video_core/gpu.h" #include "video_core/textures/texture.h" @@ -38,7 +38,7 @@ namespace Tegra::Engines { #define KEPLER_COMPUTE_REG_INDEX(field_name) \ (offsetof(Tegra::Engines::KeplerCompute::Regs, field_name) / sizeof(u32)) -class KeplerCompute final : public ConstBufferEngineInterface { +class KeplerCompute final : public ConstBufferEngineInterface { public: explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager); @@ -204,6 +204,15 @@ public: u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const override; + SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const override; + + SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer, + u64 offset) const override; + + u32 GetBoundBuffer() const override { + return regs.tex_cb_index; + } + private: Core::System& system; VideoCore::RasterizerInterface& rasterizer; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 92e38b071..558955451 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -856,4 +856,22 @@ u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offse return result; } +SamplerDescriptor Maxwell3D::AccessBoundSampler(ShaderType stage, u64 offset) const { + return AccessBindlessSampler(stage, regs.tex_cb_index, offset * sizeof(Texture::TextureHandle)); +} + +SamplerDescriptor Maxwell3D::AccessBindlessSampler(ShaderType stage, u64 const_buffer, + u64 offset) const { + ASSERT(stage != ShaderType::Compute); + const auto& shader = state.shader_stages[static_cast(stage)]; + const auto& tex_info_buffer = shader.const_buffers[const_buffer]; + const GPUVAddr tex_info_address = tex_info_buffer.address + offset; + + const Texture::TextureHandle tex_handle{memory_manager.Read(tex_info_address)}; + const Texture::FullTextureInfo tex_info = GetTextureInfo(tex_handle, offset); + SamplerDescriptor result = SamplerDescriptor::FromTicTexture(tex_info.tic.texture_type.Value()); + result.is_shadow.Assign(tex_info.tsc.depth_compare_enabled.Value()); + return result; +} + } // namespace Tegra::Engines diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 04d02d208..fa846a621 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -15,8 +15,8 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/math_util.h" -#include "video_core/engines/const_buffer_info.h" #include "video_core/engines/const_buffer_engine_interface.h" +#include "video_core/engines/const_buffer_info.h" #include "video_core/engines/engine_upload.h" #include "video_core/gpu.h" #include "video_core/macro_interpreter.h" @@ -1260,6 +1260,15 @@ public: u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const override; + SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const override; + + SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer, + u64 offset) const override; + + u32 GetBoundBuffer() const override { + return regs.tex_cb_index; + } + /// Memory for macro code - it's undetermined how big this is, however 1MB is much larger than /// we've seen used. using MacroMemory = std::array; diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 6a9e0ed5e..4f5de8ae9 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -27,43 +27,121 @@ void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface* en } std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { + if (!keys) { + keys = std::make_shared(); + } + auto& key_map = *keys; const std::pair key = {buffer, offset}; - const auto iter = keys.find(key); - if (iter != keys.end()) { + const auto iter = key_map.find(key); + if (iter != key_map.end()) { return {iter->second}; } if (!IsEngineSet()) { return {}; } const u32 value = engine->AccessConstBuffer32(shader_stage, buffer, offset); - keys.emplace(key, value); + key_map.emplace(key, value); + return {value}; +} + +std::optional ConstBufferLocker::ObtainBoundSampler(u32 offset) { + if (!bound_samplers) { + bound_samplers = std::make_shared(); + } + auto& key_map = *bound_samplers; + const u32 key = offset; + const auto iter = key_map.find(key); + if (iter != key_map.end()) { + return {iter->second}; + } + if (!IsEngineSet()) { + return {}; + } + const Tegra::Engines::SamplerDescriptor value = + engine->AccessBoundSampler(shader_stage, offset); + key_map.emplace(key, value); + return {value}; +} + +std::optional ConstBufferLocker::ObtainBindlessSampler( + u32 buffer, u32 offset) { + if (!bindless_samplers) { + bindless_samplers = std::make_shared(); + } + auto& key_map = *bindless_samplers; + const std::pair key = {buffer, offset}; + const auto iter = key_map.find(key); + if (iter != key_map.end()) { + return {iter->second}; + } + if (!IsEngineSet()) { + return {}; + } + const Tegra::Engines::SamplerDescriptor value = + engine->AccessBindlessSampler(shader_stage, buffer, offset); + key_map.emplace(key, value); return {value}; } void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) { + if (!keys) { + keys = std::make_shared(); + } const std::pair key = {buffer, offset}; - keys[key] = value; + (*keys)[key] = value; } -u32 ConstBufferLocker::NumKeys() const { - return keys.size(); +void ConstBufferLocker::InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler) { + if (!bound_samplers) { + bound_samplers = std::make_shared(); + } + (*bound_samplers)[offset] = sampler; } -const std::unordered_map, u32, Common::PairHash>& -ConstBufferLocker::AccessKeys() const { - return keys; +void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, + Tegra::Engines::SamplerDescriptor sampler) { + if (!bindless_samplers) { + bindless_samplers = std::make_shared(); + } + const std::pair key = {buffer, offset}; + (*bindless_samplers)[key] = sampler; } -bool ConstBufferLocker::AreKeysConsistant() const { +bool ConstBufferLocker::IsConsistant() const { if (!IsEngineSet()) { return false; } - for (const auto& key_val : keys) { - const std::pair key = key_val.first; - const u32 value = key_val.second; - const u32 other_value = engine->AccessConstBuffer32(shader_stage, key.first, key.second); - if (other_value != value) { - return false; + if (keys) { + for (const auto& key_val : *keys) { + const std::pair key = key_val.first; + const u32 value = key_val.second; + const u32 other_value = + engine->AccessConstBuffer32(shader_stage, key.first, key.second); + if (other_value != value) { + return false; + } + } + } + if (bound_samplers) { + for (const auto& sampler_val : *bound_samplers) { + const u32 key = sampler_val.first; + const Tegra::Engines::SamplerDescriptor value = sampler_val.second; + const Tegra::Engines::SamplerDescriptor other_value = + engine->AccessBoundSampler(shader_stage, key); + if (other_value.raw != value.raw) { + return false; + } + } + } + if (bindless_samplers) { + for (const auto& sampler_val : *bindless_samplers) { + const std::pair key = sampler_val.first; + const Tegra::Engines::SamplerDescriptor value = sampler_val.second; + const Tegra::Engines::SamplerDescriptor other_value = + engine->AccessBindlessSampler(shader_stage, key.first, key.second); + if (other_value.raw != value.raw) { + return false; + } } } return true; diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h index 39e62584d..0bc257781 100644 --- a/src/video_core/shader/const_buffer_locker.h +++ b/src/video_core/shader/const_buffer_locker.h @@ -11,6 +11,11 @@ namespace VideoCommon::Shader { +using KeyMap = std::unordered_map, u32, Common::PairHash>; +using BoundSamplerMap = std::unordered_map; +using BindlessSamplerMap = + std::unordered_map, Tegra::Engines::SamplerDescriptor, Common::PairHash>; + class ConstBufferLocker { public: explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage); @@ -29,22 +34,67 @@ public: // registered value, if not it will obtain it from maxwell3d and register it. std::optional ObtainKey(u32 buffer, u32 offset); + std::optional ObtainBoundSampler(u32 offset); + + std::optional ObtainBindlessSampler(u32 buffer, u32 offset); + // Manually inserts a key. void InsertKey(u32 buffer, u32 offset, u32 value); + void InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler); + + void InsertBindlessSampler(u32 buffer, u32 offset, Tegra::Engines::SamplerDescriptor sampler); + // Retrieves the number of keys registered. - u32 NumKeys() const; + std::size_t NumKeys() const { + if (!keys) { + return 0; + } + return keys->size(); + } + + std::size_t NumBoundSamplers() const { + if (!bound_samplers) { + return 0; + } + return bound_samplers->size(); + } + + std::size_t NumBindlessSamplers() const { + if (!bindless_samplers) { + return 0; + } + return bindless_samplers->size(); + } // Gives an accessor to the key's database. - const std::unordered_map, u32, Common::PairHash>& AccessKeys() const; + // Pre: NumKeys > 0 + const KeyMap& AccessKeys() const { + return *keys; + } + + // Gives an accessor to the sampler's database. + // Pre: NumBindlessSamplers > 0 + const BoundSamplerMap& AccessBoundSamplers() const { + return *bound_samplers; + } + + // Gives an accessor to the sampler's database. + // Pre: NumBindlessSamplers > 0 + const BindlessSamplerMap& AccessBindlessSamplers() const { + return *bindless_samplers; + } - // Checks keys against maxwell3d's current const buffers. Returns true if they + // Checks keys & samplers against engine's current const buffers. Returns true if they // are the same value, false otherwise; - bool AreKeysConsistant() const; + bool IsConsistant() const; private: Tegra::Engines::ConstBufferEngineInterface* engine; Tegra::Engines::ShaderType shader_stage; - std::unordered_map, u32, Common::PairHash> keys{}; + // All containers are lazy initialized as most shaders don't use them. + std::shared_ptr keys{}; + std::shared_ptr bound_samplers{}; + std::shared_ptr bindless_samplers{}; }; } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 0b934a069..c369e23ad 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -141,7 +141,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const Node component = Immediate(static_cast(instr.tld4s.component)); const auto& sampler = - GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); + GetSampler(instr.sampler, {{TextureType::Texture2D, false, depth_compare}}); Node4 values; for (u32 element = 0; element < values.size(); ++element) { @@ -165,10 +165,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { // Sadly, not all texture instructions specify the type of texture their sampler // uses. This must be fixed at a later instance. const auto& sampler = - is_bindless - ? GetBindlessSampler(instr.gpr8, Tegra::Shader::TextureType::Texture2D, false, - false) - : GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false); + is_bindless ? GetBindlessSampler(instr.gpr8, {}) : GetSampler(instr.sampler, {}); u32 indexer = 0; switch (instr.txq.query_type) { @@ -207,9 +204,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { auto texture_type = instr.tmml.texture_type.Value(); const bool is_array = instr.tmml.array != 0; - const auto& sampler = is_bindless - ? GetBindlessSampler(instr.gpr20, texture_type, is_array, false) - : GetSampler(instr.sampler, texture_type, is_array, false); + const auto& sampler = + is_bindless ? GetBindlessSampler(instr.gpr20, {{texture_type, is_array, false}}) + : GetSampler(instr.sampler, {{texture_type, is_array, false}}); std::vector coords; @@ -285,10 +282,30 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { return pc; } -const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, TextureType type, - bool is_array, bool is_shadow) { +const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, + std::optional sampler_info) { const auto offset = static_cast(sampler.index.Value()); + Tegra::Shader::TextureType type; + bool is_array; + bool is_shadow; + if (sampler_info) { + type = sampler_info->type; + is_array = sampler_info->is_array; + is_shadow = sampler_info->is_shadow; + } else { + auto sampler = locker.ObtainBoundSampler(offset); + if (sampler) { + type = sampler->texture_type.Value(); + is_array = sampler->is_array.Value() != 0; + is_shadow = sampler->is_shadow.Value() != 0; + } else { + type = Tegra::Shader::TextureType::Texture2D; + is_array = false; + is_shadow = false; + } + } + // If this sampler has already been used, return the existing mapping. const auto itr = std::find_if(used_samplers.begin(), used_samplers.end(), @@ -305,13 +322,32 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu return *used_samplers.emplace(entry).first; } -const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type, - bool is_array, bool is_shadow) { +const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, + std::optional sampler_info) { const Node sampler_register = GetRegister(reg); const auto [base_sampler, cbuf_index, cbuf_offset] = TrackCbuf(sampler_register, global_code, static_cast(global_code.size())); ASSERT(base_sampler != nullptr); const auto cbuf_key = (static_cast(cbuf_index) << 32) | static_cast(cbuf_offset); + Tegra::Shader::TextureType type; + bool is_array; + bool is_shadow; + if (sampler_info) { + type = sampler_info->type; + is_array = sampler_info->is_array; + is_shadow = sampler_info->is_shadow; + } else { + auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); + if (sampler) { + type = sampler->texture_type.Value(); + is_array = sampler->is_array.Value() != 0; + is_shadow = sampler->is_shadow.Value() != 0; + } else { + type = Tegra::Shader::TextureType::Texture2D; + is_array = false; + is_shadow = false; + } + } // If this sampler has already been used, return the existing mapping. const auto itr = @@ -411,9 +447,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, (texture_type == TextureType::TextureCube && is_array && is_shadow), "This method is not supported."); - const auto& sampler = is_bindless - ? GetBindlessSampler(*bindless_reg, texture_type, is_array, is_shadow) - : GetSampler(instr.sampler, texture_type, is_array, is_shadow); + const auto& sampler = + is_bindless ? GetBindlessSampler(*bindless_reg, {{texture_type, is_array, is_shadow}}) + : GetSampler(instr.sampler, {{texture_type, is_array, is_shadow}}); const bool lod_needed = process_mode == TextureProcessMode::LZ || process_mode == TextureProcessMode::LL || @@ -577,7 +613,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de dc = GetRegister(parameter_register++); } - const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, depth_compare); + const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}}); Node4 values; for (u32 element = 0; element < values.size(); ++element) { @@ -610,7 +646,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; - const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false); + const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}}); Node4 values; for (u32 element = 0; element < values.size(); ++element) { @@ -646,7 +682,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is // When lod is used always is in gpr20 const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0); - const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false); + const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}}); Node4 values; for (u32 element = 0; element < values.size(); ++element) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index e3b568d3e..3a3e381d2 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -173,6 +173,13 @@ public: private: friend class ASTDecoder; + + struct SamplerInfo { + Tegra::Shader::TextureType type; + bool is_array; + bool is_shadow; + }; + void Decode(); NodeBlock DecodeRange(u32 begin, u32 end); @@ -297,12 +304,11 @@ private: /// Accesses a texture sampler const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, - Tegra::Shader::TextureType type, bool is_array, bool is_shadow); + std::optional sampler_info); // Accesses a texture sampler for a bindless texture. const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg, - Tegra::Shader::TextureType type, bool is_array, - bool is_shadow); + std::optional sampler_info); /// Accesses an image. Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); -- cgit v1.2.3