mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-26 19:37:01 +02:00
[vulkan] Follow-up for the VK_KHR_dynamic_rendering implementation
This commit is contained in:
parent
8932211b70
commit
480104dc50
7 changed files with 146 additions and 24 deletions
|
|
@ -25,6 +25,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||||
#include "video_core/shader_notify.h"
|
#include "video_core/shader_notify.h"
|
||||||
#include "video_core/texture_cache/texture_cache.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/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/gpu_logging/gpu_logging.h"
|
#include "video_core/gpu_logging/gpu_logging.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
|
@ -138,6 +139,10 @@ RenderPassKey MakeRenderPassKey(const FixedPipelineState& state) {
|
||||||
return key;
|
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 NumAttachments(const FixedPipelineState& state) {
|
||||||
size_t num{};
|
size_t num{};
|
||||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
|
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;
|
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(
|
pipeline = device.GetLogical().CreateGraphicsPipeline(
|
||||||
{
|
{
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = use_dynamic_rendering ? &pipeline_rendering_ci : nullptr,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
.stageCount = static_cast<u32>(shader_stages.size()),
|
.stageCount = static_cast<u32>(shader_stages.size()),
|
||||||
.pStages = shader_stages.data(),
|
.pStages = shader_stages.data(),
|
||||||
|
|
@ -959,7 +1003,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.pColorBlendState = &color_blend_ci,
|
.pColorBlendState = &color_blend_ci,
|
||||||
.pDynamicState = &dynamic_state_ci,
|
.pDynamicState = &dynamic_state_ci,
|
||||||
.layout = *pipeline_layout,
|
.layout = *pipeline_layout,
|
||||||
.renderPass = render_pass,
|
.renderPass = use_dynamic_rendering ? VK_NULL_HANDLE : render_pass,
|
||||||
.subpass = 0,
|
.subpass = 0,
|
||||||
.basePipelineHandle = nullptr,
|
.basePipelineHandle = nullptr,
|
||||||
.basePipelineIndex = 0,
|
.basePipelineIndex = 0,
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
||||||
const VkRenderPass renderpass = framebuffer->RenderPass();
|
const VkRenderPass renderpass = framebuffer->RenderPass();
|
||||||
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
|
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
|
||||||
const VkExtent2D render_area = framebuffer->RenderArea();
|
const VkExtent2D render_area = framebuffer->RenderArea();
|
||||||
|
const bool use_dynamic_rendering = device.IsDynamicRenderingSupported();
|
||||||
if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer &&
|
if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer &&
|
||||||
render_area.width == state.render_area.width &&
|
render_area.width == state.render_area.width &&
|
||||||
render_area.height == state.render_area.height) {
|
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);
|
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
if (use_dynamic_rendering) {
|
||||||
const VkRenderPassBeginInfo renderpass_bi{
|
const VkRenderingInfo rendering_info = framebuffer->RenderingInfo();
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
Record([rendering_info](vk::CommandBuffer cmdbuf) { cmdbuf.BeginRendering(&rendering_info); });
|
||||||
.pNext = nullptr,
|
} else {
|
||||||
.renderPass = renderpass,
|
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
|
||||||
.framebuffer = framebuffer_handle,
|
const VkRenderPassBeginInfo renderpass_bi{
|
||||||
.renderArea =
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
{
|
.pNext = nullptr,
|
||||||
.offset = {.x = 0, .y = 0},
|
.renderPass = renderpass,
|
||||||
.extent = render_area,
|
.framebuffer = framebuffer_handle,
|
||||||
},
|
.renderArea =
|
||||||
.clearValueCount = 0,
|
{
|
||||||
.pClearValues = nullptr,
|
.offset = {.x = 0, .y = 0},
|
||||||
};
|
.extent = render_area,
|
||||||
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
},
|
||||||
});
|
.clearValueCount = 0,
|
||||||
|
.pClearValues = nullptr,
|
||||||
|
};
|
||||||
|
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
});
|
||||||
|
}
|
||||||
num_renderpass_images = framebuffer->NumImages();
|
num_renderpass_images = framebuffer->NumImages();
|
||||||
renderpass_images = framebuffer->Images();
|
renderpass_images = framebuffer->Images();
|
||||||
renderpass_image_ranges = framebuffer->ImageRanges();
|
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||||
|
state.using_dynamic_rendering = use_dynamic_rendering;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::RequestOutsideRenderPassOperationContext() {
|
void Scheduler::RequestOutsideRenderPassOperationContext() {
|
||||||
|
|
@ -334,8 +341,9 @@ void Scheduler::EndRenderPass()
|
||||||
query_cache->NotifySegment(false);
|
query_cache->NotifySegment(false);
|
||||||
|
|
||||||
Record([num_images = num_renderpass_images,
|
Record([num_images = num_renderpass_images,
|
||||||
images = renderpass_images,
|
images = renderpass_images,
|
||||||
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
|
ranges = renderpass_image_ranges,
|
||||||
|
using_dynamic = state.using_dynamic_rendering](vk::CommandBuffer cmdbuf) {
|
||||||
std::array<VkImageMemoryBarrier, 9> barriers;
|
std::array<VkImageMemoryBarrier, 9> barriers;
|
||||||
for (size_t i = 0; i < num_images; ++i) {
|
for (size_t i = 0; i < num_images; ++i) {
|
||||||
const VkImageSubresourceRange& range = ranges[i];
|
const VkImageSubresourceRange& range = ranges[i];
|
||||||
|
|
@ -371,7 +379,11 @@ void Scheduler::EndRenderPass()
|
||||||
.subresourceRange = range,
|
.subresourceRange = range,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
cmdbuf.EndRenderPass();
|
if (using_dynamic) {
|
||||||
|
cmdbuf.EndRendering();
|
||||||
|
} else {
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
}
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
|
@ -384,6 +396,7 @@ void Scheduler::EndRenderPass()
|
||||||
});
|
});
|
||||||
|
|
||||||
state.renderpass = nullptr;
|
state.renderpass = nullptr;
|
||||||
|
state.using_dynamic_rendering = false;
|
||||||
num_renderpass_images = 0;
|
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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -218,6 +218,7 @@ private:
|
||||||
bool is_rescaling = false;
|
bool is_rescaling = false;
|
||||||
bool rescaling_defined = false;
|
bool rescaling_defined = false;
|
||||||
bool needs_state_enable_refresh = false;
|
bool needs_state_enable_refresh = false;
|
||||||
|
bool using_dynamic_rendering = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void WorkerThread(std::stop_token stop_token);
|
void WorkerThread(std::stop_token stop_token);
|
||||||
|
|
|
||||||
|
|
@ -2384,11 +2384,24 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
||||||
RenderPassKey renderpass_key{};
|
RenderPassKey renderpass_key{};
|
||||||
s32 num_layers = 1;
|
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_;
|
is_rescaled = is_rescaled_;
|
||||||
const auto& resolution = runtime.resolution;
|
const auto& resolution = runtime.resolution;
|
||||||
|
|
||||||
u32 width = (std::numeric_limits<u32>::max)();
|
u32 width = (std::numeric_limits<u32>::max)();
|
||||||
u32 height = (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) {
|
for (size_t index = 0; index < NUM_RT; ++index) {
|
||||||
const ImageView* const color_buffer = color_buffers[index];
|
const ImageView* const color_buffer = color_buffers[index];
|
||||||
if (!color_buffer) {
|
if (!color_buffer) {
|
||||||
|
|
@ -2406,7 +2419,20 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
||||||
image_ranges[num_images] = MakeSubresourceRange(color_buffer);
|
image_ranges[num_images] = MakeSubresourceRange(color_buffer);
|
||||||
rt_map[index] = num_images;
|
rt_map[index] = num_images;
|
||||||
samples = color_buffer->Samples();
|
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;
|
++num_images;
|
||||||
|
++color_attachment_count;
|
||||||
}
|
}
|
||||||
const size_t num_colors = attachments.size();
|
const size_t num_colors = attachments.size();
|
||||||
if (depth_buffer) {
|
if (depth_buffer) {
|
||||||
|
|
@ -2424,6 +2450,18 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
|
||||||
++num_images;
|
++num_images;
|
||||||
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||||
has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_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 {
|
} else {
|
||||||
renderpass_key.depth_format = PixelFormat::Invalid;
|
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.width = (std::min)(render_area.width, width);
|
||||||
render_area.height = (std::min)(render_area.height, height);
|
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);
|
num_color_buffers = static_cast<u32>(num_colors);
|
||||||
framebuffer = runtime.device.GetLogical().CreateFramebuffer({
|
framebuffer = runtime.device.GetLogical().CreateFramebuffer({
|
||||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
.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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -169,6 +169,11 @@ public:
|
||||||
return renderpass;
|
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 {
|
[[nodiscard]] VkExtent2D RenderArea() const noexcept {
|
||||||
return render_area;
|
return render_area;
|
||||||
}
|
}
|
||||||
|
|
@ -222,6 +227,10 @@ private:
|
||||||
bool has_depth{};
|
bool has_depth{};
|
||||||
bool has_stencil{};
|
bool has_stencil{};
|
||||||
bool is_rescaled{};
|
bool is_rescaled{};
|
||||||
|
|
||||||
|
std::array<VkRenderingAttachmentInfo, NUM_RT> color_attachment_infos{};
|
||||||
|
VkRenderingAttachmentInfo depth_attachment_info{};
|
||||||
|
VkRenderingInfo rendering_info{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Image : public VideoCommon::ImageBase {
|
class Image : public VideoCommon::ImageBase {
|
||||||
|
|
|
||||||
|
|
@ -1307,6 +1307,14 @@ void Device::RemoveUnsuitableExtensions() {
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
|
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
|
||||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
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
|
// VK_EXT_descriptor_buffer
|
||||||
extensions.descriptor_buffer = loaded_extensions.contains(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
|
extensions.descriptor_buffer = loaded_extensions.contains(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
|
||||||
RemoveExtensionIfUnsuitable(extensions.descriptor_buffer, 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)
|
FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore)
|
||||||
|
|
||||||
#define FOR_EACH_VK_FEATURE_1_3(FEATURE) \
|
#define FOR_EACH_VK_FEATURE_1_3(FEATURE) \
|
||||||
|
FEATURE(KHR, DynamicRendering, DYNAMIC_RENDERING, dynamic_rendering) \
|
||||||
FEATURE(EXT, ImageRobustness, IMAGE_ROBUSTNESS, image_robustness) \
|
FEATURE(EXT, ImageRobustness, IMAGE_ROBUSTNESS, image_robustness) \
|
||||||
FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \
|
FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \
|
||||||
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.
|
/// Returns true if the device supports VK_KHR_dynamic_rendering.
|
||||||
bool IsDynamicRenderingSupported() const {
|
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.
|
/// Returns true if ASTC is natively supported.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue