mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-08 14:39:00 +00:00
[TEST] MSAA uploads
This commit is contained in:
@@ -34,6 +34,8 @@ set(SHADER_FILES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth.frag
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth_stencil.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/full_screen_triangle.vert
|
${CMAKE_CURRENT_SOURCE_DIR}/full_screen_triangle.vert
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/fxaa.frag
|
${CMAKE_CURRENT_SOURCE_DIR}/fxaa.frag
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(binding = 0) uniform sampler2D img_in;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConstants {
|
||||||
|
ivec2 dst_offset;
|
||||||
|
ivec2 src_offset;
|
||||||
|
ivec2 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
||||||
|
const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x);
|
||||||
|
const ivec2 coord = msaa_coord * scale + sample_offset + src_offset;
|
||||||
|
gl_FragDepth = texelFetch(img_in, coord, 0).r;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#version 450 core
|
||||||
|
#extension GL_ARB_shader_stencil_export : require
|
||||||
|
|
||||||
|
layout(binding = 0) uniform sampler2D depth_tex;
|
||||||
|
layout(binding = 1) uniform usampler2D stencil_tex;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConstants {
|
||||||
|
ivec2 dst_offset;
|
||||||
|
ivec2 src_offset;
|
||||||
|
ivec2 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset;
|
||||||
|
const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x);
|
||||||
|
const ivec2 coord = msaa_coord * scale + sample_offset + src_offset;
|
||||||
|
gl_FragDepth = texelFetch(depth_tex, coord, 0).r;
|
||||||
|
gl_FragStencilRefARB = int(texelFetch(stencil_tex, coord, 0).r);
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
|
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_frag_spv.h"
|
#include "video_core/host_shaders/convert_msaa_to_non_msaa_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_frag_spv.h"
|
#include "video_core/host_shaders/convert_non_msaa_to_msaa_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/convert_non_msaa_to_msaa_depth_frag_spv.h"
|
||||||
|
#include "video_core/host_shaders/convert_non_msaa_to_msaa_depth_stencil_frag_spv.h"
|
||||||
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
|
#include "video_core/host_shaders/convert_s8d24_to_abgr8_frag_spv.h"
|
||||||
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
|
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
|
||||||
@@ -519,7 +521,8 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::ImageView MakeMSAACopyView(const vk::Device& device, VkImage image,
|
[[nodiscard]] vk::ImageView MakeMSAACopyView(const vk::Device& device, VkImage image,
|
||||||
VkFormat format, u32 base_level) {
|
VkFormat format, u32 base_level,
|
||||||
|
VkImageAspectFlags aspect_mask) {
|
||||||
return device.CreateImageView(VkImageViewCreateInfo{
|
return device.CreateImageView(VkImageViewCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -534,7 +537,7 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
|
|||||||
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
},
|
},
|
||||||
.subresourceRange{
|
.subresourceRange{
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
.aspectMask = aspect_mask,
|
||||||
.baseMipLevel = base_level,
|
.baseMipLevel = base_level,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
@@ -586,6 +589,10 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
|
|||||||
msaa_copy_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
msaa_copy_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
||||||
one_texture_set_layout.address(),
|
one_texture_set_layout.address(),
|
||||||
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
||||||
|
msaa_copy_depth_stencil_pipeline_layout(
|
||||||
|
device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
|
||||||
|
two_textures_set_layout.address(),
|
||||||
|
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(MSAACopyPushConstants)>))),
|
||||||
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
|
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
|
||||||
blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)),
|
blit_color_to_color_frag(BuildShader(device, BLIT_COLOR_FLOAT_FRAG_SPV)),
|
||||||
blit_color_msaa_frag(BuildShader(device, BLIT_COLOR_MSAA_FRAG_SPV)),
|
blit_color_msaa_frag(BuildShader(device, BLIT_COLOR_MSAA_FRAG_SPV)),
|
||||||
@@ -610,6 +617,12 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
|
|||||||
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
|
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
|
||||||
convert_msaa_to_non_msaa_frag(BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_FRAG_SPV)),
|
convert_msaa_to_non_msaa_frag(BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_FRAG_SPV)),
|
||||||
convert_non_msaa_to_msaa_frag(BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_FRAG_SPV)),
|
convert_non_msaa_to_msaa_frag(BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_FRAG_SPV)),
|
||||||
|
convert_non_msaa_to_msaa_depth_frag(
|
||||||
|
BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_DEPTH_FRAG_SPV)),
|
||||||
|
convert_non_msaa_to_msaa_depth_stencil_frag(
|
||||||
|
device.IsExtShaderStencilExportSupported()
|
||||||
|
? BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_DEPTH_STENCIL_FRAG_SPV)
|
||||||
|
: vk::ShaderModule{}),
|
||||||
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
|
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
|
||||||
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
|
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
|
||||||
|
|
||||||
@@ -920,10 +933,12 @@ void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_i
|
|||||||
ASSERT(copy.dst_subresource.num_layers == 1);
|
ASSERT(copy.dst_subresource.num_layers == 1);
|
||||||
vk::ImageView src_view =
|
vk::ImageView src_view =
|
||||||
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format,
|
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format,
|
||||||
static_cast<u32>(copy.src_subresource.base_level));
|
static_cast<u32>(copy.src_subresource.base_level),
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
vk::ImageView dst_view =
|
vk::ImageView dst_view =
|
||||||
MakeMSAACopyView(device.GetLogical(), dst_image, dst_vk_format,
|
MakeMSAACopyView(device.GetLogical(), dst_image, dst_vk_format,
|
||||||
static_cast<u32>(copy.dst_subresource.base_level));
|
static_cast<u32>(copy.dst_subresource.base_level),
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
const VkOffset2D dst_offset{copy.dst_offset.x, copy.dst_offset.y};
|
const VkOffset2D dst_offset{copy.dst_offset.x, copy.dst_offset.y};
|
||||||
const VkExtent2D dst_extent{copy.extent.width, copy.extent.height};
|
const VkExtent2D dst_extent{copy.extent.width, copy.extent.height};
|
||||||
const VkRect2D render_area{
|
const VkRect2D render_area{
|
||||||
@@ -1417,6 +1432,198 @@ VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPas
|
|||||||
return *pipelines.back();
|
return *pipelines.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image,
|
||||||
|
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
||||||
|
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
||||||
|
std::span<const VideoCommon::ImageCopy> copies,
|
||||||
|
bool copy_stencil) {
|
||||||
|
while (!msaa_copy_resources.empty() && scheduler.IsFree(msaa_copy_resources.front().tick)) {
|
||||||
|
msaa_copy_resources.pop_front();
|
||||||
|
}
|
||||||
|
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(num_samples));
|
||||||
|
const s32 scale_x = 1 << samples_x;
|
||||||
|
const s32 scale_y = 1 << samples_y;
|
||||||
|
const VkSampleCountFlagBits samples = SampleCountFlag(num_samples);
|
||||||
|
RenderPassKey renderpass_key{};
|
||||||
|
renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
|
||||||
|
renderpass_key.depth_format = dst_format;
|
||||||
|
renderpass_key.samples = samples;
|
||||||
|
const VkRenderPass renderpass = render_pass_cache.Get(renderpass_key);
|
||||||
|
const MSAACopyPipelineKey key{
|
||||||
|
.renderpass = renderpass,
|
||||||
|
.samples = samples,
|
||||||
|
.msaa_to_non_msaa = false,
|
||||||
|
};
|
||||||
|
const VkPipeline pipeline = FindOrEmplaceMSAACopyDepthPipeline(key, copy_stencil);
|
||||||
|
const VkPipelineLayout layout = copy_stencil ? *msaa_copy_depth_stencil_pipeline_layout
|
||||||
|
: *msaa_copy_pipeline_layout;
|
||||||
|
const VkSampler sampler = *nearest_sampler;
|
||||||
|
const VkFormat src_vk_format =
|
||||||
|
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format;
|
||||||
|
const VkFormat dst_vk_format =
|
||||||
|
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format;
|
||||||
|
const VkImageAspectFlags attachment_aspect =
|
||||||
|
VideoCore::Surface::GetFormatType(dst_format) ==
|
||||||
|
VideoCore::Surface::SurfaceType::DepthStencil
|
||||||
|
? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
|
||||||
|
: VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
for (const VideoCommon::ImageCopy& copy : copies) {
|
||||||
|
ASSERT(copy.src_subresource.base_layer == 0);
|
||||||
|
ASSERT(copy.src_subresource.num_layers == 1);
|
||||||
|
ASSERT(copy.dst_subresource.base_layer == 0);
|
||||||
|
ASSERT(copy.dst_subresource.num_layers == 1);
|
||||||
|
vk::ImageView src_view =
|
||||||
|
MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format,
|
||||||
|
static_cast<u32>(copy.src_subresource.base_level),
|
||||||
|
VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||||
|
vk::ImageView src_stencil_view =
|
||||||
|
copy_stencil ? MakeMSAACopyView(device.GetLogical(), src_image, src_vk_format,
|
||||||
|
static_cast<u32>(copy.src_subresource.base_level),
|
||||||
|
VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||||
|
: vk::ImageView{};
|
||||||
|
vk::ImageView dst_view =
|
||||||
|
MakeMSAACopyView(device.GetLogical(), dst_image, dst_vk_format,
|
||||||
|
static_cast<u32>(copy.dst_subresource.base_level),
|
||||||
|
attachment_aspect);
|
||||||
|
const VkOffset2D dst_offset{copy.dst_offset.x, copy.dst_offset.y};
|
||||||
|
const VkExtent2D dst_extent{copy.extent.width, copy.extent.height};
|
||||||
|
const VkRect2D render_area{
|
||||||
|
.offset = dst_offset,
|
||||||
|
.extent = dst_extent,
|
||||||
|
};
|
||||||
|
vk::Framebuffer framebuffer = device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.renderPass = renderpass,
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.pAttachments = dst_view.address(),
|
||||||
|
.width = static_cast<u32>(dst_offset.x) + dst_extent.width,
|
||||||
|
.height = static_cast<u32>(dst_offset.y) + dst_extent.height,
|
||||||
|
.layers = 1,
|
||||||
|
});
|
||||||
|
const MSAACopyPushConstants push_constants{
|
||||||
|
.dst_offset = {dst_offset.x, dst_offset.y},
|
||||||
|
.src_offset = {copy.src_offset.x, copy.src_offset.y},
|
||||||
|
.scale = {scale_x, scale_y},
|
||||||
|
};
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
const VkImageView src_stencil_handle = copy_stencil ? *src_stencil_view : VK_NULL_HANDLE;
|
||||||
|
scheduler.Record([this, pipeline, layout, sampler, renderpass,
|
||||||
|
framebuffer_handle = *framebuffer, src_view_handle = *src_view,
|
||||||
|
src_stencil_handle, src = src_image, dst = dst_image, render_area,
|
||||||
|
attachment_aspect, push_constants](vk::CommandBuffer cmdbuf) {
|
||||||
|
const VkImageSubresourceRange src_range{
|
||||||
|
.aspectMask = attachment_aspect,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
};
|
||||||
|
const std::array pre_barriers{
|
||||||
|
VkImageMemoryBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = src,
|
||||||
|
.subresourceRange = src_range,
|
||||||
|
},
|
||||||
|
VkImageMemoryBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||||
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = dst,
|
||||||
|
.subresourceRange = src_range,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||||
|
0, nullptr, nullptr, pre_barriers);
|
||||||
|
const VkRenderPassBeginInfo renderpass_bi{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.renderPass = renderpass,
|
||||||
|
.framebuffer = framebuffer_handle,
|
||||||
|
.renderArea = render_area,
|
||||||
|
.clearValueCount = 0,
|
||||||
|
.pClearValues = nullptr,
|
||||||
|
};
|
||||||
|
cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
const VkDescriptorSet descriptor_set =
|
||||||
|
src_stencil_handle != VK_NULL_HANDLE
|
||||||
|
? two_textures_descriptor_allocator.Commit()
|
||||||
|
: one_texture_descriptor_allocator.Commit();
|
||||||
|
if (src_stencil_handle != VK_NULL_HANDLE) {
|
||||||
|
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_view_handle,
|
||||||
|
src_stencil_handle);
|
||||||
|
} else {
|
||||||
|
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view_handle);
|
||||||
|
}
|
||||||
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||||
|
nullptr);
|
||||||
|
const VkViewport viewport{
|
||||||
|
.x = static_cast<float>(render_area.offset.x),
|
||||||
|
.y = static_cast<float>(render_area.offset.y),
|
||||||
|
.width = static_cast<float>(render_area.extent.width),
|
||||||
|
.height = static_cast<float>(render_area.extent.height),
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
cmdbuf.SetViewport(0, viewport);
|
||||||
|
cmdbuf.SetScissor(0, render_area);
|
||||||
|
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants);
|
||||||
|
cmdbuf.Draw(3, 1, 0, 0);
|
||||||
|
cmdbuf.EndRenderPass();
|
||||||
|
const VkImageMemoryBarrier post_barrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT |
|
||||||
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = dst,
|
||||||
|
.subresourceRange = src_range,
|
||||||
|
};
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, 0, post_barrier);
|
||||||
|
});
|
||||||
|
msaa_copy_resources.push_back(MSAACopyResources{
|
||||||
|
.tick = scheduler.CurrentTick(),
|
||||||
|
.src_view = std::move(src_view),
|
||||||
|
.dst_view = std::move(dst_view),
|
||||||
|
.framebuffer = std::move(framebuffer),
|
||||||
|
});
|
||||||
|
if (copy_stencil) {
|
||||||
|
msaa_copy_resources.push_back(MSAACopyResources{
|
||||||
|
.tick = scheduler.CurrentTick(),
|
||||||
|
.src_view = std::move(src_stencil_view),
|
||||||
|
.dst_view = vk::ImageView{},
|
||||||
|
.framebuffer = vk::Framebuffer{},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key) {
|
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key) {
|
||||||
const auto it = std::ranges::find(msaa_copy_keys, key);
|
const auto it = std::ranges::find(msaa_copy_keys, key);
|
||||||
if (it != msaa_copy_keys.end()) {
|
if (it != msaa_copy_keys.end()) {
|
||||||
@@ -1462,6 +1669,79 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline
|
|||||||
return *msaa_copy_pipelines.back();
|
return *msaa_copy_pipelines.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPipelineKey& key,
|
||||||
|
bool copy_stencil) {
|
||||||
|
auto& keys = copy_stencil ? msaa_copy_depth_stencil_keys : msaa_copy_depth_keys;
|
||||||
|
auto& pipelines = copy_stencil ? msaa_copy_depth_stencil_pipelines : msaa_copy_depth_pipelines;
|
||||||
|
const auto it = std::ranges::find(keys, key);
|
||||||
|
if (it != keys.end()) {
|
||||||
|
return *pipelines[std::distance(keys.begin(), it)];
|
||||||
|
}
|
||||||
|
keys.push_back(key);
|
||||||
|
const std::array stages =
|
||||||
|
MakeStages(*clear_color_vert, copy_stencil ? *convert_non_msaa_to_msaa_depth_stencil_frag
|
||||||
|
: *convert_non_msaa_to_msaa_depth_frag);
|
||||||
|
const VkPipelineMultisampleStateCreateInfo multisample_ci{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.rasterizationSamples = key.samples,
|
||||||
|
.sampleShadingEnable = VK_TRUE,
|
||||||
|
.minSampleShading = 1.0f,
|
||||||
|
.pSampleMask = nullptr,
|
||||||
|
.alphaToCoverageEnable = VK_FALSE,
|
||||||
|
.alphaToOneEnable = VK_FALSE,
|
||||||
|
};
|
||||||
|
static constexpr VkStencilOpState REPLACE_STENCIL_OP{
|
||||||
|
.failOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.passOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0xFF,
|
||||||
|
.writeMask = 0xFF,
|
||||||
|
.reference = 0,
|
||||||
|
};
|
||||||
|
const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.depthTestEnable = VK_TRUE,
|
||||||
|
.depthWriteEnable = VK_TRUE,
|
||||||
|
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.depthBoundsTestEnable = VK_FALSE,
|
||||||
|
.stencilTestEnable = copy_stencil ? VK_TRUE : VK_FALSE,
|
||||||
|
.front = copy_stencil ? REPLACE_STENCIL_OP : VkStencilOpState{},
|
||||||
|
.back = copy_stencil ? REPLACE_STENCIL_OP : VkStencilOpState{},
|
||||||
|
.minDepthBounds = 0.0f,
|
||||||
|
.maxDepthBounds = 0.0f,
|
||||||
|
};
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci =
|
||||||
|
GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
|
pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
|
.pStages = stages.data(),
|
||||||
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
|
.pTessellationState = nullptr,
|
||||||
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
.pMultisampleState = &multisample_ci,
|
||||||
|
.pDepthStencilState = &depth_stencil_ci,
|
||||||
|
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
|
||||||
|
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
|
.layout = copy_stencil ? *msaa_copy_depth_stencil_pipeline_layout
|
||||||
|
: *msaa_copy_pipeline_layout,
|
||||||
|
.renderPass = key.renderpass,
|
||||||
|
.subpass = 0,
|
||||||
|
.basePipelineHandle = VK_NULL_HANDLE,
|
||||||
|
.basePipelineIndex = 0,
|
||||||
|
}, device.StaticPipelineCache()));
|
||||||
|
return *pipelines.back();
|
||||||
|
}
|
||||||
|
|
||||||
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
|
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
|
||||||
ConvertPipeline(pipeline, renderpass, false);
|
ConvertPipeline(pipeline, renderpass, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,11 @@ public:
|
|||||||
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
||||||
std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa);
|
std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa);
|
||||||
|
|
||||||
|
void CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image,
|
||||||
|
VideoCore::Surface::PixelFormat dst_format, VkImage src_image,
|
||||||
|
VideoCore::Surface::PixelFormat src_format, u32 num_samples,
|
||||||
|
std::span<const VideoCommon::ImageCopy> copies, bool copy_stencil);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||||
const ImageView& src_image_view);
|
const ImageView& src_image_view);
|
||||||
@@ -131,6 +136,9 @@ private:
|
|||||||
[[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline(
|
[[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline(
|
||||||
const BlitDepthStencilPipelineKey& key);
|
const BlitDepthStencilPipelineKey& key);
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key);
|
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key);
|
||||||
|
|
||||||
|
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPipelineKey& key,
|
||||||
|
bool copy_stencil);
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key);
|
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key);
|
||||||
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
||||||
bool resolve_stencil);
|
bool resolve_stencil);
|
||||||
@@ -162,6 +170,7 @@ private:
|
|||||||
vk::PipelineLayout two_textures_pipeline_layout;
|
vk::PipelineLayout two_textures_pipeline_layout;
|
||||||
vk::PipelineLayout clear_color_pipeline_layout;
|
vk::PipelineLayout clear_color_pipeline_layout;
|
||||||
vk::PipelineLayout msaa_copy_pipeline_layout;
|
vk::PipelineLayout msaa_copy_pipeline_layout;
|
||||||
|
vk::PipelineLayout msaa_copy_depth_stencil_pipeline_layout;
|
||||||
vk::ShaderModule full_screen_vert;
|
vk::ShaderModule full_screen_vert;
|
||||||
vk::ShaderModule blit_color_to_color_frag;
|
vk::ShaderModule blit_color_to_color_frag;
|
||||||
vk::ShaderModule blit_color_msaa_frag;
|
vk::ShaderModule blit_color_msaa_frag;
|
||||||
@@ -180,6 +189,8 @@ private:
|
|||||||
vk::ShaderModule convert_s8d24_to_abgr8_frag;
|
vk::ShaderModule convert_s8d24_to_abgr8_frag;
|
||||||
vk::ShaderModule convert_msaa_to_non_msaa_frag;
|
vk::ShaderModule convert_msaa_to_non_msaa_frag;
|
||||||
vk::ShaderModule convert_non_msaa_to_msaa_frag;
|
vk::ShaderModule convert_non_msaa_to_msaa_frag;
|
||||||
|
vk::ShaderModule convert_non_msaa_to_msaa_depth_frag;
|
||||||
|
vk::ShaderModule convert_non_msaa_to_msaa_depth_stencil_frag;
|
||||||
vk::Sampler linear_sampler;
|
vk::Sampler linear_sampler;
|
||||||
vk::Sampler nearest_sampler;
|
vk::Sampler nearest_sampler;
|
||||||
|
|
||||||
@@ -193,6 +204,10 @@ private:
|
|||||||
std::vector<vk::Pipeline> clear_stencil_pipelines;
|
std::vector<vk::Pipeline> clear_stencil_pipelines;
|
||||||
std::vector<MSAACopyPipelineKey> msaa_copy_keys;
|
std::vector<MSAACopyPipelineKey> msaa_copy_keys;
|
||||||
std::vector<vk::Pipeline> msaa_copy_pipelines;
|
std::vector<vk::Pipeline> msaa_copy_pipelines;
|
||||||
|
std::vector<MSAACopyPipelineKey> msaa_copy_depth_keys;
|
||||||
|
std::vector<vk::Pipeline> msaa_copy_depth_pipelines;
|
||||||
|
std::vector<MSAACopyPipelineKey> msaa_copy_depth_stencil_keys;
|
||||||
|
std::vector<vk::Pipeline> msaa_copy_depth_stencil_pipelines;
|
||||||
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
|
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
|
||||||
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
|
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
|
||||||
std::vector<VkRenderPass> resolve_depth_keys;
|
std::vector<VkRenderPass> resolve_depth_keys;
|
||||||
|
|||||||
@@ -1838,11 +1838,21 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
|
|||||||
ScaleDown(true);
|
ScaleDown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool msaa_upload_is_depth = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||||
const bool wants_msaa_upload = info.num_samples > 1
|
const bool wants_msaa_upload = info.num_samples > 1
|
||||||
&& (aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0
|
&& ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0 || msaa_upload_is_depth)
|
||||||
&& !VideoCore::Surface::IsPixelFormatInteger(info.format);
|
&& !VideoCore::Surface::IsPixelFormatInteger(info.format);
|
||||||
|
|
||||||
if (wants_msaa_upload) {
|
if (wants_msaa_upload) {
|
||||||
|
const bool msaa_upload_copies_stencil =
|
||||||
|
msaa_upload_is_depth && (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 &&
|
||||||
|
runtime->device.IsExtShaderStencilExportSupported();
|
||||||
|
const VkImageAspectFlags upload_aspect_mask =
|
||||||
|
msaa_upload_is_depth
|
||||||
|
? (msaa_upload_copies_stencil
|
||||||
|
? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
|
||||||
|
: VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||||
|
: aspect_mask;
|
||||||
ImageInfo temp_info = info;
|
ImageInfo temp_info = info;
|
||||||
temp_info.num_samples = 1;
|
temp_info.num_samples = 1;
|
||||||
|
|
||||||
@@ -1854,10 +1864,10 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
|
|||||||
vk::Image temp_image = runtime->memory_allocator.CreateImage(image_ci);
|
vk::Image temp_image = runtime->memory_allocator.CreateImage(image_ci);
|
||||||
|
|
||||||
scheduler->RequestOutsideRenderPassOperationContext();
|
scheduler->RequestOutsideRenderPassOperationContext();
|
||||||
auto vk_copies = TransformBufferImageCopies(copies, offset, aspect_mask);
|
auto vk_copies = TransformBufferImageCopies(copies, offset, upload_aspect_mask);
|
||||||
const VkBuffer src_buffer = buffer;
|
const VkBuffer src_buffer = buffer;
|
||||||
const VkImage temp_vk_image = *temp_image;
|
const VkImage temp_vk_image = *temp_image;
|
||||||
const VkImageAspectFlags vk_aspect_mask = aspect_mask;
|
const VkImageAspectFlags vk_aspect_mask = upload_aspect_mask;
|
||||||
|
|
||||||
scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask,
|
scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask,
|
||||||
vk_copies](vk::CommandBuffer cmdbuf) {
|
vk_copies](vk::CommandBuffer cmdbuf) {
|
||||||
@@ -1879,9 +1889,16 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
|
|||||||
image_copies.push_back(image_copy);
|
image_copies.push_back(image_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, Handle(), info.format,
|
if (msaa_upload_is_depth) {
|
||||||
temp_vk_image, info.format, info.num_samples,
|
runtime->blit_image_helper.CopyMSAADepth(runtime->render_pass_cache, Handle(),
|
||||||
image_copies, false);
|
info.format, temp_vk_image, info.format,
|
||||||
|
info.num_samples, image_copies,
|
||||||
|
msaa_upload_copies_stencil);
|
||||||
|
} else {
|
||||||
|
runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, Handle(), info.format,
|
||||||
|
temp_vk_image, info.format, info.num_samples,
|
||||||
|
image_copies, false);
|
||||||
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
runtime->pending_msaa_images.emplace_back(scheduler->CurrentTick(), std::move(temp_image));
|
runtime->pending_msaa_images.emplace_back(scheduler->CurrentTick(), std::move(temp_image));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user