summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp70
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h7
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp3
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp19
-rw-r--r--src/shader_recompiler/shader_info.h10
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h24
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp25
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp31
9 files changed, 142 insertions, 49 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index f96d5ae37..032cf5e03 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -54,28 +54,30 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
54 throw InvalidArgument("Invalid texture type {}", desc.type); 54 throw InvalidArgument("Invalid texture type {}", desc.type);
55} 55}
56 56
57spv::ImageFormat GetImageFormat(ImageFormat format) {
58 switch (format) {
59 case ImageFormat::Typeless:
60 return spv::ImageFormat::Unknown;
61 case ImageFormat::R8_UINT:
62 return spv::ImageFormat::R8ui;
63 case ImageFormat::R8_SINT:
64 return spv::ImageFormat::R8i;
65 case ImageFormat::R16_UINT:
66 return spv::ImageFormat::R16ui;
67 case ImageFormat::R16_SINT:
68 return spv::ImageFormat::R16i;
69 case ImageFormat::R32_UINT:
70 return spv::ImageFormat::R32ui;
71 case ImageFormat::R32G32_UINT:
72 return spv::ImageFormat::Rg32ui;
73 case ImageFormat::R32G32B32A32_UINT:
74 return spv::ImageFormat::Rgba32ui;
75 }
76 throw InvalidArgument("Invalid image format {}", format);
77}
78
57Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { 79Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
58 const spv::ImageFormat format{[&] { 80 const spv::ImageFormat format{GetImageFormat(desc.format)};
59 switch (desc.format) {
60 case ImageFormat::Typeless:
61 return spv::ImageFormat::Unknown;
62 case ImageFormat::R8_UINT:
63 return spv::ImageFormat::R8ui;
64 case ImageFormat::R8_SINT:
65 return spv::ImageFormat::R8i;
66 case ImageFormat::R16_UINT:
67 return spv::ImageFormat::R16ui;
68 case ImageFormat::R16_SINT:
69 return spv::ImageFormat::R16i;
70 case ImageFormat::R32_UINT:
71 return spv::ImageFormat::R32ui;
72 case ImageFormat::R32G32_UINT:
73 return spv::ImageFormat::Rg32ui;
74 case ImageFormat::R32G32B32A32_UINT:
75 return spv::ImageFormat::Rgba32ui;
76 }
77 throw InvalidArgument("Invalid image format {}", desc.format);
78 }()};
79 const Id type{ctx.U32[1]}; 81 const Id type{ctx.U32[1]};
80 switch (desc.type) { 82 switch (desc.type) {
81 case TextureType::Color1D: 83 case TextureType::Color1D:
@@ -388,6 +390,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin
388 DefineConstantBuffers(program.info, binding); 390 DefineConstantBuffers(program.info, binding);
389 DefineStorageBuffers(program.info, binding); 391 DefineStorageBuffers(program.info, binding);
390 DefineTextureBuffers(program.info, binding); 392 DefineTextureBuffers(program.info, binding);
393 DefineImageBuffers(program.info, binding);
391 DefineTextures(program.info, binding); 394 DefineTextures(program.info, binding);
392 DefineImages(program.info, binding); 395 DefineImages(program.info, binding);
393 DefineAttributeMemAccess(program.info); 396 DefineAttributeMemAccess(program.info);
@@ -883,6 +886,31 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
883 } 886 }
884} 887}
885 888
889void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
890 image_buffers.reserve(info.image_buffer_descriptors.size());
891 for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) {
892 if (desc.count != 1) {
893 throw NotImplementedException("Array of image buffers");
894 }
895 const spv::ImageFormat format{GetImageFormat(desc.format)};
896 const Id image_type{TypeImage(U32[4], spv::Dim::Buffer, false, false, false, 2, format)};
897 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
898 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
899 Decorate(id, spv::Decoration::Binding, binding);
900 Decorate(id, spv::Decoration::DescriptorSet, 0U);
901 Name(id, fmt::format("imgbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
902 const ImageBufferDefinition def{
903 .id = id,
904 .image_type = image_type,
905 };
906 image_buffers.insert(image_buffers.end(), desc.count, def);
907 if (profile.supported_spirv >= 0x00010400) {
908 interfaces.push_back(id);
909 }
910 binding += desc.count;
911 }
912}
913
886void EmitContext::DefineTextures(const Info& info, u32& binding) { 914void EmitContext::DefineTextures(const Info& info, u32& binding) {
887 textures.reserve(info.texture_descriptors.size()); 915 textures.reserve(info.texture_descriptors.size());
888 for (const TextureDescriptor& desc : info.texture_descriptors) { 916 for (const TextureDescriptor& desc : info.texture_descriptors) {
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 1f0d8be77..0da14d5f8 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -35,6 +35,11 @@ struct TextureDefinition {
35 Id image_type; 35 Id image_type;
36}; 36};
37 37
38struct ImageBufferDefinition {
39 Id id;
40 Id image_type;
41};
42
38struct ImageDefinition { 43struct ImageDefinition {
39 Id id; 44 Id id;
40 Id image_type; 45 Id image_type;
@@ -136,6 +141,7 @@ public:
136 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; 141 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{};
137 std::array<StorageDefinitions, Info::MAX_SSBOS> ssbos{}; 142 std::array<StorageDefinitions, Info::MAX_SSBOS> ssbos{};
138 std::vector<Id> texture_buffers; 143 std::vector<Id> texture_buffers;
144 std::vector<ImageBufferDefinition> image_buffers;
139 std::vector<TextureDefinition> textures; 145 std::vector<TextureDefinition> textures;
140 std::vector<ImageDefinition> images; 146 std::vector<ImageDefinition> images;
141 147
@@ -213,6 +219,7 @@ private:
213 void DefineConstantBuffers(const Info& info, u32& binding); 219 void DefineConstantBuffers(const Info& info, u32& binding);
214 void DefineStorageBuffers(const Info& info, u32& binding); 220 void DefineStorageBuffers(const Info& info, u32& binding);
215 void DefineTextureBuffers(const Info& info, u32& binding); 221 void DefineTextureBuffers(const Info& info, u32& binding);
222 void DefineImageBuffers(const Info& info, u32& binding);
216 void DefineTextures(const Info& info, u32& binding); 223 void DefineTextures(const Info& info, u32& binding);
217 void DefineImages(const Info& info, u32& binding); 224 void DefineImages(const Info& info, u32& binding);
218 void DefineAttributeMemAccess(const Info& info); 225 void DefineAttributeMemAccess(const Info& info);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 17266ce77..c8d1d25b1 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -149,7 +149,8 @@ Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
149 throw NotImplementedException("Indirect image indexing"); 149 throw NotImplementedException("Indirect image indexing");
150 } 150 }
151 if (info.type == TextureType::Buffer) { 151 if (info.type == TextureType::Buffer) {
152 throw NotImplementedException("Image buffer"); 152 const ImageBufferDefinition def{ctx.image_buffers.at(index.U32())};
153 return ctx.OpLoad(def.image_type, def.id);
153 } else { 154 } else {
154 const ImageDefinition def{ctx.images.at(index.U32())}; 155 const ImageDefinition def{ctx.images.at(index.U32())};
155 return ctx.OpLoad(def.image_type, def.id); 156 return ctx.OpLoad(def.image_type, def.id);
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index a7b1fcfad..e1d5a2ce1 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -158,9 +158,11 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
158class Descriptors { 158class Descriptors {
159public: 159public:
160 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, 160 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
161 ImageBufferDescriptors& image_buffer_descriptors_,
161 TextureDescriptors& texture_descriptors_, 162 TextureDescriptors& texture_descriptors_,
162 ImageDescriptors& image_descriptors_) 163 ImageDescriptors& image_descriptors_)
163 : texture_buffer_descriptors{texture_buffer_descriptors_}, 164 : texture_buffer_descriptors{texture_buffer_descriptors_},
165 image_buffer_descriptors{image_buffer_descriptors_},
164 texture_descriptors{texture_descriptors_}, image_descriptors{image_descriptors_} {} 166 texture_descriptors{texture_descriptors_}, image_descriptors{image_descriptors_} {}
165 167
166 u32 Add(const TextureBufferDescriptor& desc) { 168 u32 Add(const TextureBufferDescriptor& desc) {
@@ -170,6 +172,13 @@ public:
170 }); 172 });
171 } 173 }
172 174
175 u32 Add(const ImageBufferDescriptor& desc) {
176 return Add(image_buffer_descriptors, desc, [&desc](const auto& existing) {
177 return desc.format == existing.format && desc.cbuf_index == existing.cbuf_index &&
178 desc.cbuf_offset == existing.cbuf_offset;
179 });
180 }
181
173 u32 Add(const TextureDescriptor& desc) { 182 u32 Add(const TextureDescriptor& desc) {
174 return Add(texture_descriptors, desc, [&desc](const auto& existing) { 183 return Add(texture_descriptors, desc, [&desc](const auto& existing) {
175 return desc.cbuf_index == existing.cbuf_index && 184 return desc.cbuf_index == existing.cbuf_index &&
@@ -200,6 +209,7 @@ private:
200 } 209 }
201 210
202 TextureBufferDescriptors& texture_buffer_descriptors; 211 TextureBufferDescriptors& texture_buffer_descriptors;
212 ImageBufferDescriptors& image_buffer_descriptors;
203 TextureDescriptors& texture_descriptors; 213 TextureDescriptors& texture_descriptors;
204 ImageDescriptors& image_descriptors; 214 ImageDescriptors& image_descriptors;
205}; 215};
@@ -224,6 +234,7 @@ void TexturePass(Environment& env, IR::Program& program) {
224 }); 234 });
225 Descriptors descriptors{ 235 Descriptors descriptors{
226 program.info.texture_buffer_descriptors, 236 program.info.texture_buffer_descriptors,
237 program.info.image_buffer_descriptors,
227 program.info.texture_descriptors, 238 program.info.texture_descriptors,
228 program.info.image_descriptors, 239 program.info.image_descriptors,
229 }; 240 };
@@ -261,7 +272,13 @@ void TexturePass(Environment& env, IR::Program& program) {
261 case IR::Opcode::ImageWrite: { 272 case IR::Opcode::ImageWrite: {
262 const bool is_written{inst->GetOpcode() == IR::Opcode::ImageWrite}; 273 const bool is_written{inst->GetOpcode() == IR::Opcode::ImageWrite};
263 if (flags.type == TextureType::Buffer) { 274 if (flags.type == TextureType::Buffer) {
264 throw NotImplementedException("Image buffer"); 275 index = descriptors.Add(ImageBufferDescriptor{
276 .format = flags.image_format,
277 .is_written = is_written,
278 .cbuf_index = cbuf.index,
279 .cbuf_offset = cbuf.offset,
280 .count = 1,
281 });
265 } else { 282 } else {
266 index = descriptors.Add(ImageDescriptor{ 283 index = descriptors.Add(ImageDescriptor{
267 .type = flags.type, 284 .type = flags.type,
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index e078b0fa1..336c6131a 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -67,6 +67,15 @@ struct TextureBufferDescriptor {
67}; 67};
68using TextureBufferDescriptors = boost::container::small_vector<TextureBufferDescriptor, 6>; 68using TextureBufferDescriptors = boost::container::small_vector<TextureBufferDescriptor, 6>;
69 69
70struct ImageBufferDescriptor {
71 ImageFormat format;
72 bool is_written;
73 u32 cbuf_index;
74 u32 cbuf_offset;
75 u32 count;
76};
77using ImageBufferDescriptors = boost::container::small_vector<ImageBufferDescriptor, 2>;
78
70struct TextureDescriptor { 79struct TextureDescriptor {
71 TextureType type; 80 TextureType type;
72 bool is_depth; 81 bool is_depth;
@@ -153,6 +162,7 @@ struct Info {
153 constant_buffer_descriptors; 162 constant_buffer_descriptors;
154 boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; 163 boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors;
155 TextureBufferDescriptors texture_buffer_descriptors; 164 TextureBufferDescriptors texture_buffer_descriptors;
165 ImageBufferDescriptors image_buffer_descriptors;
156 TextureDescriptors texture_descriptors; 166 TextureDescriptors texture_descriptors;
157 ImageDescriptors image_descriptors; 167 ImageDescriptors image_descriptors;
158}; 168};
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 6701aab82..29746f61d 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -154,7 +154,7 @@ public:
154 void UnbindGraphicsTextureBuffers(size_t stage); 154 void UnbindGraphicsTextureBuffers(size_t stage);
155 155
156 void BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, u32 size, 156 void BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, u32 size,
157 PixelFormat format); 157 PixelFormat format, bool is_written);
158 158
159 void UnbindComputeStorageBuffers(); 159 void UnbindComputeStorageBuffers();
160 160
@@ -163,8 +163,8 @@ public:
163 163
164 void UnbindComputeTextureBuffers(); 164 void UnbindComputeTextureBuffers();
165 165
166 void BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, 166 void BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, PixelFormat format,
167 PixelFormat format); 167 bool is_written);
168 168
169 void FlushCachedWrites(); 169 void FlushCachedWrites();
170 170
@@ -393,7 +393,9 @@ private:
393 u32 written_compute_storage_buffers = 0; 393 u32 written_compute_storage_buffers = 0;
394 394
395 std::array<u32, NUM_STAGES> enabled_texture_buffers{}; 395 std::array<u32, NUM_STAGES> enabled_texture_buffers{};
396 std::array<u32, NUM_STAGES> written_texture_buffers{};
396 u32 enabled_compute_texture_buffers = 0; 397 u32 enabled_compute_texture_buffers = 0;
398 u32 written_compute_texture_buffers = 0;
397 399
398 std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{}; 400 std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{};
399 401
@@ -700,12 +702,14 @@ void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index,
700template <class P> 702template <class P>
701void BufferCache<P>::UnbindGraphicsTextureBuffers(size_t stage) { 703void BufferCache<P>::UnbindGraphicsTextureBuffers(size_t stage) {
702 enabled_texture_buffers[stage] = 0; 704 enabled_texture_buffers[stage] = 0;
705 written_texture_buffers[stage] = 0;
703} 706}
704 707
705template <class P> 708template <class P>
706void BufferCache<P>::BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, 709void BufferCache<P>::BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr,
707 u32 size, PixelFormat format) { 710 u32 size, PixelFormat format, bool is_written) {
708 enabled_texture_buffers[stage] |= 1U << tbo_index; 711 enabled_texture_buffers[stage] |= 1U << tbo_index;
712 written_texture_buffers[stage] |= (is_written ? 1U : 0U) << tbo_index;
709 texture_buffers[stage][tbo_index] = GetTextureBufferBinding(gpu_addr, size, format); 713 texture_buffers[stage][tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
710} 714}
711 715
@@ -732,12 +736,14 @@ void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index,
732template <class P> 736template <class P>
733void BufferCache<P>::UnbindComputeTextureBuffers() { 737void BufferCache<P>::UnbindComputeTextureBuffers() {
734 enabled_compute_texture_buffers = 0; 738 enabled_compute_texture_buffers = 0;
739 written_compute_texture_buffers = 0;
735} 740}
736 741
737template <class P> 742template <class P>
738void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, 743void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
739 PixelFormat format) { 744 PixelFormat format, bool is_written) {
740 enabled_compute_texture_buffers |= 1U << tbo_index; 745 enabled_compute_texture_buffers |= 1U << tbo_index;
746 written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
741 compute_texture_buffers[tbo_index] = GetTextureBufferBinding(gpu_addr, size, format); 747 compute_texture_buffers[tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
742} 748}
743 749
@@ -1274,6 +1280,10 @@ void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
1274 ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) { 1280 ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) {
1275 Binding& binding = texture_buffers[stage][index]; 1281 Binding& binding = texture_buffers[stage][index];
1276 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1282 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
1283 // Mark buffer as written if needed
1284 if (((written_texture_buffers[stage] >> index) & 1) != 0) {
1285 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
1286 }
1277 }); 1287 });
1278} 1288}
1279 1289
@@ -1343,6 +1353,10 @@ void BufferCache<P>::UpdateComputeTextureBuffers() {
1343 ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) { 1353 ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) {
1344 Binding& binding = compute_texture_buffers[index]; 1354 Binding& binding = compute_texture_buffers[index];
1345 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1355 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
1356 // Mark as written if needed
1357 if (((written_compute_texture_buffers >> index) & 1) != 0) {
1358 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
1359 }
1346 }); 1360 });
1347} 1361}
1348 1362
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index e2167dc4b..aaf9a735e 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -88,6 +88,7 @@ public:
88 Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors.size()); 88 Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors.size());
89 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors.size()); 89 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors.size());
90 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors.size()); 90 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors.size());
91 Add(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, stage, info.image_buffer_descriptors.size());
91 Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage, info.texture_descriptors.size()); 92 Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage, info.texture_descriptors.size());
92 Add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stage, info.image_descriptors.size()); 93 Add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stage, info.image_descriptors.size());
93 } 94 }
@@ -126,6 +127,7 @@ inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& sam
126 const ImageId*& image_view_ids, TextureCache& texture_cache, 127 const ImageId*& image_view_ids, TextureCache& texture_cache,
127 VKUpdateDescriptorQueue& update_descriptor_queue) { 128 VKUpdateDescriptorQueue& update_descriptor_queue) {
128 image_view_ids += info.texture_buffer_descriptors.size(); 129 image_view_ids += info.texture_buffer_descriptors.size();
130 image_view_ids += info.image_buffer_descriptors.size();
129 for (const auto& desc : info.texture_descriptors) { 131 for (const auto& desc : info.texture_descriptors) {
130 const VkSampler sampler{*(samplers++)}; 132 const VkSampler sampler{*(samplers++)};
131 ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; 133 ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 3d690f335..3c907ec5a 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -97,10 +97,12 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
97 const u32 raw_handle{gpu_memory.Read<u32>(addr)}; 97 const u32 raw_handle{gpu_memory.Read<u32>(addr)};
98 return TextureHandle(raw_handle, via_header_index); 98 return TextureHandle(raw_handle, via_header_index);
99 }}; 99 }};
100 for (const auto& desc : info.texture_buffer_descriptors) { 100 const auto add_image{[&](const auto& desc) {
101 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 101 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
102 image_view_indices.push_back(handle.image); 102 image_view_indices.push_back(handle.image);
103 } 103 }};
104 std::ranges::for_each(info.texture_buffer_descriptors, add_image);
105 std::ranges::for_each(info.image_buffer_descriptors, add_image);
104 for (const auto& desc : info.texture_descriptors) { 106 for (const auto& desc : info.texture_descriptors) {
105 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 107 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
106 image_view_indices.push_back(handle.image); 108 image_view_indices.push_back(handle.image);
@@ -108,24 +110,29 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
108 Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); 110 Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler);
109 samplers.push_back(sampler->Handle()); 111 samplers.push_back(sampler->Handle());
110 } 112 }
111 for (const auto& desc : info.image_descriptors) { 113 std::ranges::for_each(info.image_descriptors, add_image);
112 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 114
113 image_view_indices.push_back(handle.image);
114 }
115 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 115 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
116 texture_cache.FillComputeImageViews(indices_span, image_view_ids); 116 texture_cache.FillComputeImageViews(indices_span, image_view_ids);
117 117
118 buffer_cache.UnbindComputeTextureBuffers(); 118 buffer_cache.UnbindComputeTextureBuffers();
119 ImageId* texture_buffer_ids{image_view_ids.data()}; 119 ImageId* texture_buffer_ids{image_view_ids.data()};
120 size_t index{}; 120 size_t index{};
121 for (const auto& desc : info.texture_buffer_descriptors) { 121 const auto add_buffer{[&](const auto& desc) {
122 ASSERT(desc.count == 1); 122 ASSERT(desc.count == 1);
123 bool is_written{false};
124 if constexpr (std::is_same_v<decltype(desc), const Shader::ImageBufferDescriptor&>) {
125 is_written = desc.is_written;
126 }
123 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids); 127 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids);
124 buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(), 128 buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(),
125 image_view.format); 129 image_view.format, is_written);
126 ++texture_buffer_ids; 130 ++texture_buffer_ids;
127 ++index; 131 ++index;
128 } 132 }};
133 std::ranges::for_each(info.texture_buffer_descriptors, add_buffer);
134 std::ranges::for_each(info.image_buffer_descriptors, add_buffer);
135
129 buffer_cache.UpdateComputeBuffers(); 136 buffer_cache.UpdateComputeBuffers();
130 buffer_cache.BindHostComputeBuffers(); 137 buffer_cache.BindHostComputeBuffers();
131 138
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 23c01f24e..84720a6f9 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -175,10 +175,12 @@ void GraphicsPipeline::Configure(bool is_indexed) {
175 const u32 raw_handle{gpu_memory.Read<u32>(addr)}; 175 const u32 raw_handle{gpu_memory.Read<u32>(addr)};
176 return TextureHandle(raw_handle, via_header_index); 176 return TextureHandle(raw_handle, via_header_index);
177 }}; 177 }};
178 for (const auto& desc : info.texture_buffer_descriptors) { 178 const auto add_image{[&](const auto& desc) {
179 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 179 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
180 image_view_indices.push_back(handle.image); 180 image_view_indices.push_back(handle.image);
181 } 181 }};
182 std::ranges::for_each(info.texture_buffer_descriptors, add_image);
183 std::ranges::for_each(info.image_buffer_descriptors, add_image);
182 for (const auto& desc : info.texture_descriptors) { 184 for (const auto& desc : info.texture_descriptors) {
183 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 185 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
184 image_view_indices.push_back(handle.image); 186 image_view_indices.push_back(handle.image);
@@ -186,28 +188,33 @@ void GraphicsPipeline::Configure(bool is_indexed) {
186 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; 188 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
187 samplers.push_back(sampler->Handle()); 189 samplers.push_back(sampler->Handle());
188 } 190 }
189 for (const auto& desc : info.image_descriptors) { 191 std::ranges::for_each(info.image_descriptors, add_image);
190 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
191 image_view_indices.push_back(handle.image);
192 }
193 } 192 }
194 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 193 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
195 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); 194 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
196 195
197 ImageId* texture_buffer_index{image_view_ids.data()}; 196 ImageId* texture_buffer_index{image_view_ids.data()};
198 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 197 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
199 const Shader::Info& info{stage_infos[stage]};
200 buffer_cache.UnbindGraphicsTextureBuffers(stage);
201 size_t index{}; 198 size_t index{};
202 for (const auto& desc : info.texture_buffer_descriptors) { 199 const auto add_buffer{[&](const auto& desc) {
203 ASSERT(desc.count == 1); 200 ASSERT(desc.count == 1);
204 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_index); 201 bool is_written{false};
202 if constexpr (std::is_same_v<decltype(desc), const Shader::ImageBufferDescriptor&>) {
203 is_written = desc.is_written;
204 }
205 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)};
205 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), 206 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
206 image_view.BufferSize(), image_view.format); 207 image_view.BufferSize(), image_view.format,
208 is_written);
207 ++index; 209 ++index;
208 ++texture_buffer_index; 210 ++texture_buffer_index;
209 } 211 }};
212 const Shader::Info& info{stage_infos[stage]};
213 buffer_cache.UnbindGraphicsTextureBuffers(stage);
214 std::ranges::for_each(info.texture_buffer_descriptors, add_buffer);
215 std::ranges::for_each(info.image_buffer_descriptors, add_buffer);
210 texture_buffer_index += info.texture_descriptors.size(); 216 texture_buffer_index += info.texture_descriptors.size();
217 texture_buffer_index += info.image_descriptors.size();
211 } 218 }
212 buffer_cache.UpdateGraphicsBuffers(is_indexed); 219 buffer_cache.UpdateGraphicsBuffers(is_indexed);
213 220