18 changed files with 453 additions and 31 deletions
-
2src/video_core/CMakeLists.txt
-
124src/video_core/renderer_vulkan/pipeline_helper.h
-
10src/video_core/renderer_vulkan/vk_buffer_cache.cpp
-
22src/video_core/renderer_vulkan/vk_buffer_cache.h
-
69src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
-
6src/video_core/renderer_vulkan/vk_compute_pipeline.h
-
98src/video_core/renderer_vulkan/vk_descriptor_buffer.cpp
-
57src/video_core/renderer_vulkan/vk_descriptor_buffer.h
-
5src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
-
2src/video_core/renderer_vulkan/vk_pipeline_cache.h
-
8src/video_core/renderer_vulkan/vk_rasterizer.cpp
-
2src/video_core/renderer_vulkan/vk_rasterizer.h
-
15src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
-
4src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
-
2src/video_core/renderer_vulkan/vk_texture_cache.cpp
-
8src/video_core/renderer_vulkan/vk_update_descriptor.cpp
-
46src/video_core/renderer_vulkan/vk_update_descriptor.h
-
4src/video_core/vulkan_common/vulkan_device.h
@ -0,0 +1,98 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
|
||||
|
#include <algorithm>
|
||||
|
|
||||
|
#include "common/alignment.h"
|
||||
|
#include "common/assert.h"
|
||||
|
#include "common/logging.h"
|
||||
|
#include "video_core/renderer_vulkan/vk_descriptor_buffer.h"
|
||||
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
DescriptorBufferRing::DescriptorBufferRing(const Device& device_, |
||||
|
MemoryAllocator& memory_allocator) |
||||
|
: device{device_} { |
||||
|
if (!device.IsExtDescriptorBufferSupported() || !device.IsBufferDeviceAddressSupported()) { |
||||
|
return; |
||||
|
} |
||||
|
alignment = std::max<VkDeviceSize>( |
||||
|
device.DescriptorBufferProperties().descriptorBufferOffsetAlignment, 1); |
||||
|
const VkDeviceSize total = FRAME_SIZE * FRAMES_IN_FLIGHT + alignment; |
||||
|
const VkBufferCreateInfo buffer_ci{ |
||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
||||
|
.pNext = nullptr, |
||||
|
.flags = 0, |
||||
|
.size = total, |
||||
|
.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | |
||||
|
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT | |
||||
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
||||
|
.queueFamilyIndexCount = 0, |
||||
|
.pQueueFamilyIndices = nullptr, |
||||
|
}; |
||||
|
buffer = memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::Upload); |
||||
|
if (!buffer.IsHostVisible()) { |
||||
|
LOG_WARNING(Render_Vulkan, "Descriptor buffer is not host visible, disabling"); |
||||
|
buffer.reset(); |
||||
|
return; |
||||
|
} |
||||
|
if (device.HasDebuggingToolAttached()) { |
||||
|
buffer.SetObjectNameEXT("Descriptor buffer"); |
||||
|
} |
||||
|
const VkDeviceAddress raw_address = device.GetLogical().GetBufferDeviceAddress(*buffer); |
||||
|
base_address = Common::AlignUp(raw_address, alignment); |
||||
|
base_host = buffer.Mapped().data() + (base_address - raw_address); |
||||
|
} |
||||
|
|
||||
|
DescriptorBufferRing::~DescriptorBufferRing() = default; |
||||
|
|
||||
|
void DescriptorBufferRing::TickFrame() { |
||||
|
if (++frame_index >= FRAMES_IN_FLIGHT) { |
||||
|
frame_index = 0; |
||||
|
} |
||||
|
frame_start = static_cast<VkDeviceSize>(frame_index) * FRAME_SIZE; |
||||
|
cursor = 0; |
||||
|
frame_reused = true; |
||||
|
} |
||||
|
|
||||
|
DescriptorBufferRing::Allocation DescriptorBufferRing::Allocate(Scheduler& scheduler, |
||||
|
VkDeviceSize size) { |
||||
|
ASSERT(buffer); |
||||
|
const VkDeviceSize needed = Common::AlignUp(size, alignment); |
||||
|
if (needed > FRAME_SIZE) { |
||||
|
LOG_ERROR(Render_Vulkan, "Descriptor set of {} bytes exceeds frame capacity {}", needed, |
||||
|
FRAME_SIZE); |
||||
|
return Allocation{}; |
||||
|
} |
||||
|
if (frame_reused) { |
||||
|
frame_reused = false; |
||||
|
scheduler.Wait(frame_ticks[frame_index]); |
||||
|
} |
||||
|
if (cursor + needed > FRAME_SIZE) { |
||||
|
LOG_WARNING(Render_Vulkan, "Descriptor buffer frame exhausted, stalling on the GPU"); |
||||
|
scheduler.Finish(); |
||||
|
cursor = 0; |
||||
|
} |
||||
|
const VkDeviceSize offset = frame_start + cursor; |
||||
|
cursor += needed; |
||||
|
frame_ticks[frame_index] = scheduler.CurrentTick(); |
||||
|
return Allocation{ |
||||
|
.host = base_host + offset, |
||||
|
.offset = offset, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
VkDescriptorBufferBindingInfoEXT DescriptorBufferRing::BindingInfo() const noexcept { |
||||
|
return VkDescriptorBufferBindingInfoEXT{ |
||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT, |
||||
|
.pNext = nullptr, |
||||
|
.address = base_address, |
||||
|
.usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | |
||||
|
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,57 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h" |
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
class Device; |
||||
|
class Scheduler; |
||||
|
|
||||
|
class DescriptorBufferRing final { |
||||
|
static constexpr size_t FRAMES_IN_FLIGHT = 8; |
||||
|
static constexpr VkDeviceSize FRAME_SIZE = 512 * 1024; |
||||
|
|
||||
|
public: |
||||
|
explicit DescriptorBufferRing(const Device& device_, MemoryAllocator& memory_allocator); |
||||
|
~DescriptorBufferRing(); |
||||
|
|
||||
|
struct Allocation { |
||||
|
u8* host{}; |
||||
|
VkDeviceSize offset{}; |
||||
|
}; |
||||
|
|
||||
|
[[nodiscard]] static constexpr VkDeviceSize MaxAllocationSize() noexcept { |
||||
|
return FRAME_SIZE; |
||||
|
} |
||||
|
|
||||
|
void TickFrame(); |
||||
|
|
||||
|
[[nodiscard]] Allocation Allocate(Scheduler& scheduler, VkDeviceSize size); |
||||
|
|
||||
|
[[nodiscard]] VkDescriptorBufferBindingInfoEXT BindingInfo() const noexcept; |
||||
|
|
||||
|
[[nodiscard]] bool IsValid() const noexcept { |
||||
|
return static_cast<bool>(buffer); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
const Device& device; |
||||
|
vk::Buffer buffer; |
||||
|
VkDeviceAddress base_address{}; |
||||
|
u8* base_host{}; |
||||
|
VkDeviceSize alignment{1}; |
||||
|
size_t frame_index{}; |
||||
|
VkDeviceSize frame_start{}; |
||||
|
VkDeviceSize cursor{}; |
||||
|
std::array<u64, FRAMES_IN_FLIGHT> frame_ticks{}; |
||||
|
bool frame_reused{}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Vulkan |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue