From 5a45d295da3f614e3a9243eb324b61d94e39c305 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Fri, 9 Jul 2021 01:27:47 -0300
Subject: [PATCH] vk_buffer_cache: Use emulated null buffers for transform
 feedback

Vulkan does not support null buffers on transform feedback bindings.
Emulate these using the same null buffer we were using for index
buffers.
---
 .../renderer_vulkan/vk_buffer_cache.cpp       | 24 ++++++++++++-------
 .../renderer_vulkan/vk_buffer_cache.h         |  6 ++---
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 0df4e1a1cb..79876dfd01 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -152,8 +152,8 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat
     }
     if (vk_buffer == VK_NULL_HANDLE) {
         // Vulkan doesn't support null index buffers. Replace it with our own null buffer.
-        ReserveNullIndexBuffer();
-        vk_buffer = *null_index_buffer;
+        ReserveNullBuffer();
+        vk_buffer = *null_buffer;
     }
     scheduler.Record([vk_buffer, vk_offset, vk_index_type](vk::CommandBuffer cmdbuf) {
         cmdbuf.BindIndexBuffer(vk_buffer, vk_offset, vk_index_type);
@@ -195,6 +195,14 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer,
         // Already logged in the rasterizer
         return;
     }
+    if (buffer == VK_NULL_HANDLE) {
+        // Vulkan doesn't support null transform feedback buffers.
+        // Replace it with our own null buffer.
+        ReserveNullBuffer();
+        buffer = *null_buffer;
+        offset = 0;
+        size = 0;
+    }
     scheduler.Record([index, buffer, offset, size](vk::CommandBuffer cmdbuf) {
         const VkDeviceSize vk_offset = offset;
         const VkDeviceSize vk_size = size;
@@ -279,11 +287,11 @@ void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle
     });
 }
 
-void BufferCacheRuntime::ReserveNullIndexBuffer() {
-    if (null_index_buffer) {
+void BufferCacheRuntime::ReserveNullBuffer() {
+    if (null_buffer) {
         return;
     }
-    null_index_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
+    null_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{
         .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
         .pNext = nullptr,
         .flags = 0,
@@ -294,12 +302,12 @@ void BufferCacheRuntime::ReserveNullIndexBuffer() {
         .pQueueFamilyIndices = nullptr,
     });
     if (device.HasDebuggingToolAttached()) {
-        null_index_buffer.SetObjectNameEXT("Null index buffer");
+        null_buffer.SetObjectNameEXT("Null index buffer");
     }
-    null_index_buffer_commit = memory_allocator.Commit(null_index_buffer, MemoryUsage::DeviceLocal);
+    null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal);
 
     scheduler.RequestOutsideRenderPassOperationContext();
-    scheduler.Record([buffer = *null_index_buffer](vk::CommandBuffer cmdbuf) {
+    scheduler.Record([buffer = *null_buffer](vk::CommandBuffer cmdbuf) {
         cmdbuf.FillBuffer(buffer, 0, VK_WHOLE_SIZE, 0);
     });
 }
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 982e92191f..6ea8448d73 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -92,7 +92,7 @@ private:
 
     void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle);
 
-    void ReserveNullIndexBuffer();
+    void ReserveNullBuffer();
 
     const Device& device;
     MemoryAllocator& memory_allocator;
@@ -105,8 +105,8 @@ private:
     VkIndexType quad_array_lut_index_type{};
     u32 current_num_indices = 0;
 
-    vk::Buffer null_index_buffer;
-    MemoryCommit null_index_buffer_commit;
+    vk::Buffer null_buffer;
+    MemoryCommit null_buffer_commit;
 
     Uint8Pass uint8_pass;
     QuadIndexedPass quad_index_pass;