Browse Source

[TEST] depth stencil resolve implementation + fixes

temporary-branch
CamilleLaVey 4 days ago
parent
commit
6e48eeb09c
  1. 43
      src/video_core/renderer_vulkan/vk_scheduler.cpp
  2. 3
      src/video_core/renderer_vulkan/vk_scheduler.h
  3. 118
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  4. 18
      src/video_core/renderer_vulkan/vk_texture_cache.h
  5. 5
      src/video_core/vulkan_common/vulkan_device.cpp
  6. 37
      src/video_core/vulkan_common/vulkan_device.h

43
src/video_core/renderer_vulkan/vk_scheduler.cpp

@ -107,6 +107,9 @@ void Scheduler::BeginDynamicRendering(const Framebuffer* framebuffer, const Defe
state.attachment_views = attachment_views;
state.color_resolve_views = framebuffer->ColorResolveAttachments();
state.color_resolve_modes = framebuffer->ColorResolveModes();
state.depth_resolve_view = framebuffer->DepthResolveAttachment();
state.depth_resolve_mode = framebuffer->DepthResolveMode();
state.stencil_resolve_mode = framebuffer->StencilResolveMode();
state.discards_msaa_color = framebuffer->DiscardsMsaaColor();
state.discards_msaa_depth = framebuffer->DiscardsMsaaDepth();
state.render_area = render_area;
@ -453,9 +456,13 @@ void Scheduler::RecordDynamicBegin(const DeferredClear* clear) {
const bool ds_clear = clear != nullptr && clear->depth_stencil;
const VkClearValue ds_clear_value = clear ? clear->depth_stencil_value : VkClearValue{};
const bool ds_discard = state.discards_msaa_depth;
const VkImageView ds_resolve_view = state.depth_resolve_view;
const VkResolveModeFlagBits depth_resolve_mode = state.depth_resolve_mode;
const VkResolveModeFlagBits stencil_resolve_mode = state.stencil_resolve_mode;
Record([views, resolve_views, resolve_modes, num_color, has_depth, has_stencil, layers,
render_area, color_clear_mask, color_discard_mask, color_clear_values, ds_clear,
ds_clear_value, ds_discard](vk::CommandBuffer cmdbuf) {
ds_clear_value, ds_discard, ds_resolve_view, depth_resolve_mode,
stencil_resolve_mode](vk::CommandBuffer cmdbuf) {
std::array<VkRenderingAttachmentInfo, VideoCommon::NUM_RT> color_infos{};
for (u32 index = 0; index < num_color; ++index) {
const bool clear_slot = ((color_clear_mask >> index) & 1u) != 0;
@ -477,17 +484,37 @@ void Scheduler::RecordDynamicBegin(const DeferredClear* clear) {
.clearValue = clear_slot ? color_clear_values[index] : VkClearValue{},
};
}
const bool has_ds_resolve = ds_resolve_view != VK_NULL_HANDLE;
const VkAttachmentLoadOp ds_load_op = ds_clear ? VK_ATTACHMENT_LOAD_OP_CLEAR
: ds_discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE
: VK_ATTACHMENT_LOAD_OP_LOAD;
const VkAttachmentStoreOp ds_store_op =
ds_discard ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
const VkRenderingAttachmentInfo depth_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[8],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.resolveImageView = VK_NULL_HANDLE,
.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = ds_clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = ds_discard ? VK_ATTACHMENT_STORE_OP_DONT_CARE
: VK_ATTACHMENT_STORE_OP_STORE,
.resolveMode = has_ds_resolve ? depth_resolve_mode : VK_RESOLVE_MODE_NONE,
.resolveImageView = has_ds_resolve ? ds_resolve_view : VK_NULL_HANDLE,
.resolveImageLayout =
has_ds_resolve ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = ds_load_op,
.storeOp = ds_store_op,
.clearValue = ds_clear ? ds_clear_value : VkClearValue{},
};
// Stencil gets its own struct because its resolve mode may differ from depth's.
const VkRenderingAttachmentInfo stencil_info{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = views[8],
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
.resolveMode = has_ds_resolve ? stencil_resolve_mode : VK_RESOLVE_MODE_NONE,
.resolveImageView = has_ds_resolve ? ds_resolve_view : VK_NULL_HANDLE,
.resolveImageLayout =
has_ds_resolve ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.loadOp = ds_load_op,
.storeOp = ds_store_op,
.clearValue = ds_clear ? ds_clear_value : VkClearValue{},
};
const VkRenderingInfo rendering_info{
@ -504,7 +531,7 @@ void Scheduler::RecordDynamicBegin(const DeferredClear* clear) {
.colorAttachmentCount = num_color,
.pColorAttachments = color_infos.data(),
.pDepthAttachment = has_depth ? &depth_info : nullptr,
.pStencilAttachment = has_stencil ? &depth_info : nullptr,
.pStencilAttachment = has_stencil ? &stencil_info : nullptr,
};
cmdbuf.BeginRendering(rendering_info);
});

3
src/video_core/renderer_vulkan/vk_scheduler.h

@ -270,6 +270,9 @@ private:
std::array<VkImageView, 9> attachment_views{};
std::array<VkImageView, 8> color_resolve_views{};
std::array<VkResolveModeFlagBits, 8> color_resolve_modes{};
VkImageView depth_resolve_view{};
VkResolveModeFlagBits depth_resolve_mode = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits stencil_resolve_mode = VK_RESOLVE_MODE_NONE;
VkExtent2D render_area = {0, 0};
GraphicsPipeline* graphics_pipeline = nullptr;
bool rendering = false;

118
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@ -1005,7 +1005,10 @@ VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
}
VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, VkFormat format,
VkExtent2D extent, u32 layers) {
VkExtent2D extent, u32 layers,
VkImageAspectFlags aspect) {
const bool is_depth_stencil =
(aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0;
ResolveShadow& shadow = resolve_shadows[msaa_image];
if (shadow.image && shadow.format == format && shadow.extent.width == extent.width &&
shadow.extent.height == extent.height && shadow.layers == layers) {
@ -1023,8 +1026,9 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
.arrayLayers = layers,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
.usage = (is_depth_stencil ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) |
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@ -1039,7 +1043,7 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
.format = format,
.components{},
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
@ -1052,28 +1056,33 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
shadow.up_to_date = true;
if (device.IsKhrDynamicRenderingSupported()) {
scheduler.RecordWithUploadBuffer(
[image = *shadow.image, layers](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
[image = *shadow.image, layers, aspect, is_depth_stencil](
vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccessMask = is_depth_stencil
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
: VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = layers,
},
};
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
barrier);
upload_cmdbuf.PipelineBarrier(
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
is_depth_stencil ? VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
: VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, barrier);
});
}
return *shadow.view;
@ -1668,18 +1677,6 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
std::span<const VideoCommon::ImageCopy> copies) {
const bool msaa_to_non_msaa = src.info.num_samples > 1 && dst.info.num_samples == 1;
const u32 num_samples = msaa_to_non_msaa ? src.info.num_samples : dst.info.num_samples;
if (dst.AspectMask() != VK_IMAGE_ASPECT_COLOR_BIT ||
VideoCore::Surface::IsPixelFormatInteger(dst.info.format)) {
const u64 key{(static_cast<u64>(dst.AspectMask()) << 32) |
static_cast<u64>(dst.info.format)};
if (unsupported_msaa_resolves.insert(key).second) {
LOG_WARNING(Render_Vulkan,
"MSAA resolve unsupported: format={}, aspect={:#x}, samples {}->{}",
dst.info.format, dst.AspectMask(), src.info.num_samples,
dst.info.num_samples);
}
return;
}
if (ENABLE_MSAA_RESOLVE_CONSUME && msaa_to_non_msaa && copies.size() == 1 &&
src.info.format == dst.info.format) {
const VideoCommon::ImageCopy& copy = copies.front();
@ -1690,16 +1687,19 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
static_cast<u32>(copy.extent.height) <= shadow->extent.height) {
const VkImage shadow_image = *shadow->image;
const VkImage dst_image = dst.Handle();
const VkImageAspectFlags aspect = dst.AspectMask();
const bool is_depth_stencil =
(aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0;
const VkImageCopy region{
.srcSubresource{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.aspectMask = aspect,
.mipLevel = 0,
.baseArrayLayer = static_cast<u32>(copy.src_subresource.base_layer),
.layerCount = static_cast<u32>(copy.src_subresource.num_layers),
},
.srcOffset = {0, 0, 0},
.dstSubresource{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.aspectMask = aspect,
.mipLevel = static_cast<u32>(copy.dst_subresource.base_level),
.baseArrayLayer = static_cast<u32>(copy.dst_subresource.base_layer),
.layerCount = static_cast<u32>(copy.dst_subresource.num_layers),
@ -1708,34 +1708,38 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
.extent = {copy.extent.width, copy.extent.height, 1},
};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([shadow_image, dst_image, region](vk::CommandBuffer cmdbuf) {
scheduler.Record([shadow_image, dst_image, region, aspect,
is_depth_stencil](vk::CommandBuffer cmdbuf) {
const VkAccessFlags attachment_write =
is_depth_stencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
: VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
const std::array pre_barriers{
VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.srcAccessMask = attachment_write,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = shadow_image,
.subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
.subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS},
},
VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT,
.srcAccessMask =
VK_ACCESS_SHADER_WRITE_BIT | attachment_write |
VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
.subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS},
},
};
@ -1750,7 +1754,7 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = shadow_image,
.subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
.subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS},
},
VkImageMemoryBarrier{
@ -1760,17 +1764,20 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
.subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
.subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS},
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, nullptr,
pre_barriers);
@ -1783,6 +1790,18 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
return;
}
}
if (dst.AspectMask() != VK_IMAGE_ASPECT_COLOR_BIT ||
VideoCore::Surface::IsPixelFormatInteger(dst.info.format)) {
const u64 key{(static_cast<u64>(dst.AspectMask()) << 32) |
static_cast<u64>(dst.info.format)};
if (unsupported_msaa_resolves.insert(key).second) {
LOG_WARNING(Render_Vulkan,
"MSAA resolve unsupported: format={}, aspect={:#x}, samples {}->{}",
dst.info.format, dst.AspectMask(), src.info.num_samples,
dst.info.num_samples);
}
return;
}
blit_image_helper.CopyMSAA(render_pass_cache, dst.Handle(), dst.info.format, src.Handle(),
src.info.format, num_samples, copies, msaa_to_non_msaa);
}
@ -2806,10 +2825,21 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0 && runtime.device.IsTiler();
renderpass_key.resolve_color = do_resolve_color;
const VkResolveModeFlagBits depth_mode = runtime.device.GetDepthResolveMode();
const VkResolveModeFlagBits stencil_mode = runtime.device.GetStencilResolveMode();
const bool resolve_modes_compatible =
depth_mode != VK_RESOLVE_MODE_NONE &&
(!has_stencil || (stencil_mode != VK_RESOLVE_MODE_NONE &&
(runtime.device.IsIndependentResolveSupported() ||
depth_mode == stencil_mode)));
const bool do_resolve_depth =
samples != VK_SAMPLE_COUNT_1_BIT && has_depth && runtime.device.IsTiler() &&
runtime.device.IsKhrDynamicRenderingSupported() && resolve_modes_compatible;
discard_msaa_color =
ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color;
discard_msaa_depth = ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_DEPTH_DISCARD &&
samples != VK_SAMPLE_COUNT_1_BIT && has_depth && runtime.device.IsTiler();
discard_msaa_depth =
ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_DEPTH_DISCARD && do_resolve_depth;
render_pass_key = renderpass_key;
render_pass_cache = &runtime.render_pass_cache;
@ -2831,7 +2861,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
if (ENABLE_MSAA_RESOLVE_CONSUME) {
const VkImage msaa_image = images[rt_map[index]];
const VkImageView shadow_view = runtime.GetOrCreateResolveShadow(
msaa_image, vk_format, render_area, layers);
msaa_image, vk_format, render_area, layers, VK_IMAGE_ASPECT_COLOR_BIT);
color_resolve_attachments[index] = shadow_view;
attachments.push_back(shadow_view);
continue;
@ -2905,6 +2935,22 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
}
}
if (do_resolve_depth && depth_buffer != nullptr) {
const u32 layers = static_cast<u32>((std::max)(num_layers, 1));
VkImageAspectFlags aspect = 0;
if (has_depth) {
aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (has_stencil) {
aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
depth_resolve_attachment =
runtime.GetOrCreateResolveShadow(depth_buffer->ImageHandle(), depth_attachment_format,
render_area, layers, aspect);
depth_resolve_mode = depth_mode;
stencil_resolve_mode = has_stencil ? stencil_mode : VK_RESOLVE_MODE_NONE;
}
num_color_buffers = static_cast<u32>(num_colors);
layer_count = static_cast<u32>((std::max)(num_layers, 1));
if (runtime.device.IsKhrDynamicRenderingSupported()) {

18
src/video_core/renderer_vulkan/vk_texture_cache.h

@ -133,7 +133,8 @@ public:
};
[[nodiscard]] VkImageView GetOrCreateResolveShadow(VkImage msaa_image, VkFormat format,
VkExtent2D extent, u32 layers);
VkExtent2D extent, u32 layers,
VkImageAspectFlags aspect);
[[nodiscard]] const ResolveShadow* GetValidResolveShadow(VkImage msaa_image) const;
@ -233,6 +234,18 @@ public:
return depth_attachment;
}
[[nodiscard]] VkImageView DepthResolveAttachment() const noexcept {
return depth_resolve_attachment;
}
[[nodiscard]] VkResolveModeFlagBits DepthResolveMode() const noexcept {
return depth_resolve_mode;
}
[[nodiscard]] VkResolveModeFlagBits StencilResolveMode() const noexcept {
return stencil_resolve_mode;
}
[[nodiscard]] VkFormat DepthAttachmentFormat() const noexcept {
return depth_attachment_format;
}
@ -312,6 +325,9 @@ private:
std::array<VkImageView, NUM_RT> color_resolve_attachments{};
std::array<VkResolveModeFlagBits, NUM_RT> color_resolve_modes{};
VkImageView depth_attachment{};
VkImageView depth_resolve_attachment{};
VkResolveModeFlagBits depth_resolve_mode = VK_RESOLVE_MODE_NONE;
VkResolveModeFlagBits stencil_resolve_mode = VK_RESOLVE_MODE_NONE;
VkFormat depth_attachment_format = VK_FORMAT_UNDEFINED;
u32 num_color_attachments = 0;
u32 layer_count = 1;

5
src/video_core/vulkan_common/vulkan_device.cpp

@ -1120,6 +1120,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR;
SetNext(next, properties.maintenance5);
}
if (instance_version >= VK_API_VERSION_1_2) {
properties.depth_stencil_resolve.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
SetNext(next, properties.depth_stencil_resolve);
}
// Perform the property fetch.
physical.GetProperties2(properties2);

37
src/video_core/vulkan_common/vulkan_device.h

@ -1006,6 +1006,26 @@ FN_MAX_LIMIT_LIST
return ENABLE_DYNAMIC_RENDERING && extensions.dynamic_rendering;
}
/// Returns the resolve mode to use for multisampled depth.
VkResolveModeFlagBits GetDepthResolveMode() const {
return PickResolveMode(properties.depth_stencil_resolve.supportedDepthResolveModes);
}
/// Same as GetDepthResolveMode, for the stencil aspect.
VkResolveModeFlagBits GetStencilResolveMode() const {
return PickResolveMode(properties.depth_stencil_resolve.supportedStencilResolveModes);
}
/// Returns true if depth and stencil may resolve with independent modes.
bool IsIndependentResolveSupported() const {
return properties.depth_stencil_resolve.independentResolve == VK_TRUE;
}
/// Returns true if one aspect may resolve while the other does not.
bool IsIndependentResolveNoneSupported() const {
return properties.depth_stencil_resolve.independentResolveNone == VK_TRUE;
}
/// Returns true if the device supports VK_KHR_maintenance4.
bool IsKhrMaintenance4Supported() const {
return extensions.maintenance4;
@ -1087,6 +1107,22 @@ FN_MAX_LIMIT_LIST
void ShutdownGPULogging();
private:
/// Picks a usable resolve mode out of a supported-modes mask. SAMPLE_ZERO is preferred because
/// it is the only mode the spec guarantees whenever any depth/stencil resolve is supported,
/// and averaging depth samples is not meaningful for depth testing anyway.
static VkResolveModeFlagBits PickResolveMode(VkResolveModeFlags supported) {
if ((supported & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) != 0) {
return VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
}
if ((supported & VK_RESOLVE_MODE_MIN_BIT) != 0) {
return VK_RESOLVE_MODE_MIN_BIT;
}
if ((supported & VK_RESOLVE_MODE_MAX_BIT) != 0) {
return VK_RESOLVE_MODE_MAX_BIT;
}
return VK_RESOLVE_MODE_NONE;
}
/// Checks if the physical device is suitable and configures the object state
/// with all necessary info about its properties.
bool GetSuitability(bool requires_swapchain);
@ -1176,6 +1212,7 @@ private:
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{};
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};
VkPhysicalDeviceProperties properties{};
};

Loading…
Cancel
Save