summaryrefslogtreecommitdiff
path: root/src/video_core/shader
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-12-30 02:25:23 -0300
committerGravatar ReinUsesLisp2020-12-30 03:38:50 -0300
commit9764c13d6d2977903f407761b27d847c0056e1c4 (patch)
treef6f5d6d6379b0404147969e7d1f548ed3d49ca01 /src/video_core/shader
parentvideo_core: Add a delayed destruction ring abstraction (diff)
downloadyuzu-9764c13d6d2977903f407761b27d847c0056e1c4.tar.gz
yuzu-9764c13d6d2977903f407761b27d847c0056e1c4.tar.xz
yuzu-9764c13d6d2977903f407761b27d847c0056e1c4.zip
video_core: Rewrite the texture cache
The current texture cache has several points that hurt maintainability and performance. It's easy to break unrelated parts of the cache when doing minor changes. The cache can easily forget valuable information about the cached textures by CPU writes or simply by its normal usage.The current texture cache has several points that hurt maintainability and performance. It's easy to break unrelated parts of the cache when doing minor changes. The cache can easily forget valuable information about the cached textures by CPU writes or simply by its normal usage. This commit aims to address those issues.
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/async_shaders.cpp9
-rw-r--r--src/video_core/shader/async_shaders.h6
-rw-r--r--src/video_core/shader/decode.cpp6
-rw-r--r--src/video_core/shader/decode/image.cpp11
-rw-r--r--src/video_core/shader/decode/texture.cpp56
-rw-r--r--src/video_core/shader/node.h33
-rw-r--r--src/video_core/shader/shader_ir.h18
7 files changed, 70 insertions, 69 deletions
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp
index 78245473c..09f93463b 100644
--- a/src/video_core/shader/async_shaders.cpp
+++ b/src/video_core/shader/async_shaders.cpp
@@ -137,10 +137,9 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache,
137 const Vulkan::VKDevice& device, Vulkan::VKScheduler& scheduler, 137 const Vulkan::VKDevice& device, Vulkan::VKScheduler& scheduler,
138 Vulkan::VKDescriptorPool& descriptor_pool, 138 Vulkan::VKDescriptorPool& descriptor_pool,
139 Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue, 139 Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue,
140 Vulkan::VKRenderPassCache& renderpass_cache,
141 std::vector<VkDescriptorSetLayoutBinding> bindings, 140 std::vector<VkDescriptorSetLayoutBinding> bindings,
142 Vulkan::SPIRVProgram program, 141 Vulkan::SPIRVProgram program,
143 Vulkan::GraphicsPipelineCacheKey key) { 142 Vulkan::GraphicsPipelineCacheKey key, u32 num_color_buffers) {
144 std::unique_lock lock(queue_mutex); 143 std::unique_lock lock(queue_mutex);
145 pending_queue.push({ 144 pending_queue.push({
146 .backend = Backend::Vulkan, 145 .backend = Backend::Vulkan,
@@ -149,10 +148,10 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache,
149 .scheduler = &scheduler, 148 .scheduler = &scheduler,
150 .descriptor_pool = &descriptor_pool, 149 .descriptor_pool = &descriptor_pool,
151 .update_descriptor_queue = &update_descriptor_queue, 150 .update_descriptor_queue = &update_descriptor_queue,
152 .renderpass_cache = &renderpass_cache,
153 .bindings = std::move(bindings), 151 .bindings = std::move(bindings),
154 .program = std::move(program), 152 .program = std::move(program),
155 .key = key, 153 .key = key,
154 .num_color_buffers = num_color_buffers,
156 }); 155 });
157 cv.notify_one(); 156 cv.notify_one();
158} 157}
@@ -205,8 +204,8 @@ void AsyncShaders::ShaderCompilerThread(Core::Frontend::GraphicsContext* context
205 } else if (work.backend == Backend::Vulkan) { 204 } else if (work.backend == Backend::Vulkan) {
206 auto pipeline = std::make_unique<Vulkan::VKGraphicsPipeline>( 205 auto pipeline = std::make_unique<Vulkan::VKGraphicsPipeline>(
207 *work.vk_device, *work.scheduler, *work.descriptor_pool, 206 *work.vk_device, *work.scheduler, *work.descriptor_pool,
208 *work.update_descriptor_queue, *work.renderpass_cache, work.key, work.bindings, 207 *work.update_descriptor_queue, work.key, work.bindings, work.program,
209 work.program); 208 work.num_color_buffers);
210 209
211 work.pp_cache->EmplacePipeline(std::move(pipeline)); 210 work.pp_cache->EmplacePipeline(std::move(pipeline));
212 } 211 }
diff --git a/src/video_core/shader/async_shaders.h b/src/video_core/shader/async_shaders.h
index 5a7216019..004e214a8 100644
--- a/src/video_core/shader/async_shaders.h
+++ b/src/video_core/shader/async_shaders.h
@@ -98,9 +98,9 @@ public:
98 Vulkan::VKScheduler& scheduler, 98 Vulkan::VKScheduler& scheduler,
99 Vulkan::VKDescriptorPool& descriptor_pool, 99 Vulkan::VKDescriptorPool& descriptor_pool,
100 Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue, 100 Vulkan::VKUpdateDescriptorQueue& update_descriptor_queue,
101 Vulkan::VKRenderPassCache& renderpass_cache,
102 std::vector<VkDescriptorSetLayoutBinding> bindings, 101 std::vector<VkDescriptorSetLayoutBinding> bindings,
103 Vulkan::SPIRVProgram program, Vulkan::GraphicsPipelineCacheKey key); 102 Vulkan::SPIRVProgram program, Vulkan::GraphicsPipelineCacheKey key,
103 u32 num_color_buffers);
104 104
105private: 105private:
106 void ShaderCompilerThread(Core::Frontend::GraphicsContext* context); 106 void ShaderCompilerThread(Core::Frontend::GraphicsContext* context);
@@ -127,10 +127,10 @@ private:
127 Vulkan::VKScheduler* scheduler; 127 Vulkan::VKScheduler* scheduler;
128 Vulkan::VKDescriptorPool* descriptor_pool; 128 Vulkan::VKDescriptorPool* descriptor_pool;
129 Vulkan::VKUpdateDescriptorQueue* update_descriptor_queue; 129 Vulkan::VKUpdateDescriptorQueue* update_descriptor_queue;
130 Vulkan::VKRenderPassCache* renderpass_cache;
131 std::vector<VkDescriptorSetLayoutBinding> bindings; 130 std::vector<VkDescriptorSetLayoutBinding> bindings;
132 Vulkan::SPIRVProgram program; 131 Vulkan::SPIRVProgram program;
133 Vulkan::GraphicsPipelineCacheKey key; 132 Vulkan::GraphicsPipelineCacheKey key;
133 u32 num_color_buffers;
134 }; 134 };
135 135
136 std::condition_variable cv; 136 std::condition_variable cv;
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index ab14c1aa3..6576d1208 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -25,7 +25,7 @@ using Tegra::Shader::OpCode;
25namespace { 25namespace {
26 26
27void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile& gpu_driver, 27void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile& gpu_driver,
28 const std::list<Sampler>& used_samplers) { 28 const std::list<SamplerEntry>& used_samplers) {
29 if (gpu_driver.IsTextureHandlerSizeKnown() || used_samplers.size() <= 1) { 29 if (gpu_driver.IsTextureHandlerSizeKnown() || used_samplers.size() <= 1) {
30 return; 30 return;
31 } 31 }
@@ -43,9 +43,9 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile& gpu_driver,
43 } 43 }
44} 44}
45 45
46std::optional<u32> TryDeduceSamplerSize(const Sampler& sampler_to_deduce, 46std::optional<u32> TryDeduceSamplerSize(const SamplerEntry& sampler_to_deduce,
47 VideoCore::GuestDriverProfile& gpu_driver, 47 VideoCore::GuestDriverProfile& gpu_driver,
48 const std::list<Sampler>& used_samplers) { 48 const std::list<SamplerEntry>& used_samplers) {
49 const u32 base_offset = sampler_to_deduce.offset; 49 const u32 base_offset = sampler_to_deduce.offset;
50 u32 max_offset{std::numeric_limits<u32>::max()}; 50 u32 max_offset{std::numeric_limits<u32>::max()};
51 for (const auto& sampler : used_samplers) { 51 for (const auto& sampler : used_samplers) {
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index 532f66d27..5470e8cf4 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -497,11 +497,12 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
497 return pc; 497 return pc;
498} 498}
499 499
500Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { 500ImageEntry& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
501 const auto offset = static_cast<u32>(image.index.Value()); 501 const auto offset = static_cast<u32>(image.index.Value());
502 502
503 const auto it = std::find_if(std::begin(used_images), std::end(used_images), 503 const auto it =
504 [offset](const Image& entry) { return entry.offset == offset; }); 504 std::find_if(std::begin(used_images), std::end(used_images),
505 [offset](const ImageEntry& entry) { return entry.offset == offset; });
505 if (it != std::end(used_images)) { 506 if (it != std::end(used_images)) {
506 ASSERT(!it->is_bindless && it->type == type); 507 ASSERT(!it->is_bindless && it->type == type);
507 return *it; 508 return *it;
@@ -511,7 +512,7 @@ Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType t
511 return used_images.emplace_back(next_index, offset, type); 512 return used_images.emplace_back(next_index, offset, type);
512} 513}
513 514
514Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { 515ImageEntry& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) {
515 const Node image_register = GetRegister(reg); 516 const Node image_register = GetRegister(reg);
516 const auto result = 517 const auto result =
517 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size())); 518 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()));
@@ -520,7 +521,7 @@ Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::Im
520 const auto offset = std::get<2>(result); 521 const auto offset = std::get<2>(result);
521 522
522 const auto it = std::find_if(std::begin(used_images), std::end(used_images), 523 const auto it = std::find_if(std::begin(used_images), std::end(used_images),
523 [buffer, offset](const Image& entry) { 524 [buffer, offset](const ImageEntry& entry) {
524 return entry.buffer == buffer && entry.offset == offset; 525 return entry.buffer == buffer && entry.offset == offset;
525 }); 526 });
526 if (it != std::end(used_images)) { 527 if (it != std::end(used_images)) {
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index fb18f631f..833fa2a39 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) {
141 141
142 SamplerInfo info; 142 SamplerInfo info;
143 info.is_shadow = is_depth_compare; 143 info.is_shadow = is_depth_compare;
144 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info); 144 const std::optional<SamplerEntry> sampler = GetSampler(instr.sampler, info);
145 145
146 Node4 values; 146 Node4 values;
147 for (u32 element = 0; element < values.size(); ++element) { 147 for (u32 element = 0; element < values.size(); ++element) {
@@ -173,9 +173,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
173 SamplerInfo info; 173 SamplerInfo info;
174 info.type = texture_type; 174 info.type = texture_type;
175 info.is_array = is_array; 175 info.is_array = is_array;
176 const std::optional<Sampler> sampler = is_bindless 176 const std::optional<SamplerEntry> sampler =
177 ? GetBindlessSampler(base_reg, info, index_var) 177 is_bindless ? GetBindlessSampler(base_reg, info, index_var)
178 : GetSampler(instr.sampler, info); 178 : GetSampler(instr.sampler, info);
179 Node4 values; 179 Node4 values;
180 if (!sampler) { 180 if (!sampler) {
181 std::generate(values.begin(), values.end(), [this] { return Immediate(0); }); 181 std::generate(values.begin(), values.end(), [this] { return Immediate(0); });
@@ -217,9 +217,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
217 [[fallthrough]]; 217 [[fallthrough]];
218 case OpCode::Id::TXQ: { 218 case OpCode::Id::TXQ: {
219 Node index_var; 219 Node index_var;
220 const std::optional<Sampler> sampler = is_bindless 220 const std::optional<SamplerEntry> sampler =
221 ? GetBindlessSampler(instr.gpr8, {}, index_var) 221 is_bindless ? GetBindlessSampler(instr.gpr8, {}, index_var)
222 : GetSampler(instr.sampler, {}); 222 : GetSampler(instr.sampler, {});
223 223
224 if (!sampler) { 224 if (!sampler) {
225 u32 indexer = 0; 225 u32 indexer = 0;
@@ -272,7 +272,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
272 info.type = texture_type; 272 info.type = texture_type;
273 info.is_array = is_array; 273 info.is_array = is_array;
274 Node index_var; 274 Node index_var;
275 const std::optional<Sampler> sampler = 275 const std::optional<SamplerEntry> sampler =
276 is_bindless ? GetBindlessSampler(instr.gpr20, info, index_var) 276 is_bindless ? GetBindlessSampler(instr.gpr20, info, index_var)
277 : GetSampler(instr.sampler, info); 277 : GetSampler(instr.sampler, info);
278 278
@@ -379,14 +379,15 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(
379 return info; 379 return info;
380} 380}
381 381
382std::optional<Sampler> ShaderIR::GetSampler(Tegra::Shader::Sampler sampler, 382std::optional<SamplerEntry> ShaderIR::GetSampler(Tegra::Shader::Sampler sampler,
383 SamplerInfo sampler_info) { 383 SamplerInfo sampler_info) {
384 const u32 offset = static_cast<u32>(sampler.index.Value()); 384 const u32 offset = static_cast<u32>(sampler.index.Value());
385 const auto info = GetSamplerInfo(sampler_info, registry.ObtainBoundSampler(offset)); 385 const auto info = GetSamplerInfo(sampler_info, registry.ObtainBoundSampler(offset));
386 386
387 // If this sampler has already been used, return the existing mapping. 387 // If this sampler has already been used, return the existing mapping.
388 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(), 388 const auto it =
389 [offset](const Sampler& entry) { return entry.offset == offset; }); 389 std::find_if(used_samplers.begin(), used_samplers.end(),
390 [offset](const SamplerEntry& entry) { return entry.offset == offset; });
390 if (it != used_samplers.end()) { 391 if (it != used_samplers.end()) {
391 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array && 392 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array &&
392 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer); 393 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer);
@@ -399,8 +400,8 @@ std::optional<Sampler> ShaderIR::GetSampler(Tegra::Shader::Sampler sampler,
399 *info.is_shadow, *info.is_buffer, false); 400 *info.is_shadow, *info.is_buffer, false);
400} 401}
401 402
402std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, SamplerInfo info, 403std::optional<SamplerEntry> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
403 Node& index_var) { 404 SamplerInfo info, Node& index_var) {
404 const Node sampler_register = GetRegister(reg); 405 const Node sampler_register = GetRegister(reg);
405 const auto [base_node, tracked_sampler_info] = 406 const auto [base_node, tracked_sampler_info] =
406 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size())); 407 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size()));
@@ -416,7 +417,7 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
416 417
417 // If this sampler has already been used, return the existing mapping. 418 // If this sampler has already been used, return the existing mapping.
418 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(), 419 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(),
419 [buffer, offset](const Sampler& entry) { 420 [buffer, offset](const SamplerEntry& entry) {
420 return entry.buffer == buffer && entry.offset == offset; 421 return entry.buffer == buffer && entry.offset == offset;
421 }); 422 });
422 if (it != used_samplers.end()) { 423 if (it != used_samplers.end()) {
@@ -436,11 +437,12 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
436 info = GetSamplerInfo(info, registry.ObtainSeparateSampler(indices, offsets)); 437 info = GetSamplerInfo(info, registry.ObtainSeparateSampler(indices, offsets));
437 438
438 // Try to use an already created sampler if it exists 439 // Try to use an already created sampler if it exists
439 const auto it = std::find_if( 440 const auto it =
440 used_samplers.begin(), used_samplers.end(), [indices, offsets](const Sampler& entry) { 441 std::find_if(used_samplers.begin(), used_samplers.end(),
441 return offsets == std::pair{entry.offset, entry.secondary_offset} && 442 [indices, offsets](const SamplerEntry& entry) {
442 indices == std::pair{entry.buffer, entry.secondary_buffer}; 443 return offsets == std::pair{entry.offset, entry.secondary_offset} &&
443 }); 444 indices == std::pair{entry.buffer, entry.secondary_buffer};
445 });
444 if (it != used_samplers.end()) { 446 if (it != used_samplers.end()) {
445 ASSERT(it->is_separated && it->type == info.type && it->is_array == info.is_array && 447 ASSERT(it->is_separated && it->type == info.type && it->is_array == info.is_array &&
446 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer); 448 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer);
@@ -460,7 +462,7 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
460 // If this sampler has already been used, return the existing mapping. 462 // If this sampler has already been used, return the existing mapping.
461 const auto it = std::find_if( 463 const auto it = std::find_if(
462 used_samplers.begin(), used_samplers.end(), 464 used_samplers.begin(), used_samplers.end(),
463 [base_offset](const Sampler& entry) { return entry.offset == base_offset; }); 465 [base_offset](const SamplerEntry& entry) { return entry.offset == base_offset; });
464 if (it != used_samplers.end()) { 466 if (it != used_samplers.end()) {
465 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array && 467 ASSERT(!it->is_bindless && it->type == info.type && it->is_array == info.is_array &&
466 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer && 468 it->is_shadow == info.is_shadow && it->is_buffer == info.is_buffer &&
@@ -565,9 +567,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
565 info.is_buffer = false; 567 info.is_buffer = false;
566 568
567 Node index_var; 569 Node index_var;
568 const std::optional<Sampler> sampler = is_bindless 570 const std::optional<SamplerEntry> sampler =
569 ? GetBindlessSampler(*bindless_reg, info, index_var) 571 is_bindless ? GetBindlessSampler(*bindless_reg, info, index_var)
570 : GetSampler(instr.sampler, info); 572 : GetSampler(instr.sampler, info);
571 if (!sampler) { 573 if (!sampler) {
572 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)}; 574 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)};
573 } 575 }
@@ -724,7 +726,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
724 info.is_shadow = depth_compare; 726 info.is_shadow = depth_compare;
725 727
726 Node index_var; 728 Node index_var;
727 const std::optional<Sampler> sampler = 729 const std::optional<SamplerEntry> sampler =
728 is_bindless ? GetBindlessSampler(parameter_register++, info, index_var) 730 is_bindless ? GetBindlessSampler(parameter_register++, info, index_var)
729 : GetSampler(instr.sampler, info); 731 : GetSampler(instr.sampler, info);
730 Node4 values; 732 Node4 values;
@@ -783,7 +785,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
783 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; 785 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
784 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; 786 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
785 787
786 const std::optional<Sampler> sampler = GetSampler(instr.sampler, {}); 788 const std::optional<SamplerEntry> sampler = GetSampler(instr.sampler, {});
787 789
788 Node4 values; 790 Node4 values;
789 for (u32 element = 0; element < values.size(); ++element) { 791 for (u32 element = 0; element < values.size(); ++element) {
@@ -800,7 +802,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
800 info.type = texture_type; 802 info.type = texture_type;
801 info.is_array = is_array; 803 info.is_array = is_array;
802 info.is_shadow = false; 804 info.is_shadow = false;
803 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info); 805 const std::optional<SamplerEntry> sampler = GetSampler(instr.sampler, info);
804 806
805 const std::size_t type_coord_count = GetCoordCount(texture_type); 807 const std::size_t type_coord_count = GetCoordCount(texture_type);
806 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; 808 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 8db9e1de7..b54d33763 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -282,25 +282,24 @@ struct SeparateSamplerNode;
282using TrackSamplerData = std::variant<BindlessSamplerNode, SeparateSamplerNode, ArraySamplerNode>; 282using TrackSamplerData = std::variant<BindlessSamplerNode, SeparateSamplerNode, ArraySamplerNode>;
283using TrackSampler = std::shared_ptr<TrackSamplerData>; 283using TrackSampler = std::shared_ptr<TrackSamplerData>;
284 284
285struct Sampler { 285struct SamplerEntry {
286 /// Bound samplers constructor 286 /// Bound samplers constructor
287 constexpr explicit Sampler(u32 index_, u32 offset_, Tegra::Shader::TextureType type_, 287 explicit SamplerEntry(u32 index_, u32 offset_, Tegra::Shader::TextureType type_, bool is_array_,
288 bool is_array_, bool is_shadow_, bool is_buffer_, bool is_indexed_) 288 bool is_shadow_, bool is_buffer_, bool is_indexed_)
289 : index{index_}, offset{offset_}, type{type_}, is_array{is_array_}, is_shadow{is_shadow_}, 289 : index{index_}, offset{offset_}, type{type_}, is_array{is_array_}, is_shadow{is_shadow_},
290 is_buffer{is_buffer_}, is_indexed{is_indexed_} {} 290 is_buffer{is_buffer_}, is_indexed{is_indexed_} {}
291 291
292 /// Separate sampler constructor 292 /// Separate sampler constructor
293 constexpr explicit Sampler(u32 index_, std::pair<u32, u32> offsets_, 293 explicit SamplerEntry(u32 index_, std::pair<u32, u32> offsets, std::pair<u32, u32> buffers,
294 std::pair<u32, u32> buffers_, Tegra::Shader::TextureType type_, 294 Tegra::Shader::TextureType type_, bool is_array_, bool is_shadow_,
295 bool is_array_, bool is_shadow_, bool is_buffer_) 295 bool is_buffer_)
296 : index{index_}, offset{offsets_.first}, secondary_offset{offsets_.second}, 296 : index{index_}, offset{offsets.first}, secondary_offset{offsets.second},
297 buffer{buffers_.first}, secondary_buffer{buffers_.second}, type{type_}, 297 buffer{buffers.first}, secondary_buffer{buffers.second}, type{type_}, is_array{is_array_},
298 is_array{is_array_}, is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_separated{true} {} 298 is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_separated{true} {}
299 299
300 /// Bindless samplers constructor 300 /// Bindless samplers constructor
301 constexpr explicit Sampler(u32 index_, u32 offset_, u32 buffer_, 301 explicit SamplerEntry(u32 index_, u32 offset_, u32 buffer_, Tegra::Shader::TextureType type_,
302 Tegra::Shader::TextureType type_, bool is_array_, bool is_shadow_, 302 bool is_array_, bool is_shadow_, bool is_buffer_, bool is_indexed_)
303 bool is_buffer_, bool is_indexed_)
304 : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_array{is_array_}, 303 : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_array{is_array_},
305 is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_bindless{true}, is_indexed{is_indexed_} { 304 is_shadow{is_shadow_}, is_buffer{is_buffer_}, is_bindless{true}, is_indexed{is_indexed_} {
306 } 305 }
@@ -340,14 +339,14 @@ struct BindlessSamplerNode {
340 u32 offset; 339 u32 offset;
341}; 340};
342 341
343struct Image { 342struct ImageEntry {
344public: 343public:
345 /// Bound images constructor 344 /// Bound images constructor
346 constexpr explicit Image(u32 index_, u32 offset_, Tegra::Shader::ImageType type_) 345 explicit ImageEntry(u32 index_, u32 offset_, Tegra::Shader::ImageType type_)
347 : index{index_}, offset{offset_}, type{type_} {} 346 : index{index_}, offset{offset_}, type{type_} {}
348 347
349 /// Bindless samplers constructor 348 /// Bindless samplers constructor
350 constexpr explicit Image(u32 index_, u32 offset_, u32 buffer_, Tegra::Shader::ImageType type_) 349 explicit ImageEntry(u32 index_, u32 offset_, u32 buffer_, Tegra::Shader::ImageType type_)
351 : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_bindless{true} {} 350 : index{index_}, offset{offset_}, buffer{buffer_}, type{type_}, is_bindless{true} {}
352 351
353 void MarkWrite() { 352 void MarkWrite() {
@@ -391,7 +390,7 @@ struct MetaArithmetic {
391 390
392/// Parameters describing a texture sampler 391/// Parameters describing a texture sampler
393struct MetaTexture { 392struct MetaTexture {
394 Sampler sampler; 393 SamplerEntry sampler;
395 Node array; 394 Node array;
396 Node depth_compare; 395 Node depth_compare;
397 std::vector<Node> aoffi; 396 std::vector<Node> aoffi;
@@ -405,7 +404,7 @@ struct MetaTexture {
405}; 404};
406 405
407struct MetaImage { 406struct MetaImage {
408 const Image& image; 407 const ImageEntry& image;
409 std::vector<Node> values; 408 std::vector<Node> values;
410 u32 element{}; 409 u32 element{};
411}; 410};
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 6aae14e34..0c6ab0f07 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -94,11 +94,11 @@ public:
94 return used_cbufs; 94 return used_cbufs;
95 } 95 }
96 96
97 const std::list<Sampler>& GetSamplers() const { 97 const std::list<SamplerEntry>& GetSamplers() const {
98 return used_samplers; 98 return used_samplers;
99 } 99 }
100 100
101 const std::list<Image>& GetImages() const { 101 const std::list<ImageEntry>& GetImages() const {
102 return used_images; 102 return used_images;
103 } 103 }
104 104
@@ -334,17 +334,17 @@ private:
334 std::optional<Tegra::Engines::SamplerDescriptor> sampler); 334 std::optional<Tegra::Engines::SamplerDescriptor> sampler);
335 335
336 /// Accesses a texture sampler. 336 /// Accesses a texture sampler.
337 std::optional<Sampler> GetSampler(Tegra::Shader::Sampler sampler, SamplerInfo info); 337 std::optional<SamplerEntry> GetSampler(Tegra::Shader::Sampler sampler, SamplerInfo info);
338 338
339 /// Accesses a texture sampler for a bindless texture. 339 /// Accesses a texture sampler for a bindless texture.
340 std::optional<Sampler> GetBindlessSampler(Tegra::Shader::Register reg, SamplerInfo info, 340 std::optional<SamplerEntry> GetBindlessSampler(Tegra::Shader::Register reg, SamplerInfo info,
341 Node& index_var); 341 Node& index_var);
342 342
343 /// Accesses an image. 343 /// Accesses an image.
344 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); 344 ImageEntry& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);
345 345
346 /// Access a bindless image sampler. 346 /// Access a bindless image sampler.
347 Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); 347 ImageEntry& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type);
348 348
349 /// Extracts a sequence of bits from a node 349 /// Extracts a sequence of bits from a node
350 Node BitfieldExtract(Node value, u32 offset, u32 bits); 350 Node BitfieldExtract(Node value, u32 offset, u32 bits);
@@ -454,8 +454,8 @@ private:
454 std::set<Tegra::Shader::Attribute::Index> used_input_attributes; 454 std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
455 std::set<Tegra::Shader::Attribute::Index> used_output_attributes; 455 std::set<Tegra::Shader::Attribute::Index> used_output_attributes;
456 std::map<u32, ConstBuffer> used_cbufs; 456 std::map<u32, ConstBuffer> used_cbufs;
457 std::list<Sampler> used_samplers; 457 std::list<SamplerEntry> used_samplers;
458 std::list<Image> used_images; 458 std::list<ImageEntry> used_images;
459 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 459 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
460 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; 460 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
461 bool uses_layer{}; 461 bool uses_layer{};