summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-04-04 02:54:55 -0300
committerGravatar ReinUsesLisp2020-04-16 02:33:34 -0300
commit090fd3fefab9ef251e6e5bf4011280a657340f2a (patch)
treeacfdc14d7e948ae296859d3d112f356f3279680c /src
parentMerge pull request #3636 from ReinUsesLisp/drop-vk-hpp (diff)
downloadyuzu-090fd3fefab9ef251e6e5bf4011280a657340f2a.tar.gz
yuzu-090fd3fefab9ef251e6e5bf4011280a657340f2a.tar.xz
yuzu-090fd3fefab9ef251e6e5bf4011280a657340f2a.zip
buffer_cache: Return handles instead of pointer to handles
The original idea of returning pointers is that handles can be moved. The problem is that the implementation didn't take that in mind and made everything harder to work with. This commit drops pointer to handles and returns the handles themselves. While it is still true that handles can be invalidated, this way we get an old handle instead of a dangling pointer. This problem can be solved in the future with sparse buffers.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h47
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h12
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp39
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/utils.cpp62
-rw-r--r--src/video_core/renderer_opengl/utils.h43
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp16
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp30
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h16
14 files changed, 90 insertions, 228 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index b57c0d4d4..83e7a1cde 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -29,10 +29,10 @@ namespace VideoCommon {
29 29
30using MapInterval = std::shared_ptr<MapIntervalBase>; 30using MapInterval = std::shared_ptr<MapIntervalBase>;
31 31
32template <typename TBuffer, typename TBufferType, typename StreamBuffer> 32template <typename OwnerBuffer, typename BufferType, typename StreamBuffer>
33class BufferCache { 33class BufferCache {
34public: 34public:
35 using BufferInfo = std::pair<const TBufferType*, u64>; 35 using BufferInfo = std::pair<BufferType, u64>;
36 36
37 BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, 37 BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4,
38 bool is_written = false, bool use_fast_cbuf = false) { 38 bool is_written = false, bool use_fast_cbuf = false) {
@@ -89,9 +89,7 @@ public:
89 } 89 }
90 } 90 }
91 91
92 const u64 offset = static_cast<u64>(block->GetOffset(cpu_addr)); 92 return {ToHandle(block), static_cast<u64>(block->GetOffset(cpu_addr))};
93
94 return {ToHandle(block), offset};
95 } 93 }
96 94
97 /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. 95 /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset.
@@ -156,7 +154,7 @@ public:
156 } 154 }
157 } 155 }
158 156
159 virtual const TBufferType* GetEmptyBuffer(std::size_t size) = 0; 157 virtual BufferType GetEmptyBuffer(std::size_t size) = 0;
160 158
161protected: 159protected:
162 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 160 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
@@ -166,19 +164,19 @@ protected:
166 164
167 ~BufferCache() = default; 165 ~BufferCache() = default;
168 166
169 virtual const TBufferType* ToHandle(const TBuffer& storage) = 0; 167 virtual BufferType ToHandle(const OwnerBuffer& storage) = 0;
170 168
171 virtual void WriteBarrier() = 0; 169 virtual void WriteBarrier() = 0;
172 170
173 virtual TBuffer CreateBlock(VAddr cpu_addr, std::size_t size) = 0; 171 virtual OwnerBuffer CreateBlock(VAddr cpu_addr, std::size_t size) = 0;
174 172
175 virtual void UploadBlockData(const TBuffer& buffer, std::size_t offset, std::size_t size, 173 virtual void UploadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size,
176 const u8* data) = 0; 174 const u8* data) = 0;
177 175
178 virtual void DownloadBlockData(const TBuffer& buffer, std::size_t offset, std::size_t size, 176 virtual void DownloadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size,
179 u8* data) = 0; 177 u8* data) = 0;
180 178
181 virtual void CopyBlock(const TBuffer& src, const TBuffer& dst, std::size_t src_offset, 179 virtual void CopyBlock(const OwnerBuffer& src, const OwnerBuffer& dst, std::size_t src_offset,
182 std::size_t dst_offset, std::size_t size) = 0; 180 std::size_t dst_offset, std::size_t size) = 0;
183 181
184 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { 182 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
@@ -221,9 +219,8 @@ private:
221 return std::make_shared<MapIntervalBase>(start, end, gpu_addr); 219 return std::make_shared<MapIntervalBase>(start, end, gpu_addr);
222 } 220 }
223 221
224 MapInterval MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const VAddr cpu_addr, 222 MapInterval MapAddress(const OwnerBuffer& block, const GPUVAddr gpu_addr, const VAddr cpu_addr,
225 const std::size_t size) { 223 const std::size_t size) {
226
227 std::vector<MapInterval> overlaps = GetMapsInRange(cpu_addr, size); 224 std::vector<MapInterval> overlaps = GetMapsInRange(cpu_addr, size);
228 if (overlaps.empty()) { 225 if (overlaps.empty()) {
229 auto& memory_manager = system.GPU().MemoryManager(); 226 auto& memory_manager = system.GPU().MemoryManager();
@@ -272,7 +269,7 @@ private:
272 return new_map; 269 return new_map;
273 } 270 }
274 271
275 void UpdateBlock(const TBuffer& block, VAddr start, VAddr end, 272 void UpdateBlock(const OwnerBuffer& block, VAddr start, VAddr end,
276 std::vector<MapInterval>& overlaps) { 273 std::vector<MapInterval>& overlaps) {
277 const IntervalType base_interval{start, end}; 274 const IntervalType base_interval{start, end};
278 IntervalSet interval_set{}; 275 IntervalSet interval_set{};
@@ -313,7 +310,7 @@ private:
313 310
314 void FlushMap(MapInterval map) { 311 void FlushMap(MapInterval map) {
315 std::size_t size = map->GetEnd() - map->GetStart(); 312 std::size_t size = map->GetEnd() - map->GetStart();
316 TBuffer block = blocks[map->GetStart() >> block_page_bits]; 313 OwnerBuffer block = blocks[map->GetStart() >> block_page_bits];
317 staging_buffer.resize(size); 314 staging_buffer.resize(size);
318 DownloadBlockData(block, block->GetOffset(map->GetStart()), size, staging_buffer.data()); 315 DownloadBlockData(block, block->GetOffset(map->GetStart()), size, staging_buffer.data());
319 system.Memory().WriteBlockUnsafe(map->GetStart(), staging_buffer.data(), size); 316 system.Memory().WriteBlockUnsafe(map->GetStart(), staging_buffer.data(), size);
@@ -328,7 +325,7 @@ private:
328 325
329 buffer_ptr += size; 326 buffer_ptr += size;
330 buffer_offset += size; 327 buffer_offset += size;
331 return {&stream_buffer_handle, uploaded_offset}; 328 return {stream_buffer_handle, uploaded_offset};
332 } 329 }
333 330
334 void AlignBuffer(std::size_t alignment) { 331 void AlignBuffer(std::size_t alignment) {
@@ -338,11 +335,11 @@ private:
338 buffer_offset = offset_aligned; 335 buffer_offset = offset_aligned;
339 } 336 }
340 337
341 TBuffer EnlargeBlock(TBuffer buffer) { 338 OwnerBuffer EnlargeBlock(OwnerBuffer buffer) {
342 const std::size_t old_size = buffer->GetSize(); 339 const std::size_t old_size = buffer->GetSize();
343 const std::size_t new_size = old_size + block_page_size; 340 const std::size_t new_size = old_size + block_page_size;
344 const VAddr cpu_addr = buffer->GetCpuAddr(); 341 const VAddr cpu_addr = buffer->GetCpuAddr();
345 TBuffer new_buffer = CreateBlock(cpu_addr, new_size); 342 OwnerBuffer new_buffer = CreateBlock(cpu_addr, new_size);
346 CopyBlock(buffer, new_buffer, 0, 0, old_size); 343 CopyBlock(buffer, new_buffer, 0, 0, old_size);
347 buffer->SetEpoch(epoch); 344 buffer->SetEpoch(epoch);
348 pending_destruction.push_back(buffer); 345 pending_destruction.push_back(buffer);
@@ -356,14 +353,14 @@ private:
356 return new_buffer; 353 return new_buffer;
357 } 354 }
358 355
359 TBuffer MergeBlocks(TBuffer first, TBuffer second) { 356 OwnerBuffer MergeBlocks(OwnerBuffer first, OwnerBuffer second) {
360 const std::size_t size_1 = first->GetSize(); 357 const std::size_t size_1 = first->GetSize();
361 const std::size_t size_2 = second->GetSize(); 358 const std::size_t size_2 = second->GetSize();
362 const VAddr first_addr = first->GetCpuAddr(); 359 const VAddr first_addr = first->GetCpuAddr();
363 const VAddr second_addr = second->GetCpuAddr(); 360 const VAddr second_addr = second->GetCpuAddr();
364 const VAddr new_addr = std::min(first_addr, second_addr); 361 const VAddr new_addr = std::min(first_addr, second_addr);
365 const std::size_t new_size = size_1 + size_2; 362 const std::size_t new_size = size_1 + size_2;
366 TBuffer new_buffer = CreateBlock(new_addr, new_size); 363 OwnerBuffer new_buffer = CreateBlock(new_addr, new_size);
367 CopyBlock(first, new_buffer, 0, new_buffer->GetOffset(first_addr), size_1); 364 CopyBlock(first, new_buffer, 0, new_buffer->GetOffset(first_addr), size_1);
368 CopyBlock(second, new_buffer, 0, new_buffer->GetOffset(second_addr), size_2); 365 CopyBlock(second, new_buffer, 0, new_buffer->GetOffset(second_addr), size_2);
369 first->SetEpoch(epoch); 366 first->SetEpoch(epoch);
@@ -380,8 +377,8 @@ private:
380 return new_buffer; 377 return new_buffer;
381 } 378 }
382 379
383 TBuffer GetBlock(const VAddr cpu_addr, const std::size_t size) { 380 OwnerBuffer GetBlock(const VAddr cpu_addr, const std::size_t size) {
384 TBuffer found{}; 381 OwnerBuffer found;
385 const VAddr cpu_addr_end = cpu_addr + size - 1; 382 const VAddr cpu_addr_end = cpu_addr + size - 1;
386 u64 page_start = cpu_addr >> block_page_bits; 383 u64 page_start = cpu_addr >> block_page_bits;
387 const u64 page_end = cpu_addr_end >> block_page_bits; 384 const u64 page_end = cpu_addr_end >> block_page_bits;
@@ -457,7 +454,7 @@ private:
457 Core::System& system; 454 Core::System& system;
458 455
459 std::unique_ptr<StreamBuffer> stream_buffer; 456 std::unique_ptr<StreamBuffer> stream_buffer;
460 TBufferType stream_buffer_handle{}; 457 BufferType stream_buffer_handle{};
461 458
462 bool invalidated = false; 459 bool invalidated = false;
463 460
@@ -475,9 +472,9 @@ private:
475 472
476 static constexpr u64 block_page_bits = 21; 473 static constexpr u64 block_page_bits = 21;
477 static constexpr u64 block_page_size = 1ULL << block_page_bits; 474 static constexpr u64 block_page_size = 1ULL << block_page_bits;
478 std::unordered_map<u64, TBuffer> blocks; 475 std::unordered_map<u64, OwnerBuffer> blocks;
479 476
480 std::list<TBuffer> pending_destruction; 477 std::list<OwnerBuffer> pending_destruction;
481 u64 epoch = 0; 478 u64 epoch = 0;
482 u64 modified_ticks = 0; 479 u64 modified_ticks = 0;
483 480
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 4eb37a96c..cb5792407 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -55,33 +55,31 @@ void OGLBufferCache::WriteBarrier() {
55 glMemoryBarrier(GL_ALL_BARRIER_BITS); 55 glMemoryBarrier(GL_ALL_BARRIER_BITS);
56} 56}
57 57
58const GLuint* OGLBufferCache::ToHandle(const Buffer& buffer) { 58GLuint OGLBufferCache::ToHandle(const Buffer& buffer) {
59 return buffer->GetHandle(); 59 return buffer->GetHandle();
60} 60}
61 61
62const GLuint* OGLBufferCache::GetEmptyBuffer(std::size_t) { 62GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) {
63 static const GLuint null_buffer = 0; 63 return 0;
64 return &null_buffer;
65} 64}
66 65
67void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 66void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
68 const u8* data) { 67 const u8* data) {
69 glNamedBufferSubData(*buffer->GetHandle(), static_cast<GLintptr>(offset), 68 glNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset),
70 static_cast<GLsizeiptr>(size), data); 69 static_cast<GLsizeiptr>(size), data);
71} 70}
72 71
73void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 72void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
74 u8* data) { 73 u8* data) {
75 MICROPROFILE_SCOPE(OpenGL_Buffer_Download); 74 MICROPROFILE_SCOPE(OpenGL_Buffer_Download);
76 glGetNamedBufferSubData(*buffer->GetHandle(), static_cast<GLintptr>(offset), 75 glGetNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset),
77 static_cast<GLsizeiptr>(size), data); 76 static_cast<GLsizeiptr>(size), data);
78} 77}
79 78
80void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, 79void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
81 std::size_t dst_offset, std::size_t size) { 80 std::size_t dst_offset, std::size_t size) {
82 glCopyNamedBufferSubData(*src->GetHandle(), *dst->GetHandle(), 81 glCopyNamedBufferSubData(src->GetHandle(), dst->GetHandle(), static_cast<GLintptr>(src_offset),
83 static_cast<GLintptr>(src_offset), static_cast<GLintptr>(dst_offset), 82 static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size));
84 static_cast<GLsizeiptr>(size));
85} 83}
86 84
87OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, 85OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
@@ -89,7 +87,7 @@ OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_poi
89 DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); 87 DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));
90 const GLuint& cbuf = cbufs[cbuf_cursor++]; 88 const GLuint& cbuf = cbufs[cbuf_cursor++];
91 glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); 89 glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer);
92 return {&cbuf, 0}; 90 return {cbuf, 0};
93} 91}
94 92
95} // namespace OpenGL 93} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index d94a11252..a74817857 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -34,12 +34,12 @@ public:
34 explicit CachedBufferBlock(VAddr cpu_addr, const std::size_t size); 34 explicit CachedBufferBlock(VAddr cpu_addr, const std::size_t size);
35 ~CachedBufferBlock(); 35 ~CachedBufferBlock();
36 36
37 const GLuint* GetHandle() const { 37 GLuint GetHandle() const {
38 return &gl_buffer.handle; 38 return gl_buffer.handle;
39 } 39 }
40 40
41private: 41private:
42 OGLBuffer gl_buffer{}; 42 OGLBuffer gl_buffer;
43}; 43};
44 44
45class OGLBufferCache final : public GenericBufferCache { 45class OGLBufferCache final : public GenericBufferCache {
@@ -48,7 +48,7 @@ public:
48 const Device& device, std::size_t stream_size); 48 const Device& device, std::size_t stream_size);
49 ~OGLBufferCache(); 49 ~OGLBufferCache();
50 50
51 const GLuint* GetEmptyBuffer(std::size_t) override; 51 GLuint GetEmptyBuffer(std::size_t) override;
52 52
53 void Acquire() noexcept { 53 void Acquire() noexcept {
54 cbuf_cursor = 0; 54 cbuf_cursor = 0;
@@ -57,9 +57,9 @@ public:
57protected: 57protected:
58 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override; 58 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
59 59
60 void WriteBarrier() override; 60 GLuint ToHandle(const Buffer& buffer) override;
61 61
62 const GLuint* ToHandle(const Buffer& buffer) override; 62 void WriteBarrier() override;
63 63
64 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 64 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
65 const u8* data) override; 65 const u8* data) override;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index f31d960c7..91abeb9d7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -188,10 +188,8 @@ void RasterizerOpenGL::SetupVertexBuffer() {
188 ASSERT(end > start); 188 ASSERT(end > start);
189 const u64 size = end - start + 1; 189 const u64 size = end - start + 1;
190 const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); 190 const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size);
191 191 glBindVertexBuffer(static_cast<GLuint>(index), vertex_buffer, vertex_buffer_offset,
192 // Bind the vertex array to the buffer at the current offset. 192 vertex_array.stride);
193 vertex_array_pushbuffer.SetVertexBuffer(static_cast<GLuint>(index), vertex_buffer,
194 vertex_buffer_offset, vertex_array.stride);
195 } 193 }
196} 194}
197 195
@@ -222,7 +220,7 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() {
222 const auto& regs = system.GPU().Maxwell3D().regs; 220 const auto& regs = system.GPU().Maxwell3D().regs;
223 const std::size_t size = CalculateIndexBufferSize(); 221 const std::size_t size = CalculateIndexBufferSize();
224 const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); 222 const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size);
225 vertex_array_pushbuffer.SetIndexBuffer(buffer); 223 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
226 return offset; 224 return offset;
227} 225}
228 226
@@ -524,7 +522,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
524 522
525 // Prepare vertex array format. 523 // Prepare vertex array format.
526 SetupVertexFormat(); 524 SetupVertexFormat();
527 vertex_array_pushbuffer.Setup();
528 525
529 // Upload vertex and index data. 526 // Upload vertex and index data.
530 SetupVertexBuffer(); 527 SetupVertexBuffer();
@@ -534,17 +531,13 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
534 index_buffer_offset = SetupIndexBuffer(); 531 index_buffer_offset = SetupIndexBuffer();
535 } 532 }
536 533
537 // Prepare packed bindings.
538 bind_ubo_pushbuffer.Setup();
539 bind_ssbo_pushbuffer.Setup();
540
541 // Setup emulation uniform buffer. 534 // Setup emulation uniform buffer.
542 GLShader::MaxwellUniformData ubo; 535 GLShader::MaxwellUniformData ubo;
543 ubo.SetFromRegs(gpu); 536 ubo.SetFromRegs(gpu);
544 const auto [buffer, offset] = 537 const auto [buffer, offset] =
545 buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); 538 buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
546 bind_ubo_pushbuffer.Push(EmulationUniformBlockBinding, buffer, offset, 539 glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, buffer, offset,
547 static_cast<GLsizeiptr>(sizeof(ubo))); 540 static_cast<GLsizeiptr>(sizeof(ubo)));
548 541
549 // Setup shaders and their used resources. 542 // Setup shaders and their used resources.
550 texture_cache.GuardSamplers(true); 543 texture_cache.GuardSamplers(true);
@@ -557,11 +550,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
557 // Signal the buffer cache that we are not going to upload more things. 550 // Signal the buffer cache that we are not going to upload more things.
558 buffer_cache.Unmap(); 551 buffer_cache.Unmap();
559 552
560 // Now that we are no longer uploading data, we can safely bind the buffers to OpenGL.
561 vertex_array_pushbuffer.Bind();
562 bind_ubo_pushbuffer.Bind();
563 bind_ssbo_pushbuffer.Bind();
564
565 program_manager.BindGraphicsPipeline(); 553 program_manager.BindGraphicsPipeline();
566 554
567 if (texture_cache.TextureBarrier()) { 555 if (texture_cache.TextureBarrier()) {
@@ -630,17 +618,11 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
630 (Maxwell::MaxConstBufferSize + device.GetUniformBufferAlignment()); 618 (Maxwell::MaxConstBufferSize + device.GetUniformBufferAlignment());
631 buffer_cache.Map(buffer_size); 619 buffer_cache.Map(buffer_size);
632 620
633 bind_ubo_pushbuffer.Setup();
634 bind_ssbo_pushbuffer.Setup();
635
636 SetupComputeConstBuffers(kernel); 621 SetupComputeConstBuffers(kernel);
637 SetupComputeGlobalMemory(kernel); 622 SetupComputeGlobalMemory(kernel);
638 623
639 buffer_cache.Unmap(); 624 buffer_cache.Unmap();
640 625
641 bind_ubo_pushbuffer.Bind();
642 bind_ssbo_pushbuffer.Bind();
643
644 const auto& launch_desc = system.GPU().KeplerCompute().launch_description; 626 const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
645 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); 627 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z);
646 ++num_queued_commands; 628 ++num_queued_commands;
@@ -771,8 +753,8 @@ void RasterizerOpenGL::SetupConstBuffer(u32 binding, const Tegra::Engines::Const
771 const ConstBufferEntry& entry) { 753 const ConstBufferEntry& entry) {
772 if (!buffer.enabled) { 754 if (!buffer.enabled) {
773 // Set values to zero to unbind buffers 755 // Set values to zero to unbind buffers
774 bind_ubo_pushbuffer.Push(binding, buffer_cache.GetEmptyBuffer(sizeof(float)), 0, 756 glBindBufferRange(GL_UNIFORM_BUFFER, binding, buffer_cache.GetEmptyBuffer(sizeof(float)), 0,
775 sizeof(float)); 757 sizeof(float));
776 return; 758 return;
777 } 759 }
778 760
@@ -783,7 +765,7 @@ void RasterizerOpenGL::SetupConstBuffer(u32 binding, const Tegra::Engines::Const
783 const auto alignment = device.GetUniformBufferAlignment(); 765 const auto alignment = device.GetUniformBufferAlignment();
784 const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false, 766 const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false,
785 device.HasFastBufferSubData()); 767 device.HasFastBufferSubData());
786 bind_ubo_pushbuffer.Push(binding, cbuf, offset, size); 768 glBindBufferRange(GL_UNIFORM_BUFFER, binding, cbuf, offset, size);
787} 769}
788 770
789void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shader& shader) { 771void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shader& shader) {
@@ -819,7 +801,8 @@ void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& e
819 const auto alignment{device.GetShaderStorageBufferAlignment()}; 801 const auto alignment{device.GetShaderStorageBufferAlignment()};
820 const auto [ssbo, buffer_offset] = 802 const auto [ssbo, buffer_offset] =
821 buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.IsWritten()); 803 buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.IsWritten());
822 bind_ssbo_pushbuffer.Push(binding, ssbo, buffer_offset, static_cast<GLsizeiptr>(size)); 804 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset,
805 static_cast<GLsizeiptr>(size));
823} 806}
824 807
825void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& shader) { 808void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& shader) {
@@ -1432,7 +1415,7 @@ void RasterizerOpenGL::EndTransformFeedback() {
1432 const GPUVAddr gpu_addr = binding.Address(); 1415 const GPUVAddr gpu_addr = binding.Address();
1433 const std::size_t size = binding.buffer_size; 1416 const std::size_t size = binding.buffer_size;
1434 const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); 1417 const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true);
1435 glCopyNamedBufferSubData(handle, *dest_buffer, 0, offset, static_cast<GLsizeiptr>(size)); 1418 glCopyNamedBufferSubData(handle, dest_buffer, 0, offset, static_cast<GLsizeiptr>(size));
1436 } 1419 }
1437} 1420}
1438 1421
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 435da4425..caea174d2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -231,9 +231,7 @@ private:
231 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; 231 static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
232 OGLBufferCache buffer_cache; 232 OGLBufferCache buffer_cache;
233 233
234 VertexArrayPushBuffer vertex_array_pushbuffer{state_tracker}; 234 GLint vertex_binding = 0;
235 BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
236 BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
237 235
238 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> 236 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
239 transform_feedback_buffers; 237 transform_feedback_buffers;
diff --git a/src/video_core/renderer_opengl/utils.cpp b/src/video_core/renderer_opengl/utils.cpp
index b751086fa..6d7bb16b2 100644
--- a/src/video_core/renderer_opengl/utils.cpp
+++ b/src/video_core/renderer_opengl/utils.cpp
@@ -14,68 +14,6 @@
14 14
15namespace OpenGL { 15namespace OpenGL {
16 16
17struct VertexArrayPushBuffer::Entry {
18 GLuint binding_index{};
19 const GLuint* buffer{};
20 GLintptr offset{};
21 GLsizei stride{};
22};
23
24VertexArrayPushBuffer::VertexArrayPushBuffer(StateTracker& state_tracker)
25 : state_tracker{state_tracker} {}
26
27VertexArrayPushBuffer::~VertexArrayPushBuffer() = default;
28
29void VertexArrayPushBuffer::Setup() {
30 index_buffer = nullptr;
31 vertex_buffers.clear();
32}
33
34void VertexArrayPushBuffer::SetIndexBuffer(const GLuint* buffer) {
35 index_buffer = buffer;
36}
37
38void VertexArrayPushBuffer::SetVertexBuffer(GLuint binding_index, const GLuint* buffer,
39 GLintptr offset, GLsizei stride) {
40 vertex_buffers.push_back(Entry{binding_index, buffer, offset, stride});
41}
42
43void VertexArrayPushBuffer::Bind() {
44 if (index_buffer) {
45 state_tracker.BindIndexBuffer(*index_buffer);
46 }
47
48 for (const auto& entry : vertex_buffers) {
49 glBindVertexBuffer(entry.binding_index, *entry.buffer, entry.offset, entry.stride);
50 }
51}
52
53struct BindBuffersRangePushBuffer::Entry {
54 GLuint binding;
55 const GLuint* buffer;
56 GLintptr offset;
57 GLsizeiptr size;
58};
59
60BindBuffersRangePushBuffer::BindBuffersRangePushBuffer(GLenum target) : target{target} {}
61
62BindBuffersRangePushBuffer::~BindBuffersRangePushBuffer() = default;
63
64void BindBuffersRangePushBuffer::Setup() {
65 entries.clear();
66}
67
68void BindBuffersRangePushBuffer::Push(GLuint binding, const GLuint* buffer, GLintptr offset,
69 GLsizeiptr size) {
70 entries.push_back(Entry{binding, buffer, offset, size});
71}
72
73void BindBuffersRangePushBuffer::Bind() {
74 for (const Entry& entry : entries) {
75 glBindBufferRange(target, entry.binding, *entry.buffer, entry.offset, entry.size);
76 }
77}
78
79void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info) { 17void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info) {
80 if (!GLAD_GL_KHR_debug) { 18 if (!GLAD_GL_KHR_debug) {
81 // We don't need to throw an error as this is just for debugging 19 // We don't need to throw an error as this is just for debugging
diff --git a/src/video_core/renderer_opengl/utils.h b/src/video_core/renderer_opengl/utils.h
index 47ee3177b..9c09ee12c 100644
--- a/src/video_core/renderer_opengl/utils.h
+++ b/src/video_core/renderer_opengl/utils.h
@@ -11,49 +11,6 @@
11 11
12namespace OpenGL { 12namespace OpenGL {
13 13
14class StateTracker;
15
16class VertexArrayPushBuffer final {
17public:
18 explicit VertexArrayPushBuffer(StateTracker& state_tracker);
19 ~VertexArrayPushBuffer();
20
21 void Setup();
22
23 void SetIndexBuffer(const GLuint* buffer);
24
25 void SetVertexBuffer(GLuint binding_index, const GLuint* buffer, GLintptr offset,
26 GLsizei stride);
27
28 void Bind();
29
30private:
31 struct Entry;
32
33 StateTracker& state_tracker;
34
35 const GLuint* index_buffer{};
36 std::vector<Entry> vertex_buffers;
37};
38
39class BindBuffersRangePushBuffer final {
40public:
41 explicit BindBuffersRangePushBuffer(GLenum target);
42 ~BindBuffersRangePushBuffer();
43
44 void Setup();
45
46 void Push(GLuint binding, const GLuint* buffer, GLintptr offset, GLsizeiptr size);
47
48 void Bind();
49
50private:
51 struct Entry;
52
53 GLenum target;
54 std::vector<Entry> entries;
55};
56
57void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info = {}); 14void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info = {});
58 15
59} // namespace OpenGL 16} // namespace OpenGL
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 0d167afbd..81e1de2be 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -74,18 +74,18 @@ Buffer VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) {
74 return std::make_shared<CachedBufferBlock>(device, memory_manager, cpu_addr, size); 74 return std::make_shared<CachedBufferBlock>(device, memory_manager, cpu_addr, size);
75} 75}
76 76
77const VkBuffer* VKBufferCache::ToHandle(const Buffer& buffer) { 77VkBuffer VKBufferCache::ToHandle(const Buffer& buffer) {
78 return buffer->GetHandle(); 78 return buffer->GetHandle();
79} 79}
80 80
81const VkBuffer* VKBufferCache::GetEmptyBuffer(std::size_t size) { 81VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) {
82 size = std::max(size, std::size_t(4)); 82 size = std::max(size, std::size_t(4));
83 const auto& empty = staging_pool.GetUnusedBuffer(size, false); 83 const auto& empty = staging_pool.GetUnusedBuffer(size, false);
84 scheduler.RequestOutsideRenderPassOperationContext(); 84 scheduler.RequestOutsideRenderPassOperationContext();
85 scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { 85 scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) {
86 cmdbuf.FillBuffer(buffer, 0, size, 0); 86 cmdbuf.FillBuffer(buffer, 0, size, 0);
87 }); 87 });
88 return empty.handle.address(); 88 return *empty.handle;
89} 89}
90 90
91void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 91void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
@@ -94,7 +94,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st
94 std::memcpy(staging.commit->Map(size), data, size); 94 std::memcpy(staging.commit->Map(size), data, size);
95 95
96 scheduler.RequestOutsideRenderPassOperationContext(); 96 scheduler.RequestOutsideRenderPassOperationContext();
97 scheduler.Record([staging = *staging.handle, buffer = *buffer->GetHandle(), offset, 97 scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset,
98 size](vk::CommandBuffer cmdbuf) { 98 size](vk::CommandBuffer cmdbuf) {
99 cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); 99 cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size});
100 100
@@ -117,7 +117,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset,
117 u8* data) { 117 u8* data) {
118 const auto& staging = staging_pool.GetUnusedBuffer(size, true); 118 const auto& staging = staging_pool.GetUnusedBuffer(size, true);
119 scheduler.RequestOutsideRenderPassOperationContext(); 119 scheduler.RequestOutsideRenderPassOperationContext();
120 scheduler.Record([staging = *staging.handle, buffer = *buffer->GetHandle(), offset, 120 scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset,
121 size](vk::CommandBuffer cmdbuf) { 121 size](vk::CommandBuffer cmdbuf) {
122 VkBufferMemoryBarrier barrier; 122 VkBufferMemoryBarrier barrier;
123 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 123 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
@@ -144,7 +144,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset,
144void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, 144void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
145 std::size_t dst_offset, std::size_t size) { 145 std::size_t dst_offset, std::size_t size) {
146 scheduler.RequestOutsideRenderPassOperationContext(); 146 scheduler.RequestOutsideRenderPassOperationContext();
147 scheduler.Record([src_buffer = *src->GetHandle(), dst_buffer = *dst->GetHandle(), src_offset, 147 scheduler.Record([src_buffer = src->GetHandle(), dst_buffer = dst->GetHandle(), src_offset,
148 dst_offset, size](vk::CommandBuffer cmdbuf) { 148 dst_offset, size](vk::CommandBuffer cmdbuf) {
149 cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); 149 cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size});
150 150
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index d3c23da98..3cd2e2774 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -33,8 +33,8 @@ public:
33 VAddr cpu_addr, std::size_t size); 33 VAddr cpu_addr, std::size_t size);
34 ~CachedBufferBlock(); 34 ~CachedBufferBlock();
35 35
36 const VkBuffer* GetHandle() const { 36 VkBuffer GetHandle() const {
37 return buffer.handle.address(); 37 return *buffer.handle;
38 } 38 }
39 39
40private: 40private:
@@ -50,15 +50,15 @@ public:
50 VKScheduler& scheduler, VKStagingBufferPool& staging_pool); 50 VKScheduler& scheduler, VKStagingBufferPool& staging_pool);
51 ~VKBufferCache(); 51 ~VKBufferCache();
52 52
53 const VkBuffer* GetEmptyBuffer(std::size_t size) override; 53 VkBuffer GetEmptyBuffer(std::size_t size) override;
54 54
55protected: 55protected:
56 VkBuffer ToHandle(const Buffer& buffer) override;
57
56 void WriteBarrier() override {} 58 void WriteBarrier() override {}
57 59
58 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override; 60 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
59 61
60 const VkBuffer* ToHandle(const Buffer& buffer) override;
61
62 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 62 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
63 const u8* data) override; 63 const u8* data) override;
64 64
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 9d92305f4..878a78755 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -343,13 +343,13 @@ QuadArrayPass::QuadArrayPass(const VKDevice& device, VKScheduler& scheduler,
343 343
344QuadArrayPass::~QuadArrayPass() = default; 344QuadArrayPass::~QuadArrayPass() = default;
345 345
346std::pair<const VkBuffer*, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) { 346std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) {
347 const u32 num_triangle_vertices = num_vertices * 6 / 4; 347 const u32 num_triangle_vertices = num_vertices * 6 / 4;
348 const std::size_t staging_size = num_triangle_vertices * sizeof(u32); 348 const std::size_t staging_size = num_triangle_vertices * sizeof(u32);
349 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false); 349 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
350 350
351 update_descriptor_queue.Acquire(); 351 update_descriptor_queue.Acquire();
352 update_descriptor_queue.AddBuffer(buffer.handle.address(), 0, staging_size); 352 update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
353 const auto set = CommitDescriptorSet(update_descriptor_queue, scheduler.GetFence()); 353 const auto set = CommitDescriptorSet(update_descriptor_queue, scheduler.GetFence());
354 354
355 scheduler.RequestOutsideRenderPassOperationContext(); 355 scheduler.RequestOutsideRenderPassOperationContext();
@@ -377,7 +377,7 @@ std::pair<const VkBuffer*, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertice
377 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 377 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
378 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, {barrier}, {}); 378 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, {barrier}, {});
379 }); 379 });
380 return {buffer.handle.address(), 0}; 380 return {*buffer.handle, 0};
381} 381}
382 382
383Uint8Pass::Uint8Pass(const VKDevice& device, VKScheduler& scheduler, 383Uint8Pass::Uint8Pass(const VKDevice& device, VKScheduler& scheduler,
@@ -391,14 +391,14 @@ Uint8Pass::Uint8Pass(const VKDevice& device, VKScheduler& scheduler,
391 391
392Uint8Pass::~Uint8Pass() = default; 392Uint8Pass::~Uint8Pass() = default;
393 393
394std::pair<const VkBuffer*, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer, 394std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
395 u64 src_offset) { 395 u64 src_offset) {
396 const auto staging_size = static_cast<u32>(num_vertices * sizeof(u16)); 396 const auto staging_size = static_cast<u32>(num_vertices * sizeof(u16));
397 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false); 397 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
398 398
399 update_descriptor_queue.Acquire(); 399 update_descriptor_queue.Acquire();
400 update_descriptor_queue.AddBuffer(&src_buffer, src_offset, num_vertices); 400 update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
401 update_descriptor_queue.AddBuffer(buffer.handle.address(), 0, staging_size); 401 update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
402 const auto set = CommitDescriptorSet(update_descriptor_queue, scheduler.GetFence()); 402 const auto set = CommitDescriptorSet(update_descriptor_queue, scheduler.GetFence());
403 403
404 scheduler.RequestOutsideRenderPassOperationContext(); 404 scheduler.RequestOutsideRenderPassOperationContext();
@@ -422,7 +422,7 @@ std::pair<const VkBuffer*, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer s
422 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 422 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
423 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, barrier, {}); 423 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, barrier, {});
424 }); 424 });
425 return {buffer.handle.address(), 0}; 425 return {*buffer.handle, 0};
426} 426}
427 427
428} // namespace Vulkan 428} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index c62516bff..ec80c8683 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -50,7 +50,7 @@ public:
50 VKUpdateDescriptorQueue& update_descriptor_queue); 50 VKUpdateDescriptorQueue& update_descriptor_queue);
51 ~QuadArrayPass(); 51 ~QuadArrayPass();
52 52
53 std::pair<const VkBuffer*, VkDeviceSize> Assemble(u32 num_vertices, u32 first); 53 std::pair<VkBuffer, VkDeviceSize> Assemble(u32 num_vertices, u32 first);
54 54
55private: 55private:
56 VKScheduler& scheduler; 56 VKScheduler& scheduler;
@@ -65,7 +65,7 @@ public:
65 VKUpdateDescriptorQueue& update_descriptor_queue); 65 VKUpdateDescriptorQueue& update_descriptor_queue);
66 ~Uint8Pass(); 66 ~Uint8Pass();
67 67
68 std::pair<const VkBuffer*, u64> Assemble(u32 num_vertices, VkBuffer src_buffer, u64 src_offset); 68 std::pair<VkBuffer, u64> Assemble(u32 num_vertices, VkBuffer src_buffer, u64 src_offset);
69 69
70private: 70private:
71 VKScheduler& scheduler; 71 VKScheduler& scheduler;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 33cbc0bb6..ab281c9e2 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -134,13 +134,13 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry
134 134
135class BufferBindings final { 135class BufferBindings final {
136public: 136public:
137 void AddVertexBinding(const VkBuffer* buffer, VkDeviceSize offset) { 137 void AddVertexBinding(VkBuffer buffer, VkDeviceSize offset) {
138 vertex.buffer_ptrs[vertex.num_buffers] = buffer; 138 vertex.buffers[vertex.num_buffers] = buffer;
139 vertex.offsets[vertex.num_buffers] = offset; 139 vertex.offsets[vertex.num_buffers] = offset;
140 ++vertex.num_buffers; 140 ++vertex.num_buffers;
141 } 141 }
142 142
143 void SetIndexBinding(const VkBuffer* buffer, VkDeviceSize offset, VkIndexType type) { 143 void SetIndexBinding(VkBuffer buffer, VkDeviceSize offset, VkIndexType type) {
144 index.buffer = buffer; 144 index.buffer = buffer;
145 index.offset = offset; 145 index.offset = offset;
146 index.type = type; 146 index.type = type;
@@ -224,19 +224,19 @@ private:
224 // Some of these fields are intentionally left uninitialized to avoid initializing them twice. 224 // Some of these fields are intentionally left uninitialized to avoid initializing them twice.
225 struct { 225 struct {
226 std::size_t num_buffers = 0; 226 std::size_t num_buffers = 0;
227 std::array<const VkBuffer*, Maxwell::NumVertexArrays> buffer_ptrs; 227 std::array<VkBuffer, Maxwell::NumVertexArrays> buffers;
228 std::array<VkDeviceSize, Maxwell::NumVertexArrays> offsets; 228 std::array<VkDeviceSize, Maxwell::NumVertexArrays> offsets;
229 } vertex; 229 } vertex;
230 230
231 struct { 231 struct {
232 const VkBuffer* buffer = nullptr; 232 VkBuffer buffer = nullptr;
233 VkDeviceSize offset; 233 VkDeviceSize offset;
234 VkIndexType type; 234 VkIndexType type;
235 } index; 235 } index;
236 236
237 template <std::size_t N> 237 template <std::size_t N>
238 void BindStatic(VKScheduler& scheduler) const { 238 void BindStatic(VKScheduler& scheduler) const {
239 if (index.buffer != nullptr) { 239 if (index.buffer) {
240 BindStatic<N, true>(scheduler); 240 BindStatic<N, true>(scheduler);
241 } else { 241 } else {
242 BindStatic<N, false>(scheduler); 242 BindStatic<N, false>(scheduler);
@@ -251,18 +251,14 @@ private:
251 } 251 }
252 252
253 std::array<VkBuffer, N> buffers; 253 std::array<VkBuffer, N> buffers;
254 std::transform(vertex.buffer_ptrs.begin(), vertex.buffer_ptrs.begin() + N, buffers.begin(),
255 [](const auto ptr) { return *ptr; });
256
257 std::array<VkDeviceSize, N> offsets; 254 std::array<VkDeviceSize, N> offsets;
255 std::copy(vertex.buffers.begin(), vertex.buffers.begin() + N, buffers.begin());
258 std::copy(vertex.offsets.begin(), vertex.offsets.begin() + N, offsets.begin()); 256 std::copy(vertex.offsets.begin(), vertex.offsets.begin() + N, offsets.begin());
259 257
260 if constexpr (is_indexed) { 258 if constexpr (is_indexed) {
261 // Indexed draw 259 // Indexed draw
262 scheduler.Record([buffers, offsets, index_buffer = *index.buffer, 260 scheduler.Record([buffers, offsets, index = index](vk::CommandBuffer cmdbuf) {
263 index_offset = index.offset, 261 cmdbuf.BindIndexBuffer(index.buffer, index.offset, index.type);
264 index_type = index.type](vk::CommandBuffer cmdbuf) {
265 cmdbuf.BindIndexBuffer(index_buffer, index_offset, index_type);
266 cmdbuf.BindVertexBuffers(0, static_cast<u32>(N), buffers.data(), offsets.data()); 262 cmdbuf.BindVertexBuffers(0, static_cast<u32>(N), buffers.data(), offsets.data());
267 }); 263 });
268 } else { 264 } else {
@@ -787,7 +783,7 @@ void RasterizerVulkan::BeginTransformFeedback() {
787 const std::size_t size = binding.buffer_size; 783 const std::size_t size = binding.buffer_size;
788 const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); 784 const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true);
789 785
790 scheduler.Record([buffer = *buffer, offset = offset, size](vk::CommandBuffer cmdbuf) { 786 scheduler.Record([buffer = buffer, offset = offset, size](vk::CommandBuffer cmdbuf) {
791 cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); 787 cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size);
792 cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); 788 cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr);
793 }); 789 });
@@ -867,7 +863,7 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar
867 auto format = regs.index_array.format; 863 auto format = regs.index_array.format;
868 const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; 864 const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte;
869 if (is_uint8 && !device.IsExtIndexTypeUint8Supported()) { 865 if (is_uint8 && !device.IsExtIndexTypeUint8Supported()) {
870 std::tie(buffer, offset) = uint8_pass.Assemble(params.num_vertices, *buffer, offset); 866 std::tie(buffer, offset) = uint8_pass.Assemble(params.num_vertices, buffer, offset);
871 format = Maxwell::IndexFormat::UnsignedShort; 867 format = Maxwell::IndexFormat::UnsignedShort;
872 } 868 }
873 869
@@ -1004,8 +1000,8 @@ void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAdd
1004 const auto size = memory_manager.Read<u32>(address + 8); 1000 const auto size = memory_manager.Read<u32>(address + 8);
1005 1001
1006 if (size == 0) { 1002 if (size == 0) {
1007 // Sometimes global memory pointers don't have a proper size. Upload a dummy entry because 1003 // Sometimes global memory pointers don't have a proper size. Upload a dummy entry
1008 // Vulkan doesn't like empty buffers. 1004 // because Vulkan doesn't like empty buffers.
1009 constexpr std::size_t dummy_size = 4; 1005 constexpr std::size_t dummy_size = 4;
1010 const auto buffer = buffer_cache.GetEmptyBuffer(dummy_size); 1006 const auto buffer = buffer_cache.GetEmptyBuffer(dummy_size);
1011 update_descriptor_queue.AddBuffer(buffer, 0, dummy_size); 1007 update_descriptor_queue.AddBuffer(buffer, 0, dummy_size);
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
index 4bfec0077..681ecde98 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
@@ -35,12 +35,13 @@ void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template
35 payload.clear(); 35 payload.clear();
36 } 36 }
37 37
38 // TODO(Rodrigo): Rework to write the payload directly
38 const auto payload_start = payload.data() + payload.size(); 39 const auto payload_start = payload.data() + payload.size();
39 for (const auto& entry : entries) { 40 for (const auto& entry : entries) {
40 if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) { 41 if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) {
41 payload.push_back(*image); 42 payload.push_back(*image);
42 } else if (const auto buffer = std::get_if<Buffer>(&entry)) { 43 } else if (const auto buffer = std::get_if<VkDescriptorBufferInfo>(&entry)) {
43 payload.emplace_back(*buffer->buffer, buffer->offset, buffer->size); 44 payload.push_back(*buffer);
44 } else if (const auto texel = std::get_if<VkBufferView>(&entry)) { 45 } else if (const auto texel = std::get_if<VkBufferView>(&entry)) {
45 payload.push_back(*texel); 46 payload.push_back(*texel);
46 } else { 47 } else {
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h
index a9e3d5dba..6ba2c9997 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.h
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h
@@ -18,12 +18,11 @@ class VKScheduler;
18 18
19class DescriptorUpdateEntry { 19class DescriptorUpdateEntry {
20public: 20public:
21 explicit DescriptorUpdateEntry() : image{} {} 21 explicit DescriptorUpdateEntry() {}
22 22
23 DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {} 23 DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {}
24 24
25 DescriptorUpdateEntry(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size) 25 DescriptorUpdateEntry(VkDescriptorBufferInfo buffer) : buffer{buffer} {}
26 : buffer{buffer, offset, size} {}
27 26
28 DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {} 27 DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {}
29 28
@@ -54,8 +53,8 @@ public:
54 entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}}); 53 entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}});
55 } 54 }
56 55
57 void AddBuffer(const VkBuffer* buffer, u64 offset, std::size_t size) { 56 void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) {
58 entries.push_back(Buffer{buffer, offset, size}); 57 entries.emplace_back(VkDescriptorBufferInfo{buffer, offset, size});
59 } 58 }
60 59
61 void AddTexelBuffer(VkBufferView texel_buffer) { 60 void AddTexelBuffer(VkBufferView texel_buffer) {
@@ -67,12 +66,7 @@ public:
67 } 66 }
68 67
69private: 68private:
70 struct Buffer { 69 using Variant = std::variant<VkDescriptorImageInfo, VkDescriptorBufferInfo, VkBufferView>;
71 const VkBuffer* buffer = nullptr;
72 u64 offset = 0;
73 std::size_t size = 0;
74 };
75 using Variant = std::variant<VkDescriptorImageInfo, Buffer, VkBufferView>;
76 70
77 const VKDevice& device; 71 const VKDevice& device;
78 VKScheduler& scheduler; 72 VKScheduler& scheduler;