summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-04-06 20:14:55 -0300
committerGravatar ameerj2021-07-22 21:51:26 -0400
commite9a91bc5cc2c39b476ba8946f66930f5ab5608b2 (patch)
treead75617771ba4093c5609a505e3c8926668eb533
parentshader: Fix F2I (diff)
downloadyuzu-e9a91bc5cc2c39b476ba8946f66930f5ab5608b2.tar.gz
yuzu-e9a91bc5cc2c39b476ba8946f66930f5ab5608b2.tar.xz
yuzu-e9a91bc5cc2c39b476ba8946f66930f5ab5608b2.zip
shader: Interact texture buffers with buffer cache
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp54
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h2
-rw-r--r--src/shader_recompiler/shader_info.h2
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h138
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h1
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h26
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp57
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h18
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp30
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp31
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp63
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h30
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp9
-rw-r--r--src/video_core/texture_cache/image_view_base.h1
-rw-r--r--src/video_core/texture_cache/texture_cache.h13
17 files changed, 333 insertions, 148 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index d01633628..b738e00cc 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -130,8 +130,8 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin
130 DefineSharedMemory(program); 130 DefineSharedMemory(program);
131 DefineConstantBuffers(program.info, binding); 131 DefineConstantBuffers(program.info, binding);
132 DefineStorageBuffers(program.info, binding); 132 DefineStorageBuffers(program.info, binding);
133 DefineTextures(program.info, binding);
134 DefineTextureBuffers(program.info, binding); 133 DefineTextureBuffers(program.info, binding);
134 DefineTextures(program.info, binding);
135 DefineAttributeMemAccess(program.info); 135 DefineAttributeMemAccess(program.info);
136 DefineLabels(program); 136 DefineLabels(program);
137} 137}
@@ -516,6 +516,32 @@ void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) {
516 } 516 }
517} 517}
518 518
519void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
520 if (info.texture_buffer_descriptors.empty()) {
521 return;
522 }
523 const spv::ImageFormat format{spv::ImageFormat::Unknown};
524 image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
525 sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
526
527 const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
528 texture_buffers.reserve(info.texture_buffer_descriptors.size());
529 for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
530 if (desc.count != 1) {
531 throw NotImplementedException("Array of texture buffers");
532 }
533 const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
534 Decorate(id, spv::Decoration::Binding, binding);
535 Decorate(id, spv::Decoration::DescriptorSet, 0U);
536 Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
537 texture_buffers.insert(texture_buffers.end(), desc.count, id);
538 if (profile.supported_spirv >= 0x00010400) {
539 interfaces.push_back(id);
540 }
541 binding += desc.count;
542 }
543}
544
519void EmitContext::DefineTextures(const Info& info, u32& binding) { 545void EmitContext::DefineTextures(const Info& info, u32& binding) {
520 textures.reserve(info.texture_descriptors.size()); 546 textures.reserve(info.texture_descriptors.size());
521 for (const TextureDescriptor& desc : info.texture_descriptors) { 547 for (const TextureDescriptor& desc : info.texture_descriptors) {
@@ -544,32 +570,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) {
544 } 570 }
545} 571}
546 572
547void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
548 if (info.texture_buffer_descriptors.empty()) {
549 return;
550 }
551 const spv::ImageFormat format{spv::ImageFormat::Unknown};
552 image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
553 sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
554
555 const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
556 texture_buffers.reserve(info.texture_buffer_descriptors.size());
557 for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
558 if (desc.count != 1) {
559 throw NotImplementedException("Array of texture buffers");
560 }
561 const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
562 Decorate(id, spv::Decoration::Binding, binding);
563 Decorate(id, spv::Decoration::DescriptorSet, 0U);
564 Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
565 texture_buffers.insert(texture_buffers.end(), desc.count, id);
566 if (profile.supported_spirv >= 0x00010400) {
567 interfaces.push_back(id);
568 }
569 binding += desc.count;
570 }
571}
572
573void EmitContext::DefineLabels(IR::Program& program) { 573void EmitContext::DefineLabels(IR::Program& program) {
574 for (IR::Block* const block : program.blocks) { 574 for (IR::Block* const block : program.blocks) {
575 block->SetDefinition(OpLabel()); 575 block->SetDefinition(OpLabel());
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 2a10e94e5..f1ac4430c 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -154,8 +154,8 @@ private:
154 void DefineSharedMemory(const IR::Program& program); 154 void DefineSharedMemory(const IR::Program& program);
155 void DefineConstantBuffers(const Info& info, u32& binding); 155 void DefineConstantBuffers(const Info& info, u32& binding);
156 void DefineStorageBuffers(const Info& info, u32& binding); 156 void DefineStorageBuffers(const Info& info, u32& binding);
157 void DefineTextures(const Info& info, u32& binding);
158 void DefineTextureBuffers(const Info& info, u32& binding); 157 void DefineTextureBuffers(const Info& info, u32& binding);
158 void DefineTextures(const Info& info, u32& binding);
159 void DefineAttributeMemAccess(const Info& info); 159 void DefineAttributeMemAccess(const Info& info);
160 void DefineLabels(IR::Program& program); 160 void DefineLabels(IR::Program& program);
161 161
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index e6f0de8d8..4cc731198 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -119,8 +119,8 @@ struct Info {
119 boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> 119 boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS>
120 constant_buffer_descriptors; 120 constant_buffer_descriptors;
121 boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; 121 boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors;
122 TextureDescriptors texture_descriptors;
123 TextureBufferDescriptors texture_buffer_descriptors; 122 TextureBufferDescriptors texture_buffer_descriptors;
123 TextureDescriptors texture_descriptors;
124}; 124};
125 125
126} // namespace Shader 126} // namespace Shader
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 7373cb62d..6701aab82 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -31,6 +31,7 @@
31#include "video_core/engines/maxwell_3d.h" 31#include "video_core/engines/maxwell_3d.h"
32#include "video_core/memory_manager.h" 32#include "video_core/memory_manager.h"
33#include "video_core/rasterizer_interface.h" 33#include "video_core/rasterizer_interface.h"
34#include "video_core/surface.h"
34#include "video_core/texture_cache/slot_vector.h" 35#include "video_core/texture_cache/slot_vector.h"
35#include "video_core/texture_cache/types.h" 36#include "video_core/texture_cache/types.h"
36 37
@@ -42,11 +43,14 @@ MICROPROFILE_DECLARE(GPU_DownloadMemory);
42 43
43using BufferId = SlotId; 44using BufferId = SlotId;
44 45
46using VideoCore::Surface::PixelFormat;
47
45constexpr u32 NUM_VERTEX_BUFFERS = 32; 48constexpr u32 NUM_VERTEX_BUFFERS = 32;
46constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; 49constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
47constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; 50constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
48constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; 51constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
49constexpr u32 NUM_STORAGE_BUFFERS = 16; 52constexpr u32 NUM_STORAGE_BUFFERS = 16;
53constexpr u32 NUM_TEXTURE_BUFFERS = 16;
50constexpr u32 NUM_STAGES = 5; 54constexpr u32 NUM_STAGES = 5;
51 55
52using namespace Common::Literals; 56using namespace Common::Literals;
@@ -66,6 +70,7 @@ class BufferCache {
66 P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT; 70 P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT;
67 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX; 71 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX;
68 static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX; 72 static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX;
73 static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = P::NEEDS_BIND_TEXTURE_BUFFER_INDEX;
69 static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS; 74 static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS;
70 75
71 static constexpr BufferId NULL_BUFFER_ID{0}; 76 static constexpr BufferId NULL_BUFFER_ID{0};
@@ -96,6 +101,10 @@ class BufferCache {
96 BufferId buffer_id; 101 BufferId buffer_id;
97 }; 102 };
98 103
104 struct TextureBufferBinding : Binding {
105 PixelFormat format;
106 };
107
99 static constexpr Binding NULL_BINDING{ 108 static constexpr Binding NULL_BINDING{
100 .cpu_addr = 0, 109 .cpu_addr = 0,
101 .size = 0, 110 .size = 0,
@@ -142,11 +151,21 @@ public:
142 void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, 151 void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
143 bool is_written); 152 bool is_written);
144 153
154 void UnbindGraphicsTextureBuffers(size_t stage);
155
156 void BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, u32 size,
157 PixelFormat format);
158
145 void UnbindComputeStorageBuffers(); 159 void UnbindComputeStorageBuffers();
146 160
147 void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, 161 void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
148 bool is_written); 162 bool is_written);
149 163
164 void UnbindComputeTextureBuffers();
165
166 void BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
167 PixelFormat format);
168
150 void FlushCachedWrites(); 169 void FlushCachedWrites();
151 170
152 /// Return true when there are uncommitted buffers to be downloaded 171 /// Return true when there are uncommitted buffers to be downloaded
@@ -254,12 +273,16 @@ private:
254 273
255 void BindHostGraphicsStorageBuffers(size_t stage); 274 void BindHostGraphicsStorageBuffers(size_t stage);
256 275
276 void BindHostGraphicsTextureBuffers(size_t stage);
277
257 void BindHostTransformFeedbackBuffers(); 278 void BindHostTransformFeedbackBuffers();
258 279
259 void BindHostComputeUniformBuffers(); 280 void BindHostComputeUniformBuffers();
260 281
261 void BindHostComputeStorageBuffers(); 282 void BindHostComputeStorageBuffers();
262 283
284 void BindHostComputeTextureBuffers();
285
263 void DoUpdateGraphicsBuffers(bool is_indexed); 286 void DoUpdateGraphicsBuffers(bool is_indexed);
264 287
265 void DoUpdateComputeBuffers(); 288 void DoUpdateComputeBuffers();
@@ -274,6 +297,8 @@ private:
274 297
275 void UpdateStorageBuffers(size_t stage); 298 void UpdateStorageBuffers(size_t stage);
276 299
300 void UpdateTextureBuffers(size_t stage);
301
277 void UpdateTransformFeedbackBuffers(); 302 void UpdateTransformFeedbackBuffers();
278 303
279 void UpdateTransformFeedbackBuffer(u32 index); 304 void UpdateTransformFeedbackBuffer(u32 index);
@@ -282,6 +307,8 @@ private:
282 307
283 void UpdateComputeStorageBuffers(); 308 void UpdateComputeStorageBuffers();
284 309
310 void UpdateComputeTextureBuffers();
311
285 void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size); 312 void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size);
286 313
287 [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); 314 [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
@@ -323,6 +350,9 @@ private:
323 350
324 [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const; 351 [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const;
325 352
353 [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size,
354 PixelFormat format);
355
326 [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size); 356 [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size);
327 357
328 [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); 358 [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity);
@@ -347,10 +377,12 @@ private:
347 std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers; 377 std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers;
348 std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers; 378 std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers;
349 std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers; 379 std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers;
380 std::array<std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS>, NUM_STAGES> texture_buffers;
350 std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers; 381 std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers;
351 382
352 std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers; 383 std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers;
353 std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers; 384 std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers;
385 std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS> compute_texture_buffers;
354 386
355 std::array<u32, NUM_STAGES> enabled_uniform_buffers{}; 387 std::array<u32, NUM_STAGES> enabled_uniform_buffers{};
356 u32 enabled_compute_uniform_buffers = 0; 388 u32 enabled_compute_uniform_buffers = 0;
@@ -360,6 +392,9 @@ private:
360 u32 enabled_compute_storage_buffers = 0; 392 u32 enabled_compute_storage_buffers = 0;
361 u32 written_compute_storage_buffers = 0; 393 u32 written_compute_storage_buffers = 0;
362 394
395 std::array<u32, NUM_STAGES> enabled_texture_buffers{};
396 u32 enabled_compute_texture_buffers = 0;
397
363 std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{}; 398 std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{};
364 399
365 std::array<u32, 16> uniform_cache_hits{}; 400 std::array<u32, 16> uniform_cache_hits{};
@@ -619,6 +654,7 @@ void BufferCache<P>::BindHostStageBuffers(size_t stage) {
619 MICROPROFILE_SCOPE(GPU_BindUploadBuffers); 654 MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
620 BindHostGraphicsUniformBuffers(stage); 655 BindHostGraphicsUniformBuffers(stage);
621 BindHostGraphicsStorageBuffers(stage); 656 BindHostGraphicsStorageBuffers(stage);
657 BindHostGraphicsTextureBuffers(stage);
622} 658}
623 659
624template <class P> 660template <class P>
@@ -626,6 +662,7 @@ void BufferCache<P>::BindHostComputeBuffers() {
626 MICROPROFILE_SCOPE(GPU_BindUploadBuffers); 662 MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
627 BindHostComputeUniformBuffers(); 663 BindHostComputeUniformBuffers();
628 BindHostComputeStorageBuffers(); 664 BindHostComputeStorageBuffers();
665 BindHostComputeTextureBuffers();
629} 666}
630 667
631template <class P> 668template <class P>
@@ -661,6 +698,18 @@ void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index,
661} 698}
662 699
663template <class P> 700template <class P>
701void BufferCache<P>::UnbindGraphicsTextureBuffers(size_t stage) {
702 enabled_texture_buffers[stage] = 0;
703}
704
705template <class P>
706void BufferCache<P>::BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr,
707 u32 size, PixelFormat format) {
708 enabled_texture_buffers[stage] |= 1U << tbo_index;
709 texture_buffers[stage][tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
710}
711
712template <class P>
664void BufferCache<P>::UnbindComputeStorageBuffers() { 713void BufferCache<P>::UnbindComputeStorageBuffers() {
665 enabled_compute_storage_buffers = 0; 714 enabled_compute_storage_buffers = 0;
666 written_compute_storage_buffers = 0; 715 written_compute_storage_buffers = 0;
@@ -681,6 +730,18 @@ void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index,
681} 730}
682 731
683template <class P> 732template <class P>
733void BufferCache<P>::UnbindComputeTextureBuffers() {
734 enabled_compute_texture_buffers = 0;
735}
736
737template <class P>
738void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
739 PixelFormat format) {
740 enabled_compute_texture_buffers |= 1U << tbo_index;
741 compute_texture_buffers[tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
742}
743
744template <class P>
684void BufferCache<P>::FlushCachedWrites() { 745void BufferCache<P>::FlushCachedWrites() {
685 for (const BufferId buffer_id : cached_write_buffer_ids) { 746 for (const BufferId buffer_id : cached_write_buffer_ids) {
686 slot_buffers[buffer_id].FlushCachedWrites(); 747 slot_buffers[buffer_id].FlushCachedWrites();
@@ -989,6 +1050,26 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
989} 1050}
990 1051
991template <class P> 1052template <class P>
1053void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
1054 u32 binding_index = 0;
1055 ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) {
1056 const TextureBufferBinding& binding = texture_buffers[stage][index];
1057 Buffer& buffer = slot_buffers[binding.buffer_id];
1058 const u32 size = binding.size;
1059 SynchronizeBuffer(buffer, binding.cpu_addr, size);
1060
1061 const u32 offset = buffer.Offset(binding.cpu_addr);
1062 const PixelFormat format = binding.format;
1063 if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) {
1064 runtime.BindTextureBuffer(binding_index, buffer, offset, size, format);
1065 ++binding_index;
1066 } else {
1067 runtime.BindTextureBuffer(buffer, offset, size, format);
1068 }
1069 });
1070}
1071
1072template <class P>
992void BufferCache<P>::BindHostTransformFeedbackBuffers() { 1073void BufferCache<P>::BindHostTransformFeedbackBuffers() {
993 if (maxwell3d.regs.tfb_enabled == 0) { 1074 if (maxwell3d.regs.tfb_enabled == 0) {
994 return; 1075 return;
@@ -1051,6 +1132,26 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
1051} 1132}
1052 1133
1053template <class P> 1134template <class P>
1135void BufferCache<P>::BindHostComputeTextureBuffers() {
1136 u32 binding_index = 0;
1137 ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) {
1138 const TextureBufferBinding& binding = compute_texture_buffers[index];
1139 Buffer& buffer = slot_buffers[binding.buffer_id];
1140 const u32 size = binding.size;
1141 SynchronizeBuffer(buffer, binding.cpu_addr, size);
1142
1143 const u32 offset = buffer.Offset(binding.cpu_addr);
1144 const PixelFormat format = binding.format;
1145 if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) {
1146 runtime.BindTextureBuffer(binding_index, buffer, offset, size, format);
1147 ++binding_index;
1148 } else {
1149 runtime.BindTextureBuffer(buffer, offset, size, format);
1150 }
1151 });
1152}
1153
1154template <class P>
1054void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { 1155void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
1055 if (is_indexed) { 1156 if (is_indexed) {
1056 UpdateIndexBuffer(); 1157 UpdateIndexBuffer();
@@ -1060,6 +1161,7 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
1060 for (size_t stage = 0; stage < NUM_STAGES; ++stage) { 1161 for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
1061 UpdateUniformBuffers(stage); 1162 UpdateUniformBuffers(stage);
1062 UpdateStorageBuffers(stage); 1163 UpdateStorageBuffers(stage);
1164 UpdateTextureBuffers(stage);
1063 } 1165 }
1064} 1166}
1065 1167
@@ -1067,6 +1169,7 @@ template <class P>
1067void BufferCache<P>::DoUpdateComputeBuffers() { 1169void BufferCache<P>::DoUpdateComputeBuffers() {
1068 UpdateComputeUniformBuffers(); 1170 UpdateComputeUniformBuffers();
1069 UpdateComputeStorageBuffers(); 1171 UpdateComputeStorageBuffers();
1172 UpdateComputeTextureBuffers();
1070} 1173}
1071 1174
1072template <class P> 1175template <class P>
@@ -1167,6 +1270,14 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
1167} 1270}
1168 1271
1169template <class P> 1272template <class P>
1273void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
1274 ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) {
1275 Binding& binding = texture_buffers[stage][index];
1276 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
1277 });
1278}
1279
1280template <class P>
1170void BufferCache<P>::UpdateTransformFeedbackBuffers() { 1281void BufferCache<P>::UpdateTransformFeedbackBuffers() {
1171 if (maxwell3d.regs.tfb_enabled == 0) { 1282 if (maxwell3d.regs.tfb_enabled == 0) {
1172 return; 1283 return;
@@ -1228,6 +1339,14 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
1228} 1339}
1229 1340
1230template <class P> 1341template <class P>
1342void BufferCache<P>::UpdateComputeTextureBuffers() {
1343 ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) {
1344 Binding& binding = compute_texture_buffers[index];
1345 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
1346 });
1347}
1348
1349template <class P>
1231void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { 1350void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
1232 Buffer& buffer = slot_buffers[buffer_id]; 1351 Buffer& buffer = slot_buffers[buffer_id];
1233 buffer.MarkRegionAsGpuModified(cpu_addr, size); 1352 buffer.MarkRegionAsGpuModified(cpu_addr, size);
@@ -1582,6 +1701,25 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
1582} 1701}
1583 1702
1584template <class P> 1703template <class P>
1704typename BufferCache<P>::TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(
1705 GPUVAddr gpu_addr, u32 size, PixelFormat format) {
1706 const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
1707 TextureBufferBinding binding;
1708 if (!cpu_addr || size == 0) {
1709 binding.cpu_addr = 0;
1710 binding.size = 0;
1711 binding.buffer_id = NULL_BUFFER_ID;
1712 binding.format = PixelFormat::Invalid;
1713 } else {
1714 binding.cpu_addr = *cpu_addr;
1715 binding.size = size;
1716 binding.buffer_id = BufferId{};
1717 binding.format = format;
1718 }
1719 return binding;
1720}
1721
1722template <class P>
1585std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) { 1723std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) {
1586 u8* const base_pointer = cpu_memory.GetPointer(cpu_addr); 1724 u8* const base_pointer = cpu_memory.GetPointer(cpu_addr);
1587 if (IsRangeGranular(cpu_addr, size) || 1725 if (IsRangeGranular(cpu_addr, size) ||
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index fe91aa452..ddcce5e97 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -155,6 +155,7 @@ struct BufferCacheParams {
155 static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true; 155 static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true;
156 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true; 156 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true;
157 static constexpr bool NEEDS_BIND_STORAGE_INDEX = true; 157 static constexpr bool NEEDS_BIND_STORAGE_INDEX = true;
158 static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = true;
158 static constexpr bool USE_MEMORY_MAPS = false; 159 static constexpr bool USE_MEMORY_MAPS = false;
159}; 160};
160 161
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index ff0f03e99..a8bf84218 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -1016,6 +1016,10 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
1016 default_handle = Handle(info.type); 1016 default_handle = Handle(info.type);
1017} 1017}
1018 1018
1019ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1020 const VideoCommon::ImageViewInfo& view_info)
1021 : VideoCommon::ImageViewBase{info, view_info} {}
1022
1019ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) 1023ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params)
1020 : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} 1024 : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {}
1021 1025
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index cf3b789e3..817b0e650 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -182,6 +182,8 @@ class ImageView : public VideoCommon::ImageViewBase {
182 182
183public: 183public:
184 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 184 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
185 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
186 const VideoCommon::ImageViewInfo& view_info);
185 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); 187 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
186 188
187 [[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept { 189 [[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept {
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index decf0d32c..cff93cc60 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -24,7 +24,8 @@ struct TextureHandle {
24 [[likely]] if (via_header_index) { 24 [[likely]] if (via_header_index) {
25 image = data; 25 image = data;
26 sampler = data; 26 sampler = data;
27 } else { 27 }
28 else {
28 const Tegra::Texture::TextureHandle handle{data}; 29 const Tegra::Texture::TextureHandle handle{data};
29 image = handle.tic_id; 30 image = handle.tic_id;
30 sampler = via_header_index ? image : handle.tsc_id.Value(); 31 sampler = via_header_index ? image : handle.tsc_id.Value();
@@ -90,12 +91,12 @@ public:
90 for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { 91 for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) {
91 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage); 92 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage);
92 } 93 }
94 for ([[maybe_unused]] const auto& desc : info.texture_buffer_descriptors) {
95 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage);
96 }
93 for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { 97 for ([[maybe_unused]] const auto& desc : info.texture_descriptors) {
94 Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); 98 Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage);
95 } 99 }
96 for (const auto& desc : info.texture_buffer_descriptors) {
97 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage);
98 }
99 } 100 }
100 101
101private: 102private:
@@ -156,20 +157,15 @@ inline VideoCommon::ImageViewType CastType(Shader::TextureType type) {
156 return {}; 157 return {};
157} 158}
158 159
159inline void PushImageDescriptors(const Shader::Info& info, const VkSampler* samplers, 160inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
160 const ImageId* image_view_ids, TextureCache& texture_cache, 161 const ImageId*& image_view_ids, TextureCache& texture_cache,
161 VKUpdateDescriptorQueue& update_descriptor_queue, size_t& index) { 162 VKUpdateDescriptorQueue& update_descriptor_queue) {
163 image_view_ids += info.texture_buffer_descriptors.size();
162 for (const auto& desc : info.texture_descriptors) { 164 for (const auto& desc : info.texture_descriptors) {
163 const VkSampler sampler{samplers[index]}; 165 const VkSampler sampler{*(samplers++)};
164 ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; 166 ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
165 const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))}; 167 const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))};
166 update_descriptor_queue.AddSampledImage(vk_image_view, sampler); 168 update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
167 ++index;
168 }
169 for (const auto& desc : info.texture_buffer_descriptors) {
170 ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])};
171 update_descriptor_queue.AddTexelBuffer(image_view.BufferView());
172 ++index;
173 } 169 }
174} 170}
175 171
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 0def1e769..cdda56ab1 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -67,25 +67,50 @@ Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
67 67
68Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 68Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
69 VAddr cpu_addr_, u64 size_bytes_) 69 VAddr cpu_addr_, u64 size_bytes_)
70 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) { 70 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_),
71 buffer = runtime.device.GetLogical().CreateBuffer(VkBufferCreateInfo{ 71 device{&runtime.device},
72 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 72 buffer{device->GetLogical().CreateBuffer({
73 .pNext = nullptr, 73 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
74 .flags = 0, 74 .pNext = nullptr,
75 .size = SizeBytes(), 75 .flags = 0,
76 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | 76 .size = SizeBytes(),
77 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | 77 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
78 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | 78 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
79 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | 79 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
80 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 80 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
81 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 81 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
82 .queueFamilyIndexCount = 0, 82 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
83 .pQueueFamilyIndices = nullptr, 83 .queueFamilyIndexCount = 0,
84 }); 84 .pQueueFamilyIndices = nullptr,
85 })},
86 commit{runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal)} {
85 if (runtime.device.HasDebuggingToolAttached()) { 87 if (runtime.device.HasDebuggingToolAttached()) {
86 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); 88 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
87 } 89 }
88 commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); 90}
91
92VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) {
93 const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) {
94 return offset == view.offset && size == view.size && format == view.format;
95 })};
96 if (it != views.end()) {
97 return *it->handle;
98 }
99 views.push_back({
100 .offset = offset,
101 .size = size,
102 .format = format,
103 .handle = device->GetLogical().CreateBufferView({
104 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
105 .pNext = nullptr,
106 .flags = 0,
107 .buffer = *buffer,
108 .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Buffer, false, format).format,
109 .offset = offset,
110 .range = size,
111 }),
112 });
113 return *views.back().handle;
89} 114}
90 115
91BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, 116BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 3bb81d5b3..ea17406dc 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -9,6 +9,7 @@
9#include "video_core/renderer_vulkan/vk_compute_pass.h" 9#include "video_core/renderer_vulkan/vk_compute_pass.h"
10#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 10#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
11#include "video_core/renderer_vulkan/vk_update_descriptor.h" 11#include "video_core/renderer_vulkan/vk_update_descriptor.h"
12#include "video_core/surface.h"
12#include "video_core/vulkan_common/vulkan_memory_allocator.h" 13#include "video_core/vulkan_common/vulkan_memory_allocator.h"
13#include "video_core/vulkan_common/vulkan_wrapper.h" 14#include "video_core/vulkan_common/vulkan_wrapper.h"
14 15
@@ -26,6 +27,8 @@ public:
26 explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 27 explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
27 VAddr cpu_addr_, u64 size_bytes_); 28 VAddr cpu_addr_, u64 size_bytes_);
28 29
30 [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
31
29 [[nodiscard]] VkBuffer Handle() const noexcept { 32 [[nodiscard]] VkBuffer Handle() const noexcept {
30 return *buffer; 33 return *buffer;
31 } 34 }
@@ -35,8 +38,17 @@ public:
35 } 38 }
36 39
37private: 40private:
41 struct BufferView {
42 u32 offset;
43 u32 size;
44 VideoCore::Surface::PixelFormat format;
45 vk::BufferView handle;
46 };
47
48 const Device* device{};
38 vk::Buffer buffer; 49 vk::Buffer buffer;
39 MemoryCommit commit; 50 MemoryCommit commit;
51 std::vector<BufferView> views;
40}; 52};
41 53
42class BufferCacheRuntime { 54class BufferCacheRuntime {
@@ -87,6 +99,11 @@ public:
87 BindBuffer(buffer, offset, size); 99 BindBuffer(buffer, offset, size);
88 } 100 }
89 101
102 void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
103 VideoCore::Surface::PixelFormat format) {
104 update_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format));
105 }
106
90private: 107private:
91 void BindBuffer(VkBuffer buffer, u32 offset, u32 size) { 108 void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
92 update_descriptor_queue.AddBuffer(buffer, offset, size); 109 update_descriptor_queue.AddBuffer(buffer, offset, size);
@@ -123,6 +140,7 @@ struct BufferCacheParams {
123 static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false; 140 static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false;
124 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false; 141 static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false;
125 static constexpr bool NEEDS_BIND_STORAGE_INDEX = false; 142 static constexpr bool NEEDS_BIND_STORAGE_INDEX = false;
143 static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = false;
126 static constexpr bool USE_MEMORY_MAPS = true; 144 static constexpr bool USE_MEMORY_MAPS = true;
127}; 145};
128 146
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 9922cbd0f..ac47b1f3c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -80,8 +80,6 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
80 desc.is_written); 80 desc.is_written);
81 ++ssbo_index; 81 ++ssbo_index;
82 } 82 }
83 buffer_cache.UpdateComputeBuffers();
84 buffer_cache.BindHostComputeBuffers();
85 83
86 texture_cache.SynchronizeComputeDescriptors(); 84 texture_cache.SynchronizeComputeDescriptors();
87 85
@@ -99,6 +97,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
99 const u32 raw_handle{gpu_memory.Read<u32>(addr)}; 97 const u32 raw_handle{gpu_memory.Read<u32>(addr)};
100 return TextureHandle(raw_handle, via_header_index); 98 return TextureHandle(raw_handle, via_header_index);
101 }}; 99 }};
100 for (const auto& desc : info.texture_buffer_descriptors) {
101 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
102 image_view_indices.push_back(handle.image);
103 }
102 for (const auto& desc : info.texture_descriptors) { 104 for (const auto& desc : info.texture_descriptors) {
103 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 105 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
104 image_view_indices.push_back(handle.image); 106 image_view_indices.push_back(handle.image);
@@ -106,16 +108,26 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
106 Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); 108 Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler);
107 samplers.push_back(sampler->Handle()); 109 samplers.push_back(sampler->Handle());
108 } 110 }
109 for (const auto& desc : info.texture_buffer_descriptors) {
110 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
111 image_view_indices.push_back(handle.image);
112 }
113 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 111 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
114 texture_cache.FillComputeImageViews(indices_span, image_view_ids); 112 texture_cache.FillComputeImageViews(indices_span, image_view_ids);
115 113
116 size_t image_index{}; 114 buffer_cache.UnbindComputeTextureBuffers();
117 PushImageDescriptors(info, samplers.data(), image_view_ids.data(), texture_cache, 115 ImageId* texture_buffer_ids{image_view_ids.data()};
118 update_descriptor_queue, image_index); 116 size_t index{};
117 for (const auto& desc : info.texture_buffer_descriptors) {
118 ASSERT(desc.count == 1);
119 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids);
120 buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(),
121 image_view.format);
122 ++texture_buffer_ids;
123 ++index;
124 }
125 buffer_cache.UpdateComputeBuffers();
126 buffer_cache.BindHostComputeBuffers();
127
128 const VkSampler* samplers_it{samplers.data()};
129 const ImageId* views_it{image_view_ids.data()};
130 PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue);
119 131
120 if (!is_built.load(std::memory_order::relaxed)) { 132 if (!is_built.load(std::memory_order::relaxed)) {
121 // Wait for the pipeline to be built 133 // Wait for the pipeline to be built
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index afdd8b371..893258b4a 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -175,6 +175,10 @@ 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) {
179 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
180 image_view_indices.push_back(handle.image);
181 }
178 for (const auto& desc : info.texture_descriptors) { 182 for (const auto& desc : info.texture_descriptors) {
179 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 183 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
180 image_view_indices.push_back(handle.image); 184 image_view_indices.push_back(handle.image);
@@ -182,24 +186,37 @@ void GraphicsPipeline::Configure(bool is_indexed) {
182 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; 186 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
183 samplers.push_back(sampler->Handle()); 187 samplers.push_back(sampler->Handle());
184 } 188 }
189 }
190 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
191 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
192
193 ImageId* texture_buffer_index{image_view_ids.data()};
194 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
195 const Shader::Info& info{stage_infos[stage]};
196 buffer_cache.UnbindGraphicsTextureBuffers(stage);
197 size_t index{};
185 for (const auto& desc : info.texture_buffer_descriptors) { 198 for (const auto& desc : info.texture_buffer_descriptors) {
186 const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; 199 ASSERT(desc.count == 1);
187 image_view_indices.push_back(handle.image); 200 ImageView& image_view = texture_cache.GetImageView(*texture_buffer_index);
201 buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
202 image_view.BufferSize(), image_view.format);
203 ++index;
204 ++texture_buffer_index;
188 } 205 }
206 texture_buffer_index += info.texture_descriptors.size();
189 } 207 }
190 const std::span indices_span(image_view_indices.data(), image_view_indices.size());
191 buffer_cache.UpdateGraphicsBuffers(is_indexed); 208 buffer_cache.UpdateGraphicsBuffers(is_indexed);
192 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
193 209
194 buffer_cache.BindHostGeometryBuffers(is_indexed); 210 buffer_cache.BindHostGeometryBuffers(is_indexed);
195 211
196 update_descriptor_queue.Acquire(); 212 update_descriptor_queue.Acquire();
197 213
198 size_t index{}; 214 const VkSampler* samplers_it{samplers.data()};
215 const ImageId* views_it{image_view_ids.data()};
199 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 216 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
200 buffer_cache.BindHostStageBuffers(stage); 217 buffer_cache.BindHostStageBuffers(stage);
201 PushImageDescriptors(stage_infos[stage], samplers.data(), image_view_ids.data(), 218 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache,
202 texture_cache, update_descriptor_queue, index); 219 update_descriptor_queue);
203 } 220 }
204 texture_cache.UpdateRenderTargets(false); 221 texture_cache.UpdateRenderTargets(false);
205 scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); 222 scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 1bbc542a1..e42b091c5 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -15,10 +15,10 @@
15#include "video_core/renderer_vulkan/maxwell_to_vk.h" 15#include "video_core/renderer_vulkan/maxwell_to_vk.h"
16#include "video_core/renderer_vulkan/vk_compute_pass.h" 16#include "video_core/renderer_vulkan/vk_compute_pass.h"
17#include "video_core/renderer_vulkan/vk_rasterizer.h" 17#include "video_core/renderer_vulkan/vk_rasterizer.h"
18#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
18#include "video_core/renderer_vulkan/vk_scheduler.h" 19#include "video_core/renderer_vulkan/vk_scheduler.h"
19#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 20#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
20#include "video_core/renderer_vulkan/vk_texture_cache.h" 21#include "video_core/renderer_vulkan/vk_texture_cache.h"
21#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
22#include "video_core/vulkan_common/vulkan_device.h" 22#include "video_core/vulkan_common/vulkan_device.h"
23#include "video_core/vulkan_common/vulkan_memory_allocator.h" 23#include "video_core/vulkan_common/vulkan_memory_allocator.h"
24#include "video_core/vulkan_common/vulkan_wrapper.h" 24#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -162,25 +162,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
162 return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info)); 162 return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info));
163} 163}
164 164
165[[nodiscard]] vk::Buffer MakeBuffer(const Device& device, const ImageInfo& info) {
166 if (info.type != ImageType::Buffer) {
167 return vk::Buffer{};
168 }
169 const size_t bytes_per_block = VideoCore::Surface::BytesPerBlock(info.format);
170 return device.GetLogical().CreateBuffer(VkBufferCreateInfo{
171 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
172 .pNext = nullptr,
173 .flags = 0,
174 .size = info.size.width * bytes_per_block,
175 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
176 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
177 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
178 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
179 .queueFamilyIndexCount = 0,
180 .pQueueFamilyIndices = nullptr,
181 });
182}
183
184[[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { 165[[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) {
185 switch (VideoCore::Surface::GetFormatType(format)) { 166 switch (VideoCore::Surface::GetFormatType(format)) {
186 case VideoCore::Surface::SurfaceType::ColorTexture: 167 case VideoCore::Surface::SurfaceType::ColorTexture:
@@ -813,13 +794,9 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
813Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_, 794Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_,
814 VAddr cpu_addr_) 795 VAddr cpu_addr_)
815 : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler}, 796 : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler},
816 image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)), 797 image(MakeImage(runtime.device, info)),
798 commit(runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal)),
817 aspect_mask(ImageAspectMask(info.format)) { 799 aspect_mask(ImageAspectMask(info.format)) {
818 if (image) {
819 commit = runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal);
820 } else {
821 commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
822 }
823 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { 800 if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
824 if (Settings::values.accelerate_astc.GetValue()) { 801 if (Settings::values.accelerate_astc.GetValue()) {
825 flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; 802 flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
@@ -828,11 +805,7 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
828 } 805 }
829 } 806 }
830 if (runtime.device.HasDebuggingToolAttached()) { 807 if (runtime.device.HasDebuggingToolAttached()) {
831 if (image) { 808 image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
832 image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
833 } else {
834 buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
835 }
836 } 809 }
837 static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ 810 static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
838 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, 811 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
@@ -884,19 +857,6 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
884 }); 857 });
885} 858}
886 859
887void Image::UploadMemory(const StagingBufferRef& map,
888 std::span<const VideoCommon::BufferCopy> copies) {
889 // TODO: Move this to another API
890 scheduler->RequestOutsideRenderPassOperationContext();
891 std::vector vk_copies = TransformBufferCopies(copies, map.offset);
892 const VkBuffer src_buffer = map.buffer;
893 const VkBuffer dst_buffer = *buffer;
894 scheduler->Record([src_buffer, dst_buffer, vk_copies](vk::CommandBuffer cmdbuf) {
895 // TODO: Barriers
896 cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
897 });
898}
899
900void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { 860void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
901 std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); 861 std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
902 scheduler->RequestOutsideRenderPassOperationContext(); 862 scheduler->RequestOutsideRenderPassOperationContext();
@@ -1032,19 +992,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
1032 UNIMPLEMENTED(); 992 UNIMPLEMENTED();
1033 break; 993 break;
1034 case VideoCommon::ImageViewType::Buffer: 994 case VideoCommon::ImageViewType::Buffer:
1035 buffer_view = device->GetLogical().CreateBufferView(VkBufferViewCreateInfo{ 995 UNREACHABLE();
1036 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
1037 .pNext = nullptr,
1038 .flags = 0,
1039 .buffer = image.Buffer(),
1040 .format = format_info.format,
1041 .offset = 0, // TODO: Redesign buffer cache to support this
1042 .range = image.guest_size_bytes,
1043 });
1044 break; 996 break;
1045 } 997 }
1046} 998}
1047 999
1000ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1001 const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
1002 : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
1003 buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
1004
1048ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) 1005ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params)
1049 : VideoCommon::ImageViewBase{params} {} 1006 : VideoCommon::ImageViewBase{params} {}
1050 1007
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 189ee5a68..498e76a1c 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -41,9 +41,9 @@ struct TextureCacheRuntime {
41 41
42 void Finish(); 42 void Finish();
43 43
44 [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); 44 StagingBufferRef UploadStagingBuffer(size_t size);
45 45
46 [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); 46 StagingBufferRef DownloadStagingBuffer(size_t size);
47 47
48 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 48 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
49 const Region2D& dst_region, const Region2D& src_region, 49 const Region2D& dst_region, const Region2D& src_region,
@@ -54,7 +54,7 @@ struct TextureCacheRuntime {
54 54
55 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); 55 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
56 56
57 [[nodiscard]] bool CanAccelerateImageUpload(Image&) const noexcept { 57 bool CanAccelerateImageUpload(Image&) const noexcept {
58 return false; 58 return false;
59 } 59 }
60 60
@@ -92,8 +92,6 @@ public:
92 void UploadMemory(const StagingBufferRef& map, 92 void UploadMemory(const StagingBufferRef& map,
93 std::span<const VideoCommon::BufferImageCopy> copies); 93 std::span<const VideoCommon::BufferImageCopy> copies);
94 94
95 void UploadMemory(const StagingBufferRef& map, std::span<const VideoCommon::BufferCopy> copies);
96
97 void DownloadMemory(const StagingBufferRef& map, 95 void DownloadMemory(const StagingBufferRef& map,
98 std::span<const VideoCommon::BufferImageCopy> copies); 96 std::span<const VideoCommon::BufferImageCopy> copies);
99 97
@@ -101,10 +99,6 @@ public:
101 return *image; 99 return *image;
102 } 100 }
103 101
104 [[nodiscard]] VkBuffer Buffer() const noexcept {
105 return *buffer;
106 }
107
108 [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept { 102 [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
109 return aspect_mask; 103 return aspect_mask;
110 } 104 }
@@ -121,7 +115,6 @@ public:
121private: 115private:
122 VKScheduler* scheduler; 116 VKScheduler* scheduler;
123 vk::Image image; 117 vk::Image image;
124 vk::Buffer buffer;
125 MemoryCommit commit; 118 MemoryCommit commit;
126 vk::ImageView image_view; 119 vk::ImageView image_view;
127 std::vector<vk::ImageView> storage_image_views; 120 std::vector<vk::ImageView> storage_image_views;
@@ -132,6 +125,8 @@ private:
132class ImageView : public VideoCommon::ImageViewBase { 125class ImageView : public VideoCommon::ImageViewBase {
133public: 126public:
134 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 127 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
128 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
129 const VideoCommon::ImageViewInfo&, GPUVAddr);
135 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); 130 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
136 131
137 [[nodiscard]] VkImageView DepthView(); 132 [[nodiscard]] VkImageView DepthView();
@@ -142,10 +137,6 @@ public:
142 return *image_views[static_cast<size_t>(query_type)]; 137 return *image_views[static_cast<size_t>(query_type)];
143 } 138 }
144 139
145 [[nodiscard]] VkBufferView BufferView() const noexcept {
146 return *buffer_view;
147 }
148
149 [[nodiscard]] VkImage ImageHandle() const noexcept { 140 [[nodiscard]] VkImage ImageHandle() const noexcept {
150 return image_handle; 141 return image_handle;
151 } 142 }
@@ -162,6 +153,14 @@ public:
162 return samples; 153 return samples;
163 } 154 }
164 155
156 [[nodiscard]] GPUVAddr GpuAddr() const noexcept {
157 return gpu_addr;
158 }
159
160 [[nodiscard]] u32 BufferSize() const noexcept {
161 return buffer_size;
162 }
163
165private: 164private:
166 [[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask); 165 [[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask);
167 166
@@ -169,11 +168,12 @@ private:
169 std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views; 168 std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views;
170 vk::ImageView depth_view; 169 vk::ImageView depth_view;
171 vk::ImageView stencil_view; 170 vk::ImageView stencil_view;
172 vk::BufferView buffer_view;
173 VkImage image_handle = VK_NULL_HANDLE; 171 VkImage image_handle = VK_NULL_HANDLE;
174 VkImageView render_target = VK_NULL_HANDLE; 172 VkImageView render_target = VK_NULL_HANDLE;
175 PixelFormat image_format = PixelFormat::Invalid; 173 PixelFormat image_format = PixelFormat::Invalid;
176 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; 174 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
175 GPUVAddr gpu_addr = 0;
176 u32 buffer_size = 0;
177}; 177};
178 178
179class ImageAlloc : public VideoCommon::ImageAllocBase {}; 179class ImageAlloc : public VideoCommon::ImageAllocBase {};
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index e8d632f9e..450becbeb 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -36,6 +36,15 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i
36 } 36 }
37} 37}
38 38
39ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info)
40 : format{info.format}, type{ImageViewType::Buffer}, size{
41 .width = info.size.width,
42 .height = 1,
43 .depth = 1,
44 } {
45 ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer");
46}
47
39ImageViewBase::ImageViewBase(const NullImageParams&) {} 48ImageViewBase::ImageViewBase(const NullImageParams&) {}
40 49
41} // namespace VideoCommon 50} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/image_view_base.h b/src/video_core/texture_cache/image_view_base.h
index 73954167e..903f715c5 100644
--- a/src/video_core/texture_cache/image_view_base.h
+++ b/src/video_core/texture_cache/image_view_base.h
@@ -27,6 +27,7 @@ DECLARE_ENUM_FLAG_OPERATORS(ImageViewFlagBits)
27struct ImageViewBase { 27struct ImageViewBase {
28 explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, 28 explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info,
29 ImageId image_id); 29 ImageId image_id);
30 explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info);
30 explicit ImageViewBase(const NullImageParams&); 31 explicit ImageViewBase(const NullImageParams&);
31 32
32 [[nodiscard]] bool IsBuffer() const noexcept { 33 [[nodiscard]] bool IsBuffer() const noexcept {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 85ce06d56..5e8d99482 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -968,9 +968,6 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging)
968 auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data); 968 auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data);
969 ConvertImage(unswizzled_data, image.info, mapped_span, copies); 969 ConvertImage(unswizzled_data, image.info, mapped_span, copies);
970 image.UploadMemory(staging, copies); 970 image.UploadMemory(staging, copies);
971 } else if (image.info.type == ImageType::Buffer) {
972 const std::array copies{UploadBufferCopy(gpu_memory, gpu_addr, image, mapped_span)};
973 image.UploadMemory(staging, copies);
974 } else { 971 } else {
975 const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span); 972 const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span);
976 image.UploadMemory(staging, copies); 973 image.UploadMemory(staging, copies);
@@ -993,7 +990,12 @@ ImageViewId TextureCache<P>::FindImageView(const TICEntry& config) {
993template <class P> 990template <class P>
994ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) { 991ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) {
995 const ImageInfo info(config); 992 const ImageInfo info(config);
996 const GPUVAddr image_gpu_addr = config.Address() - config.BaseLayer() * info.layer_stride; 993 if (info.type == ImageType::Buffer) {
994 const ImageViewInfo view_info(config, 0);
995 return slot_image_views.insert(runtime, info, view_info, config.Address());
996 }
997 const u32 layer_offset = config.BaseLayer() * info.layer_stride;
998 const GPUVAddr image_gpu_addr = config.Address() - layer_offset;
997 const ImageId image_id = FindOrInsertImage(info, image_gpu_addr); 999 const ImageId image_id = FindOrInsertImage(info, image_gpu_addr);
998 if (!image_id) { 1000 if (!image_id) {
999 return NULL_IMAGE_VIEW_ID; 1001 return NULL_IMAGE_VIEW_ID;
@@ -1801,6 +1803,9 @@ void TextureCache<P>::PrepareImageView(ImageViewId image_view_id, bool is_modifi
1801 return; 1803 return;
1802 } 1804 }
1803 const ImageViewBase& image_view = slot_image_views[image_view_id]; 1805 const ImageViewBase& image_view = slot_image_views[image_view_id];
1806 if (image_view.IsBuffer()) {
1807 return;
1808 }
1804 PrepareImage(image_view.image_id, is_modification, invalidate); 1809 PrepareImage(image_view.image_id, is_modification, invalidate);
1805} 1810}
1806 1811