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