summaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/buffer_cache')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h138
1 files changed, 138 insertions, 0 deletions
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) ||