diff options
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp | 186 |
1 files changed, 54 insertions, 132 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp b/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp index d1719d36d1..7e4b13408a 100644 --- a/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKBoundingBox.cpp @@ -3,7 +3,6 @@ #include <vector> -#include "Common/Assert.h" #include "Common/Logging/Log.h" #include "VideoBackends/Vulkan/CommandBufferManager.h" @@ -16,11 +15,7 @@ namespace Vulkan { -BoundingBox::BoundingBox() -{ -} - -BoundingBox::~BoundingBox() +VKBoundingBox::~VKBoundingBox() { if (m_gpu_buffer != VK_NULL_HANDLE) { @@ -29,14 +24,8 @@ BoundingBox::~BoundingBox() } } -bool BoundingBox::Initialize() +bool VKBoundingBox::Initialize() { - if (!g_ActiveConfig.backend_info.bSupportsBBox) - { - WARN_LOG_FMT(VIDEO, "Vulkan: Bounding box is unsupported by your device."); - return true; - } - if (!CreateGPUBuffer()) return false; @@ -48,103 +37,71 @@ bool BoundingBox::Initialize() return true; } -void BoundingBox::Flush() +std::vector<BBoxType> VKBoundingBox::Read(u32 index, u32 length) { - if (m_gpu_buffer == VK_NULL_HANDLE) - return; - - // Combine updates together, chances are the game would have written all 4. - bool updated_buffer = false; - for (size_t start = 0; start < 4; start++) - { - if (!m_values_dirty[start]) - continue; - - size_t count = 0; - std::array<s32, 4> write_values; - for (; (start + count) < 4; count++) - { - if (!m_values_dirty[start + count]) - break; - - m_readback_buffer->Read((start + count) * sizeof(s32), &write_values[count], sizeof(s32), - false); - m_values_dirty[start + count] = false; - } - - // We can't issue vkCmdUpdateBuffer within a render pass. - // However, the writes must be serialized, so we can't put it in the init buffer. - if (!updated_buffer) - { - StateTracker::GetInstance()->EndRenderPass(); - - // Ensure GPU buffer is in a state where it can be transferred to. - StagingBuffer::BufferMemoryBarrier( - g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, - BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - updated_buffer = true; - } - - vkCmdUpdateBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, - start * sizeof(s32), count * sizeof(s32), - reinterpret_cast<const u32*>(write_values.data())); - } - - // Restore fragment shader access to the buffer. - if (updated_buffer) - { - StagingBuffer::BufferMemoryBarrier( - g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - } + // Can't be done within a render pass. + StateTracker::GetInstance()->EndRenderPass(); - // We're now up-to-date. - m_valid = true; -} + // Ensure all writes are completed to the GPU buffer prior to the transfer. + StagingBuffer::BufferMemoryBarrier( + g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, + BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + m_readback_buffer->PrepareForGPUWrite(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); -void BoundingBox::Invalidate() -{ - if (m_gpu_buffer == VK_NULL_HANDLE) - return; + // Copy from GPU -> readback buffer. + VkBufferCopy region = {0, 0, BUFFER_SIZE}; + vkCmdCopyBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, + m_readback_buffer->GetBuffer(), 1, ®ion); - m_valid = false; -} + // Restore GPU buffer access. + StagingBuffer::BufferMemoryBarrier( + g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + m_readback_buffer->FlushGPUCache(g_command_buffer_mgr->GetCurrentCommandBuffer(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); -s32 BoundingBox::Get(size_t index) -{ - ASSERT(index < NUM_VALUES); + // Wait until these commands complete. + Renderer::GetInstance()->ExecuteCommandBuffer(false, true); - if (!m_valid) - Readback(); + // Cache is now valid. + m_readback_buffer->InvalidateCPUCache(); - s32 value; - m_readback_buffer->Read(index * sizeof(s32), &value, sizeof(value), false); - return value; + // Read out the values and return + std::vector<BBoxType> values(length); + m_readback_buffer->Read(index * sizeof(BBoxType), values.data(), length * sizeof(BBoxType), + false); + return values; } -void BoundingBox::Set(size_t index, s32 value) +void VKBoundingBox::Write(u32 index, const std::vector<BBoxType>& values) { - ASSERT(index < NUM_VALUES); + // We can't issue vkCmdUpdateBuffer within a render pass. + // However, the writes must be serialized, so we can't put it in the init buffer. + StateTracker::GetInstance()->EndRenderPass(); - // If we're currently valid, update the stored value in both our cache and the GPU buffer. - if (m_valid) - { - // Skip when it hasn't changed. - s32 current_value; - m_readback_buffer->Read(index * sizeof(s32), ¤t_value, sizeof(current_value), false); - if (current_value == value) - return; - } + // Ensure GPU buffer is in a state where it can be transferred to. + StagingBuffer::BufferMemoryBarrier( + g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, + BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + // Write the values to the GPU buffer + vkCmdUpdateBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, + index * sizeof(BBoxType), values.size() * sizeof(BBoxType), + reinterpret_cast<const BBoxType*>(values.data())); - // Flag as dirty, and update values. - m_readback_buffer->Write(index * sizeof(s32), &value, sizeof(value), true); - m_values_dirty[index] = true; + // Restore fragment shader access to the buffer. + StagingBuffer::BufferMemoryBarrier( + g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } -bool BoundingBox::CreateGPUBuffer() +bool VKBoundingBox::CreateGPUBuffer() { VkBufferUsageFlags buffer_usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | @@ -204,7 +161,7 @@ bool BoundingBox::CreateGPUBuffer() return true; } -bool BoundingBox::CreateReadbackBuffer() +bool VKBoundingBox::CreateReadbackBuffer() { m_readback_buffer = StagingBuffer::Create(STAGING_BUFFER_TYPE_READBACK, BUFFER_SIZE, VK_BUFFER_USAGE_TRANSFER_DST_BIT); @@ -215,39 +172,4 @@ bool BoundingBox::CreateReadbackBuffer() return true; } -void BoundingBox::Readback() -{ - // Can't be done within a render pass. - StateTracker::GetInstance()->EndRenderPass(); - - // Ensure all writes are completed to the GPU buffer prior to the transfer. - StagingBuffer::BufferMemoryBarrier( - g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, - BUFFER_SIZE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - m_readback_buffer->PrepareForGPUWrite(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - - // Copy from GPU -> readback buffer. - VkBufferCopy region = {0, 0, BUFFER_SIZE}; - vkCmdCopyBuffer(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, - m_readback_buffer->GetBuffer(), 1, ®ion); - - // Restore GPU buffer access. - StagingBuffer::BufferMemoryBarrier( - g_command_buffer_mgr->GetCurrentCommandBuffer(), m_gpu_buffer, VK_ACCESS_TRANSFER_READ_BIT, - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0, BUFFER_SIZE, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - m_readback_buffer->FlushGPUCache(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - // Wait until these commands complete. - Renderer::GetInstance()->ExecuteCommandBuffer(false, true); - - // Cache is now valid. - m_readback_buffer->InvalidateCPUCache(); - m_valid = true; -} - } // namespace Vulkan |
