summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp24
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp52
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h33
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp72
-rw-r--r--src/video_core/shader/decode.cpp18
-rw-r--r--src/video_core/shader/decode/image.cpp18
-rw-r--r--src/video_core/shader/decode/texture.cpp99
-rw-r--r--src/video_core/shader/node.h129
-rw-r--r--src/video_core/shader/shader_ir.h20
-rw-r--r--src/video_core/texture_cache/surface_params.cpp10
-rw-r--r--src/video_core/texture_cache/texture_cache.h4
13 files changed, 197 insertions, 299 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 4c16c89d2..0719f2407 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -59,14 +59,12 @@ constexpr std::size_t NumSupportedVertexAttributes = 16;
59template <typename Engine, typename Entry> 59template <typename Engine, typename Entry>
60Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, 60Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry,
61 ShaderType shader_type, std::size_t index = 0) { 61 ShaderType shader_type, std::size_t index = 0) {
62 if (entry.IsBindless()) { 62 if (entry.is_bindless) {
63 const Tegra::Texture::TextureHandle tex_handle = 63 const auto tex_handle = engine.AccessConstBuffer32(shader_type, entry.buffer, entry.offset);
64 engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset());
65 return engine.GetTextureInfo(tex_handle); 64 return engine.GetTextureInfo(tex_handle);
66 } 65 }
67 const auto& gpu_profile = engine.AccessGuestDriverProfile(); 66 const auto& gpu_profile = engine.AccessGuestDriverProfile();
68 const u32 offset = 67 const u32 offset = entry.offset + static_cast<u32>(index * gpu_profile.GetTextureHandlerSize());
69 entry.GetOffset() + static_cast<u32>(index * gpu_profile.GetTextureHandlerSize());
70 if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) { 68 if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) {
71 return engine.GetStageTexture(shader_type, offset); 69 return engine.GetStageTexture(shader_type, offset);
72 } else { 70 } else {
@@ -829,9 +827,9 @@ void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shad
829 827
830 u32 binding = device.GetBaseBindings(stage_index).shader_storage_buffer; 828 u32 binding = device.GetBaseBindings(stage_index).shader_storage_buffer;
831 for (const auto& entry : shader->GetEntries().global_memory_entries) { 829 for (const auto& entry : shader->GetEntries().global_memory_entries) {
832 const auto addr{cbufs.const_buffers[entry.GetCbufIndex()].address + entry.GetCbufOffset()}; 830 const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset};
833 const auto gpu_addr{memory_manager.Read<u64>(addr)}; 831 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
834 const auto size{memory_manager.Read<u32>(addr + 8)}; 832 const u32 size{memory_manager.Read<u32>(addr + 8)};
835 SetupGlobalMemory(binding++, entry, gpu_addr, size); 833 SetupGlobalMemory(binding++, entry, gpu_addr, size);
836 } 834 }
837} 835}
@@ -843,7 +841,7 @@ void RasterizerOpenGL::SetupComputeGlobalMemory(const Shader& kernel) {
843 841
844 u32 binding = 0; 842 u32 binding = 0;
845 for (const auto& entry : kernel->GetEntries().global_memory_entries) { 843 for (const auto& entry : kernel->GetEntries().global_memory_entries) {
846 const auto addr{cbufs[entry.GetCbufIndex()].Address() + entry.GetCbufOffset()}; 844 const auto addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset};
847 const auto gpu_addr{memory_manager.Read<u64>(addr)}; 845 const auto gpu_addr{memory_manager.Read<u64>(addr)};
848 const auto size{memory_manager.Read<u32>(addr + 8)}; 846 const auto size{memory_manager.Read<u32>(addr + 8)};
849 SetupGlobalMemory(binding++, entry, gpu_addr, size); 847 SetupGlobalMemory(binding++, entry, gpu_addr, size);
@@ -854,7 +852,7 @@ void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& e
854 GPUVAddr gpu_addr, std::size_t size) { 852 GPUVAddr gpu_addr, std::size_t size) {
855 const auto alignment{device.GetShaderStorageBufferAlignment()}; 853 const auto alignment{device.GetShaderStorageBufferAlignment()};
856 const auto [ssbo, buffer_offset] = 854 const auto [ssbo, buffer_offset] =
857 buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.IsWritten()); 855 buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written);
858 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset, 856 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset,
859 static_cast<GLsizeiptr>(size)); 857 static_cast<GLsizeiptr>(size));
860} 858}
@@ -865,7 +863,7 @@ void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader&
865 u32 binding = device.GetBaseBindings(stage_index).sampler; 863 u32 binding = device.GetBaseBindings(stage_index).sampler;
866 for (const auto& entry : shader->GetEntries().samplers) { 864 for (const auto& entry : shader->GetEntries().samplers) {
867 const auto shader_type = static_cast<ShaderType>(stage_index); 865 const auto shader_type = static_cast<ShaderType>(stage_index);
868 for (std::size_t i = 0; i < entry.Size(); ++i) { 866 for (std::size_t i = 0; i < entry.size; ++i) {
869 const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i); 867 const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i);
870 SetupTexture(binding++, texture, entry); 868 SetupTexture(binding++, texture, entry);
871 } 869 }
@@ -877,7 +875,7 @@ void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) {
877 const auto& compute = system.GPU().KeplerCompute(); 875 const auto& compute = system.GPU().KeplerCompute();
878 u32 binding = 0; 876 u32 binding = 0;
879 for (const auto& entry : kernel->GetEntries().samplers) { 877 for (const auto& entry : kernel->GetEntries().samplers) {
880 for (std::size_t i = 0; i < entry.Size(); ++i) { 878 for (std::size_t i = 0; i < entry.size; ++i) {
881 const auto texture = GetTextureInfo(compute, entry, ShaderType::Compute, i); 879 const auto texture = GetTextureInfo(compute, entry, ShaderType::Compute, i);
882 SetupTexture(binding++, texture, entry); 880 SetupTexture(binding++, texture, entry);
883 } 881 }
@@ -934,7 +932,7 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t
934 if (!tic.IsBuffer()) { 932 if (!tic.IsBuffer()) {
935 view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source); 933 view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
936 } 934 }
937 if (entry.IsWritten()) { 935 if (entry.is_written) {
938 view->MarkAsModified(texture_cache.Tick()); 936 view->MarkAsModified(texture_cache.Tick());
939 } 937 }
940 glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE, 938 glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE,
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 0cd3ad7e1..1b474337a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -870,13 +870,13 @@ private:
870 for (const auto& sampler : ir.GetSamplers()) { 870 for (const auto& sampler : ir.GetSamplers()) {
871 const std::string name = GetSampler(sampler); 871 const std::string name = GetSampler(sampler);
872 const std::string description = fmt::format("layout (binding = {}) uniform", binding); 872 const std::string description = fmt::format("layout (binding = {}) uniform", binding);
873 binding += sampler.IsIndexed() ? sampler.Size() : 1; 873 binding += sampler.is_indexed ? sampler.size : 1;
874 874
875 std::string sampler_type = [&]() { 875 std::string sampler_type = [&]() {
876 if (sampler.IsBuffer()) { 876 if (sampler.is_buffer) {
877 return "samplerBuffer"; 877 return "samplerBuffer";
878 } 878 }
879 switch (sampler.GetType()) { 879 switch (sampler.type) {
880 case Tegra::Shader::TextureType::Texture1D: 880 case Tegra::Shader::TextureType::Texture1D:
881 return "sampler1D"; 881 return "sampler1D";
882 case Tegra::Shader::TextureType::Texture2D: 882 case Tegra::Shader::TextureType::Texture2D:
@@ -890,17 +890,17 @@ private:
890 return "sampler2D"; 890 return "sampler2D";
891 } 891 }
892 }(); 892 }();
893 if (sampler.IsArray()) { 893 if (sampler.is_array) {
894 sampler_type += "Array"; 894 sampler_type += "Array";
895 } 895 }
896 if (sampler.IsShadow()) { 896 if (sampler.is_shadow) {
897 sampler_type += "Shadow"; 897 sampler_type += "Shadow";
898 } 898 }
899 899
900 if (!sampler.IsIndexed()) { 900 if (!sampler.is_indexed) {
901 code.AddLine("{} {} {};", description, sampler_type, name); 901 code.AddLine("{} {} {};", description, sampler_type, name);
902 } else { 902 } else {
903 code.AddLine("{} {} {}[{}];", description, sampler_type, name, sampler.Size()); 903 code.AddLine("{} {} {}[{}];", description, sampler_type, name, sampler.size);
904 } 904 }
905 } 905 }
906 if (!ir.GetSamplers().empty()) { 906 if (!ir.GetSamplers().empty()) {
@@ -946,14 +946,14 @@ private:
946 u32 binding = device.GetBaseBindings(stage).image; 946 u32 binding = device.GetBaseBindings(stage).image;
947 for (const auto& image : ir.GetImages()) { 947 for (const auto& image : ir.GetImages()) {
948 std::string qualifier = "coherent volatile"; 948 std::string qualifier = "coherent volatile";
949 if (image.IsRead() && !image.IsWritten()) { 949 if (image.is_read && !image.is_written) {
950 qualifier += " readonly"; 950 qualifier += " readonly";
951 } else if (image.IsWritten() && !image.IsRead()) { 951 } else if (image.is_written && !image.is_read) {
952 qualifier += " writeonly"; 952 qualifier += " writeonly";
953 } 953 }
954 954
955 const char* format = image.IsAtomic() ? "r32ui, " : ""; 955 const char* format = image.is_atomic ? "r32ui, " : "";
956 const char* type_declaration = GetImageTypeDeclaration(image.GetType()); 956 const char* type_declaration = GetImageTypeDeclaration(image.type);
957 code.AddLine("layout ({}binding = {}) {} uniform uimage{} {};", format, binding++, 957 code.AddLine("layout ({}binding = {}) {} uniform uimage{} {};", format, binding++,
958 qualifier, type_declaration, GetImage(image)); 958 qualifier, type_declaration, GetImage(image));
959 } 959 }
@@ -1337,8 +1337,8 @@ private:
1337 ASSERT(meta); 1337 ASSERT(meta);
1338 1338
1339 const std::size_t count = operation.GetOperandsCount(); 1339 const std::size_t count = operation.GetOperandsCount();
1340 const bool has_array = meta->sampler.IsArray(); 1340 const bool has_array = meta->sampler.is_array;
1341 const bool has_shadow = meta->sampler.IsShadow(); 1341 const bool has_shadow = meta->sampler.is_shadow;
1342 1342
1343 std::string expr = "texture" + function_suffix; 1343 std::string expr = "texture" + function_suffix;
1344 if (!meta->aoffi.empty()) { 1344 if (!meta->aoffi.empty()) {
@@ -1346,7 +1346,7 @@ private:
1346 } else if (!meta->ptp.empty()) { 1346 } else if (!meta->ptp.empty()) {
1347 expr += "Offsets"; 1347 expr += "Offsets";
1348 } 1348 }
1349 if (!meta->sampler.IsIndexed()) { 1349 if (!meta->sampler.is_indexed) {
1350 expr += '(' + GetSampler(meta->sampler) + ", "; 1350 expr += '(' + GetSampler(meta->sampler) + ", ";
1351 } else { 1351 } else {
1352 expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], "; 1352 expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], ";
@@ -1974,7 +1974,7 @@ private:
1974 1974
1975 std::string expr = GenerateTexture( 1975 std::string expr = GenerateTexture(
1976 operation, "", {TextureOffset{}, TextureArgument{Type::Float, meta->bias}}); 1976 operation, "", {TextureOffset{}, TextureArgument{Type::Float, meta->bias}});
1977 if (meta->sampler.IsShadow()) { 1977 if (meta->sampler.is_shadow) {
1978 expr = "vec4(" + expr + ')'; 1978 expr = "vec4(" + expr + ')';
1979 } 1979 }
1980 return {expr + GetSwizzle(meta->element), Type::Float}; 1980 return {expr + GetSwizzle(meta->element), Type::Float};
@@ -1986,7 +1986,7 @@ private:
1986 1986
1987 std::string expr = GenerateTexture( 1987 std::string expr = GenerateTexture(
1988 operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureOffset{}}); 1988 operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureOffset{}});
1989 if (meta->sampler.IsShadow()) { 1989 if (meta->sampler.is_shadow) {
1990 expr = "vec4(" + expr + ')'; 1990 expr = "vec4(" + expr + ')';
1991 } 1991 }
1992 return {expr + GetSwizzle(meta->element), Type::Float}; 1992 return {expr + GetSwizzle(meta->element), Type::Float};
@@ -1995,11 +1995,11 @@ private:
1995 Expression TextureGather(Operation operation) { 1995 Expression TextureGather(Operation operation) {
1996 const auto& meta = std::get<MetaTexture>(operation.GetMeta()); 1996 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
1997 1997
1998 const auto type = meta.sampler.IsShadow() ? Type::Float : Type::Int; 1998 const auto type = meta.sampler.is_shadow ? Type::Float : Type::Int;
1999 const bool separate_dc = meta.sampler.IsShadow(); 1999 const bool separate_dc = meta.sampler.is_shadow;
2000 2000
2001 std::vector<TextureIR> ir; 2001 std::vector<TextureIR> ir;
2002 if (meta.sampler.IsShadow()) { 2002 if (meta.sampler.is_shadow) {
2003 ir = {TextureOffset{}}; 2003 ir = {TextureOffset{}};
2004 } else { 2004 } else {
2005 ir = {TextureOffset{}, TextureArgument{type, meta.component}}; 2005 ir = {TextureOffset{}, TextureArgument{type, meta.component}};
@@ -2044,7 +2044,7 @@ private:
2044 constexpr std::array constructors = {"int", "ivec2", "ivec3", "ivec4"}; 2044 constexpr std::array constructors = {"int", "ivec2", "ivec3", "ivec4"};
2045 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); 2045 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
2046 ASSERT(meta); 2046 ASSERT(meta);
2047 UNIMPLEMENTED_IF(meta->sampler.IsArray()); 2047 UNIMPLEMENTED_IF(meta->sampler.is_array);
2048 const std::size_t count = operation.GetOperandsCount(); 2048 const std::size_t count = operation.GetOperandsCount();
2049 2049
2050 std::string expr = "texelFetch("; 2050 std::string expr = "texelFetch(";
@@ -2065,7 +2065,7 @@ private:
2065 } 2065 }
2066 expr += ')'; 2066 expr += ')';
2067 2067
2068 if (meta->lod && !meta->sampler.IsBuffer()) { 2068 if (meta->lod && !meta->sampler.is_buffer) {
2069 expr += ", "; 2069 expr += ", ";
2070 expr += Visit(meta->lod).AsInt(); 2070 expr += Visit(meta->lod).AsInt();
2071 } 2071 }
@@ -2076,12 +2076,10 @@ private:
2076 } 2076 }
2077 2077
2078 Expression TextureGradient(Operation operation) { 2078 Expression TextureGradient(Operation operation) {
2079 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); 2079 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
2080 ASSERT(meta);
2081
2082 std::string expr = 2080 std::string expr =
2083 GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureOffset{}}); 2081 GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureOffset{}});
2084 return {std::move(expr) + GetSwizzle(meta->element), Type::Float}; 2082 return {std::move(expr) + GetSwizzle(meta.element), Type::Float};
2085 } 2083 }
2086 2084
2087 Expression ImageLoad(Operation operation) { 2085 Expression ImageLoad(Operation operation) {
@@ -2598,11 +2596,11 @@ private:
2598 } 2596 }
2599 2597
2600 std::string GetSampler(const Sampler& sampler) const { 2598 std::string GetSampler(const Sampler& sampler) const {
2601 return AppendSuffix(static_cast<u32>(sampler.GetIndex()), "sampler"); 2599 return AppendSuffix(sampler.index, "sampler");
2602 } 2600 }
2603 2601
2604 std::string GetImage(const Image& image) const { 2602 std::string GetImage(const Image& image) const {
2605 return AppendSuffix(static_cast<u32>(image.GetIndex()), "image"); 2603 return AppendSuffix(image.index, "image");
2606 } 2604 }
2607 2605
2608 std::string AppendSuffix(u32 index, std::string_view name) const { 2606 std::string AppendSuffix(u32 index, std::string_view name) const {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index e7dbd810c..e8a178764 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -33,36 +33,19 @@ public:
33 } 33 }
34 34
35private: 35private:
36 u32 index{}; 36 u32 index = 0;
37}; 37};
38 38
39class GlobalMemoryEntry { 39struct GlobalMemoryEntry {
40public: 40 constexpr explicit GlobalMemoryEntry(u32 cbuf_index, u32 cbuf_offset, bool is_read,
41 explicit GlobalMemoryEntry(u32 cbuf_index, u32 cbuf_offset, bool is_read, bool is_written) 41 bool is_written)
42 : cbuf_index{cbuf_index}, cbuf_offset{cbuf_offset}, is_read{is_read}, is_written{ 42 : cbuf_index{cbuf_index}, cbuf_offset{cbuf_offset}, is_read{is_read}, is_written{
43 is_written} {} 43 is_written} {}
44 44
45 u32 GetCbufIndex() const { 45 u32 cbuf_index = 0;
46 return cbuf_index; 46 u32 cbuf_offset = 0;
47 } 47 bool is_read = false;
48 48 bool is_written = false;
49 u32 GetCbufOffset() const {
50 return cbuf_offset;
51 }
52
53 bool IsRead() const {
54 return is_read;
55 }
56
57 bool IsWritten() const {
58 return is_written;
59 }
60
61private:
62 u32 cbuf_index{};
63 u32 cbuf_offset{};
64 bool is_read{};
65 bool is_written{};
66}; 49};
67 50
68struct ShaderEntries { 51struct ShaderEntries {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 91b1b16a5..fcbcadc8e 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -133,7 +133,7 @@ void AddBindings(std::vector<VkDescriptorSetLayoutBinding>& bindings, u32& bindi
133 u32 count = 1; 133 u32 count = 1;
134 if constexpr (descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) { 134 if constexpr (descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
135 // Combined image samplers can be arrayed. 135 // Combined image samplers can be arrayed.
136 count = container[i].Size(); 136 count = container[i].size;
137 } 137 }
138 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back(); 138 VkDescriptorSetLayoutBinding& entry = bindings.emplace_back();
139 entry.binding = binding++; 139 entry.binding = binding++;
@@ -393,7 +393,7 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3
393 393
394 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) { 394 if constexpr (descriptor_type == COMBINED_IMAGE_SAMPLER) {
395 for (u32 i = 0; i < count; ++i) { 395 for (u32 i = 0; i < count; ++i) {
396 const u32 num_samplers = container[i].Size(); 396 const u32 num_samplers = container[i].size;
397 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); 397 VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back();
398 entry.dstBinding = binding; 398 entry.dstBinding = binding;
399 entry.dstArrayElement = 0; 399 entry.dstArrayElement = 0;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 8a1f57891..4ac844212 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -119,14 +119,13 @@ template <typename Engine, typename Entry>
119Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, 119Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry,
120 std::size_t stage, std::size_t index = 0) { 120 std::size_t stage, std::size_t index = 0) {
121 const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage); 121 const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage);
122 if (entry.IsBindless()) { 122 if (entry.is_bindless) {
123 const Tegra::Texture::TextureHandle tex_handle = 123 const auto tex_handle = engine.AccessConstBuffer32(stage_type, entry.buffer, entry.offset);
124 engine.AccessConstBuffer32(stage_type, entry.GetBuffer(), entry.GetOffset());
125 return engine.GetTextureInfo(tex_handle); 124 return engine.GetTextureInfo(tex_handle);
126 } 125 }
127 const auto& gpu_profile = engine.AccessGuestDriverProfile(); 126 const auto& gpu_profile = engine.AccessGuestDriverProfile();
128 const u32 entry_offset = static_cast<u32>(index * gpu_profile.GetTextureHandlerSize()); 127 const u32 entry_offset = static_cast<u32>(index * gpu_profile.GetTextureHandlerSize());
129 const u32 offset = entry.GetOffset() + entry_offset; 128 const u32 offset = entry.offset + entry_offset;
130 if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) { 129 if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) {
131 return engine.GetStageTexture(stage_type, offset); 130 return engine.GetStageTexture(stage_type, offset);
132 } else { 131 } else {
@@ -961,7 +960,7 @@ void RasterizerVulkan::SetupGraphicsTextures(const ShaderEntries& entries, std::
961 MICROPROFILE_SCOPE(Vulkan_Textures); 960 MICROPROFILE_SCOPE(Vulkan_Textures);
962 const auto& gpu = system.GPU().Maxwell3D(); 961 const auto& gpu = system.GPU().Maxwell3D();
963 for (const auto& entry : entries.samplers) { 962 for (const auto& entry : entries.samplers) {
964 for (std::size_t i = 0; i < entry.Size(); ++i) { 963 for (std::size_t i = 0; i < entry.size; ++i) {
965 const auto texture = GetTextureInfo(gpu, entry, stage, i); 964 const auto texture = GetTextureInfo(gpu, entry, stage, i);
966 SetupTexture(texture, entry); 965 SetupTexture(texture, entry);
967 } 966 }
@@ -1013,7 +1012,7 @@ void RasterizerVulkan::SetupComputeTextures(const ShaderEntries& entries) {
1013 MICROPROFILE_SCOPE(Vulkan_Textures); 1012 MICROPROFILE_SCOPE(Vulkan_Textures);
1014 const auto& gpu = system.GPU().KeplerCompute(); 1013 const auto& gpu = system.GPU().KeplerCompute();
1015 for (const auto& entry : entries.samplers) { 1014 for (const auto& entry : entries.samplers) {
1016 for (std::size_t i = 0; i < entry.Size(); ++i) { 1015 for (std::size_t i = 0; i < entry.size; ++i) {
1017 const auto texture = GetTextureInfo(gpu, entry, ComputeShaderIndex, i); 1016 const auto texture = GetTextureInfo(gpu, entry, ComputeShaderIndex, i);
1018 SetupTexture(texture, entry); 1017 SetupTexture(texture, entry);
1019 } 1018 }
@@ -1094,7 +1093,7 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu
1094void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry) { 1093void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry) {
1095 auto view = texture_cache.GetImageSurface(tic, entry); 1094 auto view = texture_cache.GetImageSurface(tic, entry);
1096 1095
1097 if (entry.IsWritten()) { 1096 if (entry.is_written) {
1098 view->MarkAsModified(texture_cache.Tick()); 1097 view->MarkAsModified(texture_cache.Tick());
1099 } 1098 }
1100 1099
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index aaa138f52..8ffdd19d7 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -103,8 +103,8 @@ struct GenericVaryingDescription {
103}; 103};
104 104
105spv::Dim GetSamplerDim(const Sampler& sampler) { 105spv::Dim GetSamplerDim(const Sampler& sampler) {
106 ASSERT(!sampler.IsBuffer()); 106 ASSERT(!sampler.is_buffer);
107 switch (sampler.GetType()) { 107 switch (sampler.type) {
108 case Tegra::Shader::TextureType::Texture1D: 108 case Tegra::Shader::TextureType::Texture1D:
109 return spv::Dim::Dim1D; 109 return spv::Dim::Dim1D;
110 case Tegra::Shader::TextureType::Texture2D: 110 case Tegra::Shader::TextureType::Texture2D:
@@ -114,13 +114,13 @@ spv::Dim GetSamplerDim(const Sampler& sampler) {
114 case Tegra::Shader::TextureType::TextureCube: 114 case Tegra::Shader::TextureType::TextureCube:
115 return spv::Dim::Cube; 115 return spv::Dim::Cube;
116 default: 116 default:
117 UNIMPLEMENTED_MSG("Unimplemented sampler type={}", static_cast<u32>(sampler.GetType())); 117 UNIMPLEMENTED_MSG("Unimplemented sampler type={}", static_cast<int>(sampler.type));
118 return spv::Dim::Dim2D; 118 return spv::Dim::Dim2D;
119 } 119 }
120} 120}
121 121
122std::pair<spv::Dim, bool> GetImageDim(const Image& image) { 122std::pair<spv::Dim, bool> GetImageDim(const Image& image) {
123 switch (image.GetType()) { 123 switch (image.type) {
124 case Tegra::Shader::ImageType::Texture1D: 124 case Tegra::Shader::ImageType::Texture1D:
125 return {spv::Dim::Dim1D, false}; 125 return {spv::Dim::Dim1D, false};
126 case Tegra::Shader::ImageType::TextureBuffer: 126 case Tegra::Shader::ImageType::TextureBuffer:
@@ -134,7 +134,7 @@ std::pair<spv::Dim, bool> GetImageDim(const Image& image) {
134 case Tegra::Shader::ImageType::Texture3D: 134 case Tegra::Shader::ImageType::Texture3D:
135 return {spv::Dim::Dim3D, false}; 135 return {spv::Dim::Dim3D, false};
136 default: 136 default:
137 UNIMPLEMENTED_MSG("Unimplemented image type={}", static_cast<u32>(image.GetType())); 137 UNIMPLEMENTED_MSG("Unimplemented image type={}", static_cast<int>(image.type));
138 return {spv::Dim::Dim2D, false}; 138 return {spv::Dim::Dim2D, false};
139 } 139 }
140} 140}
@@ -879,11 +879,11 @@ private:
879 879
880 u32 DeclareTexelBuffers(u32 binding) { 880 u32 DeclareTexelBuffers(u32 binding) {
881 for (const auto& sampler : ir.GetSamplers()) { 881 for (const auto& sampler : ir.GetSamplers()) {
882 if (!sampler.IsBuffer()) { 882 if (!sampler.is_buffer) {
883 continue; 883 continue;
884 } 884 }
885 ASSERT(!sampler.IsArray()); 885 ASSERT(!sampler.is_array);
886 ASSERT(!sampler.IsShadow()); 886 ASSERT(!sampler.is_shadow);
887 887
888 constexpr auto dim = spv::Dim::Buffer; 888 constexpr auto dim = spv::Dim::Buffer;
889 constexpr int depth = 0; 889 constexpr int depth = 0;
@@ -894,23 +894,23 @@ private:
894 const Id image_type = TypeImage(t_float, dim, depth, arrayed, ms, sampled, format); 894 const Id image_type = TypeImage(t_float, dim, depth, arrayed, ms, sampled, format);
895 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type); 895 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type);
896 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); 896 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant);
897 AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.GetIndex()))); 897 AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.index)));
898 Decorate(id, spv::Decoration::Binding, binding++); 898 Decorate(id, spv::Decoration::Binding, binding++);
899 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); 899 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET);
900 900
901 texel_buffers.emplace(sampler.GetIndex(), TexelBuffer{image_type, id}); 901 texel_buffers.emplace(sampler.index, TexelBuffer{image_type, id});
902 } 902 }
903 return binding; 903 return binding;
904 } 904 }
905 905
906 u32 DeclareSamplers(u32 binding) { 906 u32 DeclareSamplers(u32 binding) {
907 for (const auto& sampler : ir.GetSamplers()) { 907 for (const auto& sampler : ir.GetSamplers()) {
908 if (sampler.IsBuffer()) { 908 if (sampler.is_buffer) {
909 continue; 909 continue;
910 } 910 }
911 const auto dim = GetSamplerDim(sampler); 911 const auto dim = GetSamplerDim(sampler);
912 const int depth = sampler.IsShadow() ? 1 : 0; 912 const int depth = sampler.is_shadow ? 1 : 0;
913 const int arrayed = sampler.IsArray() ? 1 : 0; 913 const int arrayed = sampler.is_array ? 1 : 0;
914 constexpr bool ms = false; 914 constexpr bool ms = false;
915 constexpr int sampled = 1; 915 constexpr int sampled = 1;
916 constexpr auto format = spv::ImageFormat::Unknown; 916 constexpr auto format = spv::ImageFormat::Unknown;
@@ -918,17 +918,17 @@ private:
918 const Id sampler_type = TypeSampledImage(image_type); 918 const Id sampler_type = TypeSampledImage(image_type);
919 const Id sampler_pointer_type = 919 const Id sampler_pointer_type =
920 TypePointer(spv::StorageClass::UniformConstant, sampler_type); 920 TypePointer(spv::StorageClass::UniformConstant, sampler_type);
921 const Id type = sampler.IsIndexed() 921 const Id type = sampler.is_indexed
922 ? TypeArray(sampler_type, Constant(t_uint, sampler.Size())) 922 ? TypeArray(sampler_type, Constant(t_uint, sampler.size))
923 : sampler_type; 923 : sampler_type;
924 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, type); 924 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, type);
925 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); 925 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant);
926 AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.GetIndex()))); 926 AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.index)));
927 Decorate(id, spv::Decoration::Binding, binding++); 927 Decorate(id, spv::Decoration::Binding, binding++);
928 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); 928 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET);
929 929
930 sampled_images.emplace(sampler.GetIndex(), SampledImage{image_type, sampler_type, 930 sampled_images.emplace(
931 sampler_pointer_type, id}); 931 sampler.index, SampledImage{image_type, sampler_type, sampler_pointer_type, id});
932 } 932 }
933 return binding; 933 return binding;
934 } 934 }
@@ -943,17 +943,17 @@ private:
943 const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {}); 943 const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {});
944 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type); 944 const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type);
945 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); 945 const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant);
946 AddGlobalVariable(Name(id, fmt::format("image_{}", image.GetIndex()))); 946 AddGlobalVariable(Name(id, fmt::format("image_{}", image.index)));
947 947
948 Decorate(id, spv::Decoration::Binding, binding++); 948 Decorate(id, spv::Decoration::Binding, binding++);
949 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); 949 Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET);
950 if (image.IsRead() && !image.IsWritten()) { 950 if (image.is_read && !image.is_written) {
951 Decorate(id, spv::Decoration::NonWritable); 951 Decorate(id, spv::Decoration::NonWritable);
952 } else if (image.IsWritten() && !image.IsRead()) { 952 } else if (image.is_written && !image.is_read) {
953 Decorate(id, spv::Decoration::NonReadable); 953 Decorate(id, spv::Decoration::NonReadable);
954 } 954 }
955 955
956 images.emplace(static_cast<u32>(image.GetIndex()), StorageImage{image_type, id}); 956 images.emplace(image.index, StorageImage{image_type, id});
957 } 957 }
958 return binding; 958 return binding;
959 } 959 }
@@ -1611,11 +1611,11 @@ private:
1611 1611
1612 Id GetTextureSampler(Operation operation) { 1612 Id GetTextureSampler(Operation operation) {
1613 const auto& meta = std::get<MetaTexture>(operation.GetMeta()); 1613 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
1614 ASSERT(!meta.sampler.IsBuffer()); 1614 ASSERT(!meta.sampler.is_buffer);
1615 1615
1616 const auto& entry = sampled_images.at(meta.sampler.GetIndex()); 1616 const auto& entry = sampled_images.at(meta.sampler.index);
1617 Id sampler = entry.variable; 1617 Id sampler = entry.variable;
1618 if (meta.sampler.IsIndexed()) { 1618 if (meta.sampler.is_indexed) {
1619 const Id index = AsInt(Visit(meta.index)); 1619 const Id index = AsInt(Visit(meta.index));
1620 sampler = OpAccessChain(entry.sampler_pointer_type, sampler, index); 1620 sampler = OpAccessChain(entry.sampler_pointer_type, sampler, index);
1621 } 1621 }
@@ -1624,8 +1624,8 @@ private:
1624 1624
1625 Id GetTextureImage(Operation operation) { 1625 Id GetTextureImage(Operation operation) {
1626 const auto& meta = std::get<MetaTexture>(operation.GetMeta()); 1626 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
1627 const u32 index = meta.sampler.GetIndex(); 1627 const u32 index = meta.sampler.index;
1628 if (meta.sampler.IsBuffer()) { 1628 if (meta.sampler.is_buffer) {
1629 const auto& entry = texel_buffers.at(index); 1629 const auto& entry = texel_buffers.at(index);
1630 return OpLoad(entry.image_type, entry.image); 1630 return OpLoad(entry.image_type, entry.image);
1631 } else { 1631 } else {
@@ -1636,7 +1636,7 @@ private:
1636 1636
1637 Id GetImage(Operation operation) { 1637 Id GetImage(Operation operation) {
1638 const auto& meta = std::get<MetaImage>(operation.GetMeta()); 1638 const auto& meta = std::get<MetaImage>(operation.GetMeta());
1639 const auto entry = images.at(meta.image.GetIndex()); 1639 const auto entry = images.at(meta.image.index);
1640 return OpLoad(entry.image_type, entry.image); 1640 return OpLoad(entry.image_type, entry.image);
1641 } 1641 }
1642 1642
@@ -1652,7 +1652,7 @@ private:
1652 } 1652 }
1653 if (const auto meta = std::get_if<MetaTexture>(&operation.GetMeta())) { 1653 if (const auto meta = std::get_if<MetaTexture>(&operation.GetMeta())) {
1654 // Add array coordinate for textures 1654 // Add array coordinate for textures
1655 if (meta->sampler.IsArray()) { 1655 if (meta->sampler.is_array) {
1656 Id array = AsInt(Visit(meta->array)); 1656 Id array = AsInt(Visit(meta->array));
1657 if (type == Type::Float) { 1657 if (type == Type::Float) {
1658 array = OpConvertSToF(t_float, array); 1658 array = OpConvertSToF(t_float, array);
@@ -1758,7 +1758,7 @@ private:
1758 operands.push_back(GetOffsetCoordinates(operation)); 1758 operands.push_back(GetOffsetCoordinates(operation));
1759 } 1759 }
1760 1760
1761 if (meta.sampler.IsShadow()) { 1761 if (meta.sampler.is_shadow) {
1762 const Id dref = AsFloat(Visit(meta.depth_compare)); 1762 const Id dref = AsFloat(Visit(meta.depth_compare));
1763 return {OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, mask, operands), 1763 return {OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, mask, operands),
1764 Type::Float}; 1764 Type::Float};
@@ -1773,7 +1773,7 @@ private:
1773 1773
1774 const Id coords = GetCoordinates(operation, Type::Float); 1774 const Id coords = GetCoordinates(operation, Type::Float);
1775 Id texture{}; 1775 Id texture{};
1776 if (meta.sampler.IsShadow()) { 1776 if (meta.sampler.is_shadow) {
1777 texture = OpImageDrefGather(t_float4, GetTextureSampler(operation), coords, 1777 texture = OpImageDrefGather(t_float4, GetTextureSampler(operation), coords,
1778 AsFloat(Visit(meta.depth_compare))); 1778 AsFloat(Visit(meta.depth_compare)));
1779 } else { 1779 } else {
@@ -1800,8 +1800,8 @@ private:
1800 } 1800 }
1801 1801
1802 const Id lod = AsUint(Visit(operation[0])); 1802 const Id lod = AsUint(Visit(operation[0]));
1803 const std::size_t coords_count = [&]() { 1803 const std::size_t coords_count = [&meta] {
1804 switch (const auto type = meta.sampler.GetType(); type) { 1804 switch (const auto type = meta.sampler.type) {
1805 case Tegra::Shader::TextureType::Texture1D: 1805 case Tegra::Shader::TextureType::Texture1D:
1806 return 1; 1806 return 1;
1807 case Tegra::Shader::TextureType::Texture2D: 1807 case Tegra::Shader::TextureType::Texture2D:
@@ -1810,7 +1810,7 @@ private:
1810 case Tegra::Shader::TextureType::Texture3D: 1810 case Tegra::Shader::TextureType::Texture3D:
1811 return 3; 1811 return 3;
1812 default: 1812 default:
1813 UNREACHABLE_MSG("Invalid texture type={}", static_cast<u32>(type)); 1813 UNREACHABLE_MSG("Invalid texture type={}", static_cast<int>(type));
1814 return 2; 1814 return 2;
1815 } 1815 }
1816 }(); 1816 }();
@@ -1853,7 +1853,7 @@ private:
1853 const Id image = GetTextureImage(operation); 1853 const Id image = GetTextureImage(operation);
1854 const Id coords = GetCoordinates(operation, Type::Int); 1854 const Id coords = GetCoordinates(operation, Type::Int);
1855 Id fetch; 1855 Id fetch;
1856 if (meta.lod && !meta.sampler.IsBuffer()) { 1856 if (meta.lod && !meta.sampler.is_buffer) {
1857 fetch = OpImageFetch(t_float4, image, coords, spv::ImageOperandsMask::Lod, 1857 fetch = OpImageFetch(t_float4, image, coords, spv::ImageOperandsMask::Lod,
1858 AsInt(Visit(meta.lod))); 1858 AsInt(Visit(meta.lod)));
1859 } else { 1859 } else {
@@ -2969,7 +2969,7 @@ ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir) {
2969 entries.global_buffers.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_written); 2969 entries.global_buffers.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_written);
2970 } 2970 }
2971 for (const auto& sampler : ir.GetSamplers()) { 2971 for (const auto& sampler : ir.GetSamplers()) {
2972 if (sampler.IsBuffer()) { 2972 if (sampler.is_buffer) {
2973 entries.texel_buffers.emplace_back(sampler); 2973 entries.texel_buffers.emplace_back(sampler);
2974 } else { 2974 } else {
2975 entries.samplers.emplace_back(sampler); 2975 entries.samplers.emplace_back(sampler);
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 87ac9ac6c..8427837b7 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -42,11 +42,11 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile& gpu_driver,
42 u32 count{}; 42 u32 count{};
43 std::vector<u32> bound_offsets; 43 std::vector<u32> bound_offsets;
44 for (const auto& sampler : used_samplers) { 44 for (const auto& sampler : used_samplers) {
45 if (sampler.IsBindless()) { 45 if (sampler.is_bindless) {
46 continue; 46 continue;
47 } 47 }
48 ++count; 48 ++count;
49 bound_offsets.emplace_back(sampler.GetOffset()); 49 bound_offsets.emplace_back(sampler.offset);
50 } 50 }
51 if (count > 1) { 51 if (count > 1) {
52 gpu_driver.DeduceTextureHandlerSize(std::move(bound_offsets)); 52 gpu_driver.DeduceTextureHandlerSize(std::move(bound_offsets));
@@ -56,14 +56,14 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile& gpu_driver,
56std::optional<u32> TryDeduceSamplerSize(const Sampler& sampler_to_deduce, 56std::optional<u32> TryDeduceSamplerSize(const Sampler& sampler_to_deduce,
57 VideoCore::GuestDriverProfile& gpu_driver, 57 VideoCore::GuestDriverProfile& gpu_driver,
58 const std::list<Sampler>& used_samplers) { 58 const std::list<Sampler>& used_samplers) {
59 const u32 base_offset = sampler_to_deduce.GetOffset(); 59 const u32 base_offset = sampler_to_deduce.offset;
60 u32 max_offset{std::numeric_limits<u32>::max()}; 60 u32 max_offset{std::numeric_limits<u32>::max()};
61 for (const auto& sampler : used_samplers) { 61 for (const auto& sampler : used_samplers) {
62 if (sampler.IsBindless()) { 62 if (sampler.is_bindless) {
63 continue; 63 continue;
64 } 64 }
65 if (sampler.GetOffset() > base_offset) { 65 if (sampler.offset > base_offset) {
66 max_offset = std::min(sampler.GetOffset(), max_offset); 66 max_offset = std::min(sampler.offset, max_offset);
67 } 67 }
68 } 68 }
69 if (max_offset == std::numeric_limits<u32>::max()) { 69 if (max_offset == std::numeric_limits<u32>::max()) {
@@ -363,14 +363,14 @@ void ShaderIR::PostDecode() {
363 return; 363 return;
364 } 364 }
365 for (auto& sampler : used_samplers) { 365 for (auto& sampler : used_samplers) {
366 if (!sampler.IsIndexed()) { 366 if (!sampler.is_indexed) {
367 continue; 367 continue;
368 } 368 }
369 if (const auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers)) { 369 if (const auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers)) {
370 sampler.SetSize(*size); 370 sampler.size = *size;
371 } else { 371 } else {
372 LOG_CRITICAL(HW_GPU, "Failed to deduce size of indexed sampler"); 372 LOG_CRITICAL(HW_GPU, "Failed to deduce size of indexed sampler");
373 sampler.SetSize(1); 373 sampler.size = 1;
374 } 374 }
375 } 375 }
376} 376}
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index 85ee9aa5e..60b6ad72a 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -485,11 +485,10 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
485Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { 485Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
486 const auto offset = static_cast<u32>(image.index.Value()); 486 const auto offset = static_cast<u32>(image.index.Value());
487 487
488 const auto it = 488 const auto it = std::find_if(std::begin(used_images), std::end(used_images),
489 std::find_if(std::begin(used_images), std::end(used_images), 489 [offset](const Image& entry) { return entry.offset == offset; });
490 [offset](const Image& entry) { return entry.GetOffset() == offset; });
491 if (it != std::end(used_images)) { 490 if (it != std::end(used_images)) {
492 ASSERT(!it->IsBindless() && it->GetType() == it->GetType()); 491 ASSERT(!it->is_bindless && it->type == type);
493 return *it; 492 return *it;
494 } 493 }
495 494
@@ -505,13 +504,12 @@ Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::Im
505 const auto buffer = std::get<1>(result); 504 const auto buffer = std::get<1>(result);
506 const auto offset = std::get<2>(result); 505 const auto offset = std::get<2>(result);
507 506
508 const auto it = 507 const auto it = std::find_if(std::begin(used_images), std::end(used_images),
509 std::find_if(std::begin(used_images), std::end(used_images), 508 [buffer, offset](const Image& entry) {
510 [buffer = buffer, offset = offset](const Image& entry) { 509 return entry.buffer == buffer && entry.offset == offset;
511 return entry.GetBuffer() == buffer && entry.GetOffset() == offset; 510 });
512 });
513 if (it != std::end(used_images)) { 511 if (it != std::end(used_images)) {
514 ASSERT(it->IsBindless() && it->GetType() == it->GetType()); 512 ASSERT(it->is_bindless && it->type == type);
515 return *it; 513 return *it;
516 } 514 }
517 515
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index e68f1d305..193368c29 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -140,14 +140,13 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
140 const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); 140 const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
141 141
142 const SamplerInfo info{TextureType::Texture2D, false, is_depth_compare, false}; 142 const SamplerInfo info{TextureType::Texture2D, false, is_depth_compare, false};
143 const Sampler& sampler = *GetSampler(instr.sampler, info); 143 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info);
144 144
145 Node4 values; 145 Node4 values;
146 for (u32 element = 0; element < values.size(); ++element) { 146 for (u32 element = 0; element < values.size(); ++element) {
147 auto coords_copy = coords; 147 MetaTexture meta{*sampler, {}, depth_compare, aoffi, {}, {},
148 MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, 148 {}, {}, component, element, {}};
149 {}, {}, component, element, {}}; 149 values[element] = Operation(OperationCode::TextureGather, meta, coords);
150 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
151 } 150 }
152 151
153 if (instr.tld4s.fp16_flag) { 152 if (instr.tld4s.fp16_flag) {
@@ -170,13 +169,15 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
170 const auto texture_type = instr.txd.texture_type.Value(); 169 const auto texture_type = instr.txd.texture_type.Value();
171 const auto coord_count = GetCoordCount(texture_type); 170 const auto coord_count = GetCoordCount(texture_type);
172 Node index_var{}; 171 Node index_var{};
173 const Sampler* sampler = 172 const std::optional<Sampler> sampler =
174 is_bindless 173 is_bindless
175 ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false, false}}) 174 ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false, false}})
176 : GetSampler(instr.sampler, {{texture_type, is_array, false, false}}); 175 : GetSampler(instr.sampler, {{texture_type, is_array, false, false}});
177 Node4 values; 176 Node4 values;
178 if (sampler == nullptr) { 177 if (!sampler) {
179 std::generate(values.begin(), values.end(), [] { return Immediate(0); }); 178 for (u32 element = 0; element < values.size(); ++element) {
179 values[element] = Immediate(0);
180 }
180 WriteTexInstructionFloat(bb, instr, values); 181 WriteTexInstructionFloat(bb, instr, values);
181 break; 182 break;
182 } 183 }
@@ -218,10 +219,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
218 // Sadly, not all texture instructions specify the type of texture their sampler 219 // Sadly, not all texture instructions specify the type of texture their sampler
219 // uses. This must be fixed at a later instance. 220 // uses. This must be fixed at a later instance.
220 Node index_var{}; 221 Node index_var{};
221 const Sampler* sampler = 222 const std::optional<Sampler> sampler =
222 is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler); 223 is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler);
223 224
224 if (sampler == nullptr) { 225 if (!sampler) {
225 u32 indexer = 0; 226 u32 indexer = 0;
226 for (u32 element = 0; element < 4; ++element) { 227 for (u32 element = 0; element < 4; ++element) {
227 if (!instr.txq.IsComponentEnabled(element)) { 228 if (!instr.txq.IsComponentEnabled(element)) {
@@ -269,10 +270,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
269 270
270 auto texture_type = instr.tmml.texture_type.Value(); 271 auto texture_type = instr.tmml.texture_type.Value();
271 Node index_var{}; 272 Node index_var{};
272 const Sampler* sampler = 273 const std::optional<Sampler> sampler =
273 is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); 274 is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler);
274 275
275 if (sampler == nullptr) { 276 if (!sampler) {
276 u32 indexer = 0; 277 u32 indexer = 0;
277 for (u32 element = 0; element < 2; ++element) { 278 for (u32 element = 0; element < 2; ++element) {
278 if (!instr.tmml.IsComponentEnabled(element)) { 279 if (!instr.tmml.IsComponentEnabled(element)) {
@@ -368,35 +369,34 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sample
368 sampler->is_buffer != 0}; 369 sampler->is_buffer != 0};
369} 370}
370 371
371const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, 372std::optional<Sampler> ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
372 std::optional<SamplerInfo> sampler_info) { 373 std::optional<SamplerInfo> sampler_info) {
373 const auto offset = static_cast<u32>(sampler.index.Value()); 374 const auto offset = static_cast<u32>(sampler.index.Value());
374 const auto info = GetSamplerInfo(sampler_info, offset); 375 const auto info = GetSamplerInfo(sampler_info, offset);
375 376
376 // If this sampler has already been used, return the existing mapping. 377 // If this sampler has already been used, return the existing mapping.
377 const auto it = 378 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(),
378 std::find_if(used_samplers.begin(), used_samplers.end(), 379 [offset](const Sampler& entry) { return entry.offset == offset; });
379 [offset](const Sampler& entry) { return entry.GetOffset() == offset; });
380 if (it != used_samplers.end()) { 380 if (it != used_samplers.end()) {
381 ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && 381 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array &&
382 it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); 382 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer);
383 return &*it; 383 return *it;
384 } 384 }
385 385
386 // Otherwise create a new mapping for this sampler 386 // Otherwise create a new mapping for this sampler
387 const auto next_index = static_cast<u32>(used_samplers.size()); 387 const auto next_index = static_cast<u32>(used_samplers.size());
388 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, 388 return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
389 info.is_buffer, false); 389 info.is_buffer, false);
390} 390}
391 391
392const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, 392std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var,
393 std::optional<SamplerInfo> sampler_info) { 393 std::optional<SamplerInfo> sampler_info) {
394 const Node sampler_register = GetRegister(reg); 394 const Node sampler_register = GetRegister(reg);
395 const auto [base_node, tracked_sampler_info] = 395 const auto [base_node, tracked_sampler_info] =
396 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size())); 396 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size()));
397 ASSERT(base_node != nullptr); 397 ASSERT(base_node != nullptr);
398 if (base_node == nullptr) { 398 if (base_node == nullptr) {
399 return nullptr; 399 return std::nullopt;
400 } 400 }
401 401
402 if (const auto bindless_sampler_info = 402 if (const auto bindless_sampler_info =
@@ -406,23 +406,22 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& i
406 const auto info = GetSamplerInfo(sampler_info, offset, buffer); 406 const auto info = GetSamplerInfo(sampler_info, offset, buffer);
407 407
408 // If this sampler has already been used, return the existing mapping. 408 // If this sampler has already been used, return the existing mapping.
409 const auto it = 409 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(),
410 std::find_if(used_samplers.begin(), used_samplers.end(), 410 [buffer = buffer, offset = offset](const Sampler& entry) {
411 [buffer = buffer, offset = offset](const Sampler& entry) { 411 return entry.buffer == buffer && entry.offset == offset;
412 return entry.GetBuffer() == buffer && entry.GetOffset() == offset; 412 });
413 });
414 if (it != used_samplers.end()) { 413 if (it != used_samplers.end()) {
415 ASSERT(it->IsBindless() && it->GetType() == info.type && 414 ASSERT(it->is_bindless && it->type == info.type && it->is_array == info.is_array &&
416 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow); 415 it->is_shadow == info.is_shadow);
417 return &*it; 416 return *it;
418 } 417 }
419 418
420 // Otherwise create a new mapping for this sampler 419 // Otherwise create a new mapping for this sampler
421 const auto next_index = static_cast<u32>(used_samplers.size()); 420 const auto next_index = static_cast<u32>(used_samplers.size());
422 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, 421 return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
423 info.is_shadow, info.is_buffer, false); 422 info.is_shadow, info.is_buffer, false);
424 } else if (const auto array_sampler_info = 423 }
425 std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { 424 if (const auto array_sampler_info = std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
426 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; 425 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
427 index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); 426 index_var = GetCustomVariable(array_sampler_info->GetIndexVar());
428 const auto info = GetSamplerInfo(sampler_info, base_offset); 427 const auto info = GetSamplerInfo(sampler_info, base_offset);
@@ -430,21 +429,21 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& i
430 // If this sampler has already been used, return the existing mapping. 429 // If this sampler has already been used, return the existing mapping.
431 const auto it = std::find_if( 430 const auto it = std::find_if(
432 used_samplers.begin(), used_samplers.end(), 431 used_samplers.begin(), used_samplers.end(),
433 [base_offset](const Sampler& entry) { return entry.GetOffset() == base_offset; }); 432 [base_offset](const Sampler& entry) { return entry.offset == base_offset; });
434 if (it != used_samplers.end()) { 433 if (it != used_samplers.end()) {
435 ASSERT(!it->IsBindless() && it->GetType() == info.type && 434 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array &&
436 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow && 435 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer &&
437 it->IsBuffer() == info.is_buffer && it->IsIndexed()); 436 it->is_indexed);
438 return &*it; 437 return *it;
439 } 438 }
440 439
441 uses_indexed_samplers = true; 440 uses_indexed_samplers = true;
442 // Otherwise create a new mapping for this sampler 441 // Otherwise create a new mapping for this sampler
443 const auto next_index = static_cast<u32>(used_samplers.size()); 442 const auto next_index = static_cast<u32>(used_samplers.size());
444 return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array, 443 return used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array,
445 info.is_shadow, info.is_buffer, true); 444 info.is_shadow, info.is_buffer, true);
446 } 445 }
447 return nullptr; 446 return std::nullopt;
448} 447}
449 448
450void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 449void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
@@ -531,7 +530,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
531 530
532 const SamplerInfo info{texture_type, is_array, is_shadow, false}; 531 const SamplerInfo info{texture_type, is_array, is_shadow, false};
533 Node index_var; 532 Node index_var;
534 const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info) 533 std::optional<Sampler> sampler = is_bindless
534 ? GetBindlessSampler(*bindless_reg, index_var, info)
535 : GetSampler(instr.sampler, info); 535 : GetSampler(instr.sampler, info);
536 if (!sampler) { 536 if (!sampler) {
537 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)}; 537 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)};
@@ -685,10 +685,11 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
685 685
686 const SamplerInfo info{texture_type, is_array, depth_compare, false}; 686 const SamplerInfo info{texture_type, is_array, depth_compare, false};
687 Node index_var{}; 687 Node index_var{};
688 const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, index_var, info) 688 const std::optional<Sampler> sampler =
689 : GetSampler(instr.sampler, info); 689 is_bindless ? GetBindlessSampler(parameter_register++, index_var, info)
690 : GetSampler(instr.sampler, info);
690 Node4 values; 691 Node4 values;
691 if (sampler == nullptr) { 692 if (!sampler) {
692 for (u32 element = 0; element < values.size(); ++element) { 693 for (u32 element = 0; element < values.size(); ++element) {
693 values[element] = Immediate(0); 694 values[element] = Immediate(0);
694 } 695 }
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 3eee961f5..d0656b581 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -265,76 +265,30 @@ class ArraySamplerNode;
265using TrackSamplerData = std::variant<BindlessSamplerNode, ArraySamplerNode>; 265using TrackSamplerData = std::variant<BindlessSamplerNode, ArraySamplerNode>;
266using TrackSampler = std::shared_ptr<TrackSamplerData>; 266using TrackSampler = std::shared_ptr<TrackSamplerData>;
267 267
268class Sampler { 268struct Sampler {
269public: 269 /// Bound samplers constructor
270 /// This constructor is for bound samplers
271 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type, 270 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
272 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed) 271 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
273 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow}, 272 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
274 is_buffer{is_buffer}, is_indexed{is_indexed} {} 273 is_buffer{is_buffer}, is_indexed{is_indexed} {}
275 274
276 /// This constructor is for bindless samplers 275 /// Bindless samplers constructor
277 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type, 276 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
278 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed) 277 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
279 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array}, 278 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
280 is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true}, is_indexed{is_indexed} {} 279 is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true}, is_indexed{is_indexed} {}
281 280
282 constexpr u32 GetIndex() const { 281 u32 index = 0; ///< Emulated index given for the this sampler.
283 return index; 282 u32 offset = 0; ///< Offset in the const buffer from where the sampler is being read.
284 } 283 u32 buffer = 0; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
285 284 u32 size = 1; ///< Size of the sampler.
286 constexpr u32 GetOffset() const {
287 return offset;
288 }
289
290 constexpr u32 GetBuffer() const {
291 return buffer;
292 }
293
294 constexpr Tegra::Shader::TextureType GetType() const {
295 return type;
296 }
297
298 constexpr bool IsArray() const {
299 return is_array;
300 }
301
302 constexpr bool IsShadow() const {
303 return is_shadow;
304 }
305
306 constexpr bool IsBuffer() const {
307 return is_buffer;
308 }
309
310 constexpr bool IsBindless() const {
311 return is_bindless;
312 }
313
314 constexpr bool IsIndexed() const {
315 return is_indexed;
316 }
317
318 constexpr u32 Size() const {
319 return size;
320 }
321
322 constexpr void SetSize(u32 new_size) {
323 size = new_size;
324 }
325
326private:
327 u32 index{}; ///< Emulated index given for the this sampler.
328 u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
329 u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
330 u32 size{1}; ///< Size of the sampler.
331 285
332 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) 286 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
333 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. 287 bool is_array = false; ///< Whether the texture is being sampled as an array texture or not.
334 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. 288 bool is_shadow = false; ///< Whether the texture is being sampled as a depth texture or not.
335 bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler. 289 bool is_buffer = false; ///< Whether the texture is a texture buffer without sampler.
336 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. 290 bool is_bindless = false; ///< Whether this sampler belongs to a bindless texture or not.
337 bool is_indexed{}; ///< Whether this sampler is an indexed array of textures. 291 bool is_indexed = false; ///< Whether this sampler is an indexed array of textures.
338}; 292};
339 293
340/// Represents a tracked bindless sampler into a direct const buffer 294/// Represents a tracked bindless sampler into a direct const buffer
@@ -379,13 +333,13 @@ private:
379 u32 offset; 333 u32 offset;
380}; 334};
381 335
382class Image final { 336struct Image {
383public: 337public:
384 /// This constructor is for bound images 338 /// Bound images constructor
385 constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type) 339 constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type)
386 : index{index}, offset{offset}, type{type} {} 340 : index{index}, offset{offset}, type{type} {}
387 341
388 /// This constructor is for bindless samplers 342 /// Bindless samplers constructor
389 constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type) 343 constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type)
390 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {} 344 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {}
391 345
@@ -403,53 +357,20 @@ public:
403 is_atomic = true; 357 is_atomic = true;
404 } 358 }
405 359
406 constexpr u32 GetIndex() const { 360 u32 index = 0;
407 return index; 361 u32 offset = 0;
408 } 362 u32 buffer = 0;
409
410 constexpr u32 GetOffset() const {
411 return offset;
412 }
413
414 constexpr u32 GetBuffer() const {
415 return buffer;
416 }
417
418 constexpr Tegra::Shader::ImageType GetType() const {
419 return type;
420 }
421
422 constexpr bool IsBindless() const {
423 return is_bindless;
424 }
425
426 constexpr bool IsWritten() const {
427 return is_written;
428 }
429
430 constexpr bool IsRead() const {
431 return is_read;
432 }
433
434 constexpr bool IsAtomic() const {
435 return is_atomic;
436 }
437
438private:
439 u32 index{};
440 u32 offset{};
441 u32 buffer{};
442 363
443 Tegra::Shader::ImageType type{}; 364 Tegra::Shader::ImageType type{};
444 bool is_bindless{}; 365 bool is_bindless = false;
445 bool is_written{}; 366 bool is_written = false;
446 bool is_read{}; 367 bool is_read = false;
447 bool is_atomic{}; 368 bool is_atomic = false;
448}; 369};
449 370
450struct GlobalMemoryBase { 371struct GlobalMemoryBase {
451 u32 cbuf_index{}; 372 u32 cbuf_index = 0;
452 u32 cbuf_offset{}; 373 u32 cbuf_offset = 0;
453 374
454 bool operator<(const GlobalMemoryBase& rhs) const { 375 bool operator<(const GlobalMemoryBase& rhs) const {
455 return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset); 376 return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
@@ -463,7 +384,7 @@ struct MetaArithmetic {
463 384
464/// Parameters describing a texture sampler 385/// Parameters describing a texture sampler
465struct MetaTexture { 386struct MetaTexture {
466 const Sampler& sampler; 387 Sampler sampler;
467 Node array; 388 Node array;
468 Node depth_compare; 389 Node depth_compare;
469 std::vector<Node> aoffi; 390 std::vector<Node> aoffi;
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index c6e7bdf50..ae5e414cb 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -29,12 +29,11 @@ using ProgramCode = std::vector<u64>;
29 29
30constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; 30constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
31 31
32class ConstBuffer { 32struct ConstBuffer {
33public: 33 constexpr explicit ConstBuffer(u32 max_offset, bool is_indirect)
34 explicit ConstBuffer(u32 max_offset, bool is_indirect)
35 : max_offset{max_offset}, is_indirect{is_indirect} {} 34 : max_offset{max_offset}, is_indirect{is_indirect} {}
36 35
37 ConstBuffer() = default; 36 constexpr ConstBuffer() = default;
38 37
39 void MarkAsUsed(u64 offset) { 38 void MarkAsUsed(u64 offset) {
40 max_offset = std::max(max_offset, static_cast<u32>(offset)); 39 max_offset = std::max(max_offset, static_cast<u32>(offset));
@@ -57,8 +56,8 @@ public:
57 } 56 }
58 57
59private: 58private:
60 u32 max_offset{}; 59 u32 max_offset = 0;
61 bool is_indirect{}; 60 bool is_indirect = false;
62}; 61};
63 62
64struct GlobalMemoryUsage { 63struct GlobalMemoryUsage {
@@ -332,12 +331,13 @@ private:
332 std::optional<u32> buffer = std::nullopt); 331 std::optional<u32> buffer = std::nullopt);
333 332
334 /// Accesses a texture sampler 333 /// Accesses a texture sampler
335 const Sampler* GetSampler(const Tegra::Shader::Sampler& sampler, 334 std::optional<Sampler> GetSampler(const Tegra::Shader::Sampler& sampler,
336 std::optional<SamplerInfo> sampler_info = std::nullopt); 335 std::optional<SamplerInfo> sampler_info = std::nullopt);
337 336
338 /// Accesses a texture sampler for a bindless texture. 337 /// Accesses a texture sampler for a bindless texture.
339 const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, 338 std::optional<Sampler> GetBindlessSampler(
340 std::optional<SamplerInfo> sampler_info = std::nullopt); 339 Tegra::Shader::Register reg, Node& index_var,
340 std::optional<SamplerInfo> sampler_info = std::nullopt);
341 341
342 /// Accesses an image. 342 /// Accesses an image.
343 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); 343 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 0de499946..884fabffe 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -81,7 +81,7 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
81 params.pixel_format = lookup_table.GetPixelFormat( 81 params.pixel_format = lookup_table.GetPixelFormat(
82 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); 82 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type);
83 params.type = GetFormatType(params.pixel_format); 83 params.type = GetFormatType(params.pixel_format);
84 if (entry.IsShadow() && params.type == SurfaceType::ColorTexture) { 84 if (entry.is_shadow && params.type == SurfaceType::ColorTexture) {
85 switch (params.pixel_format) { 85 switch (params.pixel_format) {
86 case PixelFormat::R16U: 86 case PixelFormat::R16U:
87 case PixelFormat::R16F: 87 case PixelFormat::R16F:
@@ -108,7 +108,7 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
108 params.emulated_levels = 1; 108 params.emulated_levels = 1;
109 params.is_layered = false; 109 params.is_layered = false;
110 } else { 110 } else {
111 params.target = TextureTypeToSurfaceTarget(entry.GetType(), entry.IsArray()); 111 params.target = TextureTypeToSurfaceTarget(entry.type, entry.is_array);
112 params.width = tic.Width(); 112 params.width = tic.Width();
113 params.height = tic.Height(); 113 params.height = tic.Height();
114 params.depth = tic.Depth(); 114 params.depth = tic.Depth();
@@ -138,7 +138,7 @@ SurfaceParams SurfaceParams::CreateForImage(const FormatLookupTable& lookup_tabl
138 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type); 138 tic.format, params.srgb_conversion, tic.r_type, tic.g_type, tic.b_type, tic.a_type);
139 params.type = GetFormatType(params.pixel_format); 139 params.type = GetFormatType(params.pixel_format);
140 params.type = GetFormatType(params.pixel_format); 140 params.type = GetFormatType(params.pixel_format);
141 params.target = ImageTypeToSurfaceTarget(entry.GetType()); 141 params.target = ImageTypeToSurfaceTarget(entry.type);
142 // TODO: on 1DBuffer we should use the tic info. 142 // TODO: on 1DBuffer we should use the tic info.
143 if (tic.IsBuffer()) { 143 if (tic.IsBuffer()) {
144 params.target = SurfaceTarget::TextureBuffer; 144 params.target = SurfaceTarget::TextureBuffer;
@@ -248,12 +248,12 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
248 248
249VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget( 249VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget(
250 const VideoCommon::Shader::Sampler& entry) { 250 const VideoCommon::Shader::Sampler& entry) {
251 return TextureTypeToSurfaceTarget(entry.GetType(), entry.IsArray()); 251 return TextureTypeToSurfaceTarget(entry.type, entry.is_array);
252} 252}
253 253
254VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget( 254VideoCore::Surface::SurfaceTarget SurfaceParams::ExpectedTarget(
255 const VideoCommon::Shader::Image& entry) { 255 const VideoCommon::Shader::Image& entry) {
256 return ImageTypeToSurfaceTarget(entry.GetType()); 256 return ImageTypeToSurfaceTarget(entry.type);
257} 257}
258 258
259bool SurfaceParams::IsLayered() const { 259bool SurfaceParams::IsLayered() const {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cf6bd005a..215d4254d 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1156,7 +1156,7 @@ private:
1156 /// Returns true the shader sampler entry is compatible with the TIC texture type. 1156 /// Returns true the shader sampler entry is compatible with the TIC texture type.
1157 static bool IsTypeCompatible(Tegra::Texture::TextureType tic_type, 1157 static bool IsTypeCompatible(Tegra::Texture::TextureType tic_type,
1158 const VideoCommon::Shader::Sampler& entry) { 1158 const VideoCommon::Shader::Sampler& entry) {
1159 const auto shader_type = entry.GetType(); 1159 const auto shader_type = entry.type;
1160 switch (tic_type) { 1160 switch (tic_type) {
1161 case Tegra::Texture::TextureType::Texture1D: 1161 case Tegra::Texture::TextureType::Texture1D:
1162 case Tegra::Texture::TextureType::Texture1DArray: 1162 case Tegra::Texture::TextureType::Texture1DArray:
@@ -1177,7 +1177,7 @@ private:
1177 if (shader_type == Tegra::Shader::TextureType::TextureCube) { 1177 if (shader_type == Tegra::Shader::TextureType::TextureCube) {
1178 return true; 1178 return true;
1179 } 1179 }
1180 return shader_type == Tegra::Shader::TextureType::Texture2D && entry.IsArray(); 1180 return shader_type == Tegra::Shader::TextureType::Texture2D && entry.is_array;
1181 } 1181 }
1182 UNREACHABLE(); 1182 UNREACHABLE();
1183 return true; 1183 return true;