[vulkan] Follow-up for the VK_KHR_dynamic_rendering implementation
This commit is contained in:
parent
8932211b70
commit
480104dc50
|
|
@ -25,6 +25,7 @@
|
|||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||
#include "video_core/shader_notify.h"
|
||||
#include "video_core/texture_cache/texture_cache.h"
|
||||
#include "video_core/surface.h"
|
||||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
#include "video_core/gpu_logging/gpu_logging.h"
|
||||
#include "common/settings.h"
|
||||
|
|
@ -138,6 +139,10 @@ RenderPassKey MakeRenderPassKey(const FixedPipelineState& state) {
|
|||
return key;
|
||||
}
|
||||
|
||||
VkFormat DecodeVkFormat(const Device& device, PixelFormat format) {
|
||||
return MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, format).format;
|
||||
}
|
||||
|
||||
size_t NumAttachments(const FixedPipelineState& state) {
|
||||
size_t num{};
|
||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
|
||||
|
|
@ -942,10 +947,49 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
|
||||
}
|
||||
|
||||
const bool use_dynamic_rendering = device.IsDynamicRenderingSupported();
|
||||
static_vector<VkFormat, Maxwell::NumRenderTargets> color_formats;
|
||||
if (use_dynamic_rendering) {
|
||||
const size_t num_colors = NumAttachments(key.state);
|
||||
for (size_t index = 0; index < num_colors; ++index) {
|
||||
const auto rt_format = DecodeFormat(key.state.color_formats[index]);
|
||||
if (rt_format == PixelFormat::Invalid) {
|
||||
continue;
|
||||
}
|
||||
color_formats.push_back(DecodeVkFormat(device, rt_format));
|
||||
}
|
||||
}
|
||||
VkFormat depth_attachment_format = VK_FORMAT_UNDEFINED;
|
||||
VkFormat stencil_attachment_format = VK_FORMAT_UNDEFINED;
|
||||
if (use_dynamic_rendering && key.state.depth_enabled != 0) {
|
||||
const auto depth_format = static_cast<Tegra::DepthFormat>(key.state.depth_format.Value());
|
||||
const PixelFormat depth_pixel_format = PixelFormatFromDepthFormat(depth_format);
|
||||
const auto surface_type = VideoCore::Surface::GetFormatType(depth_pixel_format);
|
||||
const VkFormat vk_depth_format = DecodeVkFormat(device, depth_pixel_format);
|
||||
if (surface_type == VideoCore::Surface::SurfaceType::Depth ||
|
||||
surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
|
||||
depth_attachment_format = vk_depth_format;
|
||||
}
|
||||
if (surface_type == VideoCore::Surface::SurfaceType::Stencil ||
|
||||
surface_type == VideoCore::Surface::SurfaceType::DepthStencil) {
|
||||
stencil_attachment_format = vk_depth_format;
|
||||
}
|
||||
}
|
||||
|
||||
VkPipelineRenderingCreateInfo pipeline_rendering_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.viewMask = 0,
|
||||
.colorAttachmentCount = static_cast<u32>(color_formats.size()),
|
||||
.pColorAttachmentFormats = color_formats.data(),
|
||||
.depthAttachmentFormat = depth_attachment_format,
|
||||
.stencilAttachmentFormat = stencil_attachment_format,
|
||||
};
|
||||
|
||||
pipeline = device.GetLogical().CreateGraphicsPipeline(
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.pNext = use_dynamic_rendering ? &pipeline_rendering_ci : nullptr,
|
||||
.flags = flags,
|
||||
.stageCount = static_cast<u32>(shader_stages.size()),
|
||||
.pStages = shader_stages.data(),
|
||||
|
|
@ -959,7 +1003,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
.pColorBlendState = &color_blend_ci,
|
||||
.pDynamicState = &dynamic_state_ci,
|
||||
.layout = *pipeline_layout,
|
||||
.renderPass = render_pass,
|
||||
.renderPass = use_dynamic_rendering ? VK_NULL_HANDLE : render_pass,
|
||||
.subpass = 0,
|
||||
.basePipelineHandle = nullptr,
|
||||
.basePipelineIndex = 0,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
|||
const VkRenderPass renderpass = framebuffer->RenderPass();
|
||||
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
|
||||
const VkExtent2D render_area = framebuffer->RenderArea();
|
||||
const bool use_dynamic_rendering = device.IsDynamicRenderingSupported();
|
||||
if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer &&
|
||||
render_area.width == state.render_area.width &&
|
||||
render_area.height == state.render_area.height) {
|
||||
|
|
@ -127,25 +128,31 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
|||
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
|
||||
}
|
||||
|
||||
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
||||
const VkRenderPassBeginInfo renderpass_bi{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.renderPass = renderpass,
|
||||
.framebuffer = framebuffer_handle,
|
||||
.renderArea =
|
||||
{
|
||||
.offset = {.x = 0, .y = 0},
|
||||
.extent = render_area,
|
||||
},
|
||||
.clearValueCount = 0,
|
||||
.pClearValues = nullptr,
|
||||
};
|
||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||
});
|
||||
if (use_dynamic_rendering) {
|
||||
const VkRenderingInfo rendering_info = framebuffer->RenderingInfo();
|
||||
Record([rendering_info](vk::CommandBuffer cmdbuf) { cmdbuf.BeginRendering(&rendering_info); });
|
||||
} else {
|
||||
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
||||
const VkRenderPassBeginInfo renderpass_bi{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.renderPass = renderpass,
|
||||
.framebuffer = framebuffer_handle,
|
||||
.renderArea =
|
||||
{
|
||||
.offset = {.x = 0, .y = 0},
|
||||
.extent = render_area,
|
||||
},
|
||||
.clearValueCount = 0,
|
||||
.pClearValues = nullptr,
|
||||
};
|
||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||
});
|
||||
}
|
||||
num_renderpass_images = framebuffer->NumImages();
|
||||
renderpass_images = framebuffer->Images();
|
||||
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||
state.using_dynamic_rendering = use_dynamic_rendering;
|
||||
}
|
||||
|
||||
void Scheduler::RequestOutsideRenderPassOperationContext() {
|
||||
|
|
@ -334,8 +341,9 @@ void Scheduler::EndRenderPass()
|
|||
query_cache->NotifySegment(false);
|
||||
|
||||
Record([num_images = num_renderpass_images,
|
||||
images = renderpass_images,
|
||||
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
|
||||
images = renderpass_images,
|
||||
ranges = renderpass_image_ranges,
|
||||
using_dynamic = state.using_dynamic_rendering](vk::CommandBuffer cmdbuf) {
|
||||
std::array<VkImageMemoryBarrier, 9> barriers;
|
||||
for (size_t i = 0; i < num_images; ++i) {
|
||||
const VkImageSubresourceRange& range = ranges[i];
|
||||
|
|
@ -371,7 +379,11 @@ void Scheduler::EndRenderPass()
|
|||
.subresourceRange = range,
|
||||
};
|
||||
}
|
||||
cmdbuf.EndRenderPass();
|
||||
if (using_dynamic) {
|
||||
cmdbuf.EndRendering();
|
||||
} else {
|
||||
cmdbuf.EndRenderPass();
|
||||
}
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
|
|
@ -384,6 +396,7 @@ void Scheduler::EndRenderPass()
|
|||
});
|
||||
|
||||
state.renderpass = nullptr;
|
||||
state.using_dynamic_rendering = false;
|
||||
num_renderpass_images = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
|
@ -218,6 +218,7 @@ private:
|
|||
bool is_rescaling = false;
|
||||
bool rescaling_defined = false;
|
||||
bool needs_state_enable_refresh = false;
|
||||
bool using_dynamic_rendering = false;
|
||||
};
|
||||
|
||||
void WorkerThread(std::stop_token stop_token);
|
||||
|
|
|
|||
|
|
@ -2384,11 +2384,24 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
RenderPassKey renderpass_key{};
|
||||
s32 num_layers = 1;
|
||||
|
||||
rendering_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.renderArea = {
|
||||
.offset = {0, 0},
|
||||
.extent = render_area,
|
||||
},
|
||||
.layerCount = 1,
|
||||
.viewMask = 0,
|
||||
};
|
||||
|
||||
is_rescaled = is_rescaled_;
|
||||
const auto& resolution = runtime.resolution;
|
||||
|
||||
u32 width = (std::numeric_limits<u32>::max)();
|
||||
u32 height = (std::numeric_limits<u32>::max)();
|
||||
u32 color_attachment_count = 0;
|
||||
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||
const ImageView* const color_buffer = color_buffers[index];
|
||||
if (!color_buffer) {
|
||||
|
|
@ -2406,7 +2419,20 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
image_ranges[num_images] = MakeSubresourceRange(color_buffer);
|
||||
rt_map[index] = num_images;
|
||||
samples = color_buffer->Samples();
|
||||
color_attachment_infos[color_attachment_count] = VkRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.pNext = nullptr,
|
||||
.imageView = color_buffer->RenderTarget(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.resolveMode = VK_RESOLVE_MODE_NONE,
|
||||
.resolveImageView = VK_NULL_HANDLE,
|
||||
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue = {},
|
||||
};
|
||||
++num_images;
|
||||
++color_attachment_count;
|
||||
}
|
||||
const size_t num_colors = attachments.size();
|
||||
if (depth_buffer) {
|
||||
|
|
@ -2424,6 +2450,18 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
++num_images;
|
||||
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
depth_attachment_info = VkRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.pNext = nullptr,
|
||||
.imageView = depth_buffer->RenderTarget(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.resolveMode = VK_RESOLVE_MODE_NONE,
|
||||
.resolveImageView = VK_NULL_HANDLE,
|
||||
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue = {},
|
||||
};
|
||||
} else {
|
||||
renderpass_key.depth_format = PixelFormat::Invalid;
|
||||
}
|
||||
|
|
@ -2433,6 +2471,13 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
|||
render_area.width = (std::min)(render_area.width, width);
|
||||
render_area.height = (std::min)(render_area.height, height);
|
||||
|
||||
rendering_info.layerCount = static_cast<u32>((std::max)(num_layers, 1));
|
||||
rendering_info.renderArea.extent = render_area;
|
||||
rendering_info.colorAttachmentCount = color_attachment_count;
|
||||
rendering_info.pColorAttachments = color_attachment_count > 0 ? color_attachment_infos.data() : nullptr;
|
||||
rendering_info.pDepthAttachment = has_depth ? &depth_attachment_info : nullptr;
|
||||
rendering_info.pStencilAttachment = has_stencil ? &depth_attachment_info : nullptr;
|
||||
|
||||
num_color_buffers = static_cast<u32>(num_colors);
|
||||
framebuffer = runtime.device.GetLogical().CreateFramebuffer({
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
|
@ -169,6 +169,11 @@ public:
|
|||
return renderpass;
|
||||
}
|
||||
|
||||
/// Returns the cached rendering info used for dynamic rendering.
|
||||
[[nodiscard]] const VkRenderingInfo& RenderingInfo() const noexcept {
|
||||
return rendering_info;
|
||||
}
|
||||
|
||||
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
|
||||
return render_area;
|
||||
}
|
||||
|
|
@ -222,6 +227,10 @@ private:
|
|||
bool has_depth{};
|
||||
bool has_stencil{};
|
||||
bool is_rescaled{};
|
||||
|
||||
std::array<VkRenderingAttachmentInfo, NUM_RT> color_attachment_infos{};
|
||||
VkRenderingAttachmentInfo depth_attachment_info{};
|
||||
VkRenderingInfo rendering_info{};
|
||||
};
|
||||
|
||||
class Image : public VideoCommon::ImageBase {
|
||||
|
|
|
|||
|
|
@ -1307,6 +1307,14 @@ void Device::RemoveUnsuitableExtensions() {
|
|||
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
|
||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_dynamic_rendering
|
||||
if (!features.dynamic_rendering.dynamicRendering && extensions.dynamic_rendering) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"VK_KHR_dynamic_rendering reported but dynamicRendering feature not available, disabling");
|
||||
RemoveExtensionFeature(extensions.dynamic_rendering, features.dynamic_rendering,
|
||||
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
// VK_EXT_descriptor_buffer
|
||||
extensions.descriptor_buffer = loaded_extensions.contains(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
|
||||
RemoveExtensionIfUnsuitable(extensions.descriptor_buffer, VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
|||
FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore)
|
||||
|
||||
#define FOR_EACH_VK_FEATURE_1_3(FEATURE) \
|
||||
FEATURE(KHR, DynamicRendering, DYNAMIC_RENDERING, dynamic_rendering) \
|
||||
FEATURE(EXT, ImageRobustness, IMAGE_ROBUSTNESS, image_robustness) \
|
||||
FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \
|
||||
shader_demote_to_helper_invocation) \
|
||||
|
|
@ -356,7 +357,8 @@ public:
|
|||
|
||||
/// Returns true if the device supports VK_KHR_dynamic_rendering.
|
||||
bool IsDynamicRenderingSupported() const {
|
||||
return extensions.dynamic_rendering;
|
||||
return features.dynamic_rendering.dynamicRendering &&
|
||||
(instance_version >= VK_API_VERSION_1_3 || extensions.dynamic_rendering);
|
||||
}
|
||||
|
||||
/// Returns true if ASTC is natively supported.
|
||||
|
|
|
|||
Loading…
Reference in New Issue