Browse Source

[vulkan] Follow-up for the VK_KHR_dynamic_rendering implementation

qcomopts2
CamilleLaVey 1 week ago
committed by Caio Oliveira
parent
commit
480104dc50
No known key found for this signature in database GPG Key ID: AAAE6C7FD4186B0C
  1. 48
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  2. 51
      src/video_core/renderer_vulkan/vk_scheduler.cpp
  3. 3
      src/video_core/renderer_vulkan/vk_scheduler.h
  4. 45
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  5. 11
      src/video_core/renderer_vulkan/vk_texture_cache.h
  6. 8
      src/video_core/vulkan_common/vulkan_device.cpp
  7. 4
      src/video_core/vulkan_common/vulkan_device.h

48
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -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,

51
src/video_core/renderer_vulkan/vk_scheduler.cpp

@ -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;
}

3
src/video_core/renderer_vulkan/vk_scheduler.h

@ -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);

45
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -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,

11
src/video_core/renderer_vulkan/vk_texture_cache.h

@ -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 {

8
src/video_core/vulkan_common/vulkan_device.cpp

@ -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);

4
src/video_core/vulkan_common/vulkan_device.h

@ -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…
Cancel
Save