mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-03-28 14:40:05 -06:00
video_core: Fix a few vulkan validation issues (#1818)
This commit is contained in:
parent
d49aa070fd
commit
8d284aeccf
@ -250,8 +250,7 @@ BlitHelper::BlitHelper(const Instance& instance_, Scheduler& scheduler_,
|
||||
vk::ShaderStageFlagBits::eCompute, device)},
|
||||
depth_to_buffer_comp{Compile(HostShaders::VULKAN_DEPTH_TO_BUFFER_COMP,
|
||||
vk::ShaderStageFlagBits::eCompute, device)},
|
||||
blit_depth_stencil_frag{Compile(HostShaders::VULKAN_BLIT_DEPTH_STENCIL_FRAG,
|
||||
vk::ShaderStageFlagBits::eFragment, device)},
|
||||
blit_depth_stencil_frag{VK_NULL_HANDLE},
|
||||
// Texture filtering shader modules
|
||||
bicubic_frag{Compile(HostShaders::BICUBIC_FRAG, vk::ShaderStageFlagBits::eFragment, device)},
|
||||
scale_force_frag{
|
||||
@ -263,10 +262,16 @@ BlitHelper::BlitHelper(const Instance& instance_, Scheduler& scheduler_,
|
||||
d24s8_to_rgba8_pipeline{MakeComputePipeline(d24s8_to_rgba8_comp, compute_pipeline_layout)},
|
||||
depth_to_buffer_pipeline{
|
||||
MakeComputePipeline(depth_to_buffer_comp, compute_buffer_pipeline_layout)},
|
||||
depth_blit_pipeline{MakeDepthStencilBlitPipeline()},
|
||||
depth_blit_pipeline{VK_NULL_HANDLE},
|
||||
linear_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eLinear>)},
|
||||
nearest_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eNearest>)} {
|
||||
|
||||
if (instance.IsShaderStencilExportSupported()) {
|
||||
blit_depth_stencil_frag = Compile(HostShaders::VULKAN_BLIT_DEPTH_STENCIL_FRAG,
|
||||
vk::ShaderStageFlagBits::eFragment, device);
|
||||
depth_blit_pipeline = MakeDepthStencilBlitPipeline();
|
||||
}
|
||||
|
||||
if (instance.HasDebuggingToolAttached()) {
|
||||
SetObjectName(device, compute_pipeline_layout, "BlitHelper: compute_pipeline_layout");
|
||||
SetObjectName(device, compute_buffer_pipeline_layout,
|
||||
@ -280,7 +285,9 @@ BlitHelper::BlitHelper(const Instance& instance_, Scheduler& scheduler_,
|
||||
SetObjectName(device, full_screen_vert, "BlitHelper: full_screen_vert");
|
||||
SetObjectName(device, d24s8_to_rgba8_comp, "BlitHelper: d24s8_to_rgba8_comp");
|
||||
SetObjectName(device, depth_to_buffer_comp, "BlitHelper: depth_to_buffer_comp");
|
||||
SetObjectName(device, blit_depth_stencil_frag, "BlitHelper: blit_depth_stencil_frag");
|
||||
if (blit_depth_stencil_frag) {
|
||||
SetObjectName(device, blit_depth_stencil_frag, "BlitHelper: blit_depth_stencil_frag");
|
||||
}
|
||||
SetObjectName(device, d24s8_to_rgba8_pipeline, "BlitHelper: d24s8_to_rgba8_pipeline");
|
||||
SetObjectName(device, depth_to_buffer_pipeline, "BlitHelper: depth_to_buffer_pipeline");
|
||||
if (depth_blit_pipeline) {
|
||||
@ -304,7 +311,9 @@ BlitHelper::~BlitHelper() {
|
||||
device.destroyShaderModule(full_screen_vert);
|
||||
device.destroyShaderModule(d24s8_to_rgba8_comp);
|
||||
device.destroyShaderModule(depth_to_buffer_comp);
|
||||
device.destroyShaderModule(blit_depth_stencil_frag);
|
||||
if (blit_depth_stencil_frag) {
|
||||
device.destroyShaderModule(blit_depth_stencil_frag);
|
||||
}
|
||||
// Destroy texture filtering shader modules
|
||||
device.destroyShaderModule(bicubic_frag);
|
||||
device.destroyShaderModule(scale_force_frag);
|
||||
@ -592,10 +601,6 @@ vk::Pipeline BlitHelper::MakeComputePipeline(vk::ShaderModule shader, vk::Pipeli
|
||||
}
|
||||
|
||||
vk::Pipeline BlitHelper::MakeDepthStencilBlitPipeline() {
|
||||
if (!instance.IsShaderStencilExportSupported()) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
const std::array stages = MakeStages(full_screen_vert, blit_depth_stencil_frag);
|
||||
const auto renderpass = renderpass_cache.GetRenderpass(VideoCore::PixelFormat::Invalid,
|
||||
VideoCore::PixelFormat::D24S8, false);
|
||||
|
||||
@ -398,8 +398,6 @@ bool Instance::CreateDevice() {
|
||||
const vk::StructureChain feature_chain = physical_device.getFeatures2<
|
||||
vk::PhysicalDeviceFeatures2, vk::PhysicalDevicePortabilitySubsetFeaturesKHR,
|
||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT,
|
||||
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT,
|
||||
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT,
|
||||
vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR,
|
||||
vk::PhysicalDeviceCustomBorderColorFeaturesEXT, vk::PhysicalDeviceIndexTypeUint8FeaturesEXT,
|
||||
vk::PhysicalDeviceFragmentShaderInterlockFeaturesEXT,
|
||||
@ -529,8 +527,6 @@ bool Instance::CreateDevice() {
|
||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR{},
|
||||
vk::PhysicalDeviceTimelineSemaphoreFeaturesKHR{},
|
||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{},
|
||||
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{},
|
||||
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT{},
|
||||
vk::PhysicalDeviceCustomBorderColorFeaturesEXT{},
|
||||
vk::PhysicalDeviceIndexTypeUint8FeaturesEXT{},
|
||||
vk::PhysicalDeviceFragmentShaderInterlockFeaturesEXT{},
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
@ -6,6 +10,7 @@
|
||||
#include <limits>
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/literals.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
#include "video_core/renderer_vulkan/vk_memory_util.h"
|
||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||
@ -15,6 +20,8 @@ namespace Vulkan {
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace Common::Literals;
|
||||
|
||||
std::string_view BufferTypeName(BufferType type) {
|
||||
switch (type) {
|
||||
case BufferType::Upload:
|
||||
@ -167,7 +174,7 @@ void StreamBuffer::Commit(u32 size) {
|
||||
watch.tick = scheduler.CurrentTick();
|
||||
}
|
||||
|
||||
void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
||||
void StreamBuffer::CreateBuffers(u64 preferred_size) {
|
||||
const vk::Device device = instance.GetDevice();
|
||||
const auto memory_properties = instance.GetPhysicalDevice().getMemoryProperties();
|
||||
const u32 preferred_type = GetMemoryType(memory_properties, type);
|
||||
@ -180,53 +187,81 @@ void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
||||
const vk::DeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
|
||||
// As per DXVK's example, using `heap_size / 2`
|
||||
const vk::DeviceSize allocable_size = heap_size / 2;
|
||||
buffer = device.createBuffer({
|
||||
.size = std::min(prefered_size, allocable_size),
|
||||
.usage = usage,
|
||||
});
|
||||
|
||||
const auto requirements_chain =
|
||||
device
|
||||
.getBufferMemoryRequirements2<vk::MemoryRequirements2, vk::MemoryDedicatedRequirements>(
|
||||
{.buffer = buffer});
|
||||
vk::DeviceSize attempt_size = std::min(preferred_size, allocable_size);
|
||||
|
||||
const auto& requirements = requirements_chain.get<vk::MemoryRequirements2>();
|
||||
const auto& dedicated_requirements = requirements_chain.get<vk::MemoryDedicatedRequirements>();
|
||||
// Retry allocation until we reach minimum 8 KiB allocation size
|
||||
const vk::DeviceSize min_buffer_size = std::min<vk::DeviceSize>(8_KiB, attempt_size);
|
||||
|
||||
stream_buffer_size = static_cast<u64>(requirements.memoryRequirements.size);
|
||||
while (attempt_size >= min_buffer_size) {
|
||||
try {
|
||||
// Create buffer with current attempt size
|
||||
buffer = device.createBuffer({
|
||||
.size = attempt_size,
|
||||
.usage = usage,
|
||||
});
|
||||
|
||||
LOG_INFO(Render_Vulkan, "Creating {} buffer with size {} KiB with flags {}",
|
||||
BufferTypeName(type), stream_buffer_size / 1024,
|
||||
vk::to_string(mem_type.propertyFlags));
|
||||
const auto requirements_chain = device.getBufferMemoryRequirements2<
|
||||
vk::MemoryRequirements2, vk::MemoryDedicatedRequirements>({.buffer = buffer});
|
||||
|
||||
if (dedicated_requirements.prefersDedicatedAllocation) {
|
||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> alloc_chain =
|
||||
{};
|
||||
const auto& requirements = requirements_chain.get<vk::MemoryRequirements2>();
|
||||
const auto& dedicated_requirements =
|
||||
requirements_chain.get<vk::MemoryDedicatedRequirements>();
|
||||
|
||||
auto& alloc_info = alloc_chain.get<vk::MemoryAllocateInfo>();
|
||||
alloc_info.allocationSize = requirements.memoryRequirements.size;
|
||||
alloc_info.memoryTypeIndex = preferred_type;
|
||||
if (dedicated_requirements.prefersDedicatedAllocation) {
|
||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo>
|
||||
alloc_chain{};
|
||||
|
||||
auto& dedicated_alloc_info = alloc_chain.get<vk::MemoryDedicatedAllocateInfo>();
|
||||
dedicated_alloc_info.buffer = buffer;
|
||||
auto& alloc_info = alloc_chain.get<vk::MemoryAllocateInfo>();
|
||||
alloc_info.allocationSize = requirements.memoryRequirements.size;
|
||||
alloc_info.memoryTypeIndex = preferred_type;
|
||||
|
||||
memory = device.allocateMemory(alloc_chain.get());
|
||||
} else {
|
||||
memory = device.allocateMemory({
|
||||
.allocationSize = requirements.memoryRequirements.size,
|
||||
.memoryTypeIndex = preferred_type,
|
||||
});
|
||||
auto& dedicated_alloc_info = alloc_chain.get<vk::MemoryDedicatedAllocateInfo>();
|
||||
dedicated_alloc_info.buffer = buffer;
|
||||
|
||||
memory = device.allocateMemory(alloc_chain.get());
|
||||
} else {
|
||||
memory = device.allocateMemory({
|
||||
.allocationSize = requirements.memoryRequirements.size,
|
||||
.memoryTypeIndex = preferred_type,
|
||||
});
|
||||
}
|
||||
|
||||
// Allocation succeeded, bind and map
|
||||
device.bindBufferMemory(buffer, memory, 0);
|
||||
|
||||
mapped = reinterpret_cast<u8*>(
|
||||
device.mapMemory(memory, 0, requirements.memoryRequirements.size));
|
||||
|
||||
stream_buffer_size = static_cast<u64>(attempt_size);
|
||||
|
||||
LOG_INFO(Render_Vulkan, "Created {} buffer with size {} KiB (flags {})",
|
||||
BufferTypeName(type), stream_buffer_size / 1024,
|
||||
vk::to_string(mem_type.propertyFlags));
|
||||
|
||||
if (instance.HasDebuggingToolAttached()) {
|
||||
SetObjectName(device, buffer, "StreamBuffer({}): {} KiB {}", BufferTypeName(type),
|
||||
stream_buffer_size / 1024, vk::to_string(mem_type.propertyFlags));
|
||||
SetObjectName(device, memory, "StreamBufferMemory({}): {} Kib {}",
|
||||
BufferTypeName(type), stream_buffer_size / 1024,
|
||||
vk::to_string(mem_type.propertyFlags));
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (const vk::SystemError& err) {
|
||||
// Allocation failed, clean up and retry smaller
|
||||
if (buffer) {
|
||||
device.destroyBuffer(buffer);
|
||||
buffer = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
attempt_size /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
device.bindBufferMemory(buffer, memory, 0);
|
||||
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
||||
|
||||
if (instance.HasDebuggingToolAttached()) {
|
||||
SetObjectName(device, buffer, "StreamBuffer({}): {} KiB {}", BufferTypeName(type),
|
||||
stream_buffer_size / 1024, vk::to_string(mem_type.propertyFlags));
|
||||
SetObjectName(device, memory, "StreamBufferMemory({}): {} Kib {}", BufferTypeName(type),
|
||||
stream_buffer_size / 1024, vk::to_string(mem_type.propertyFlags));
|
||||
}
|
||||
UNREACHABLE_MSG("Failed to allocate {} buffer of preferred size {} KiB (flags {})",
|
||||
BufferTypeName(type), preferred_size / 1024,
|
||||
vk::to_string(mem_type.propertyFlags));
|
||||
}
|
||||
|
||||
void StreamBuffer::ReserveWatches(std::vector<Watch>& watches, std::size_t grow_size) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user