mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-25 00:40:32 +00:00
[TEST] Added another MSAA depth stencil shaders to convert into non msaa + sanitize MSAA UINT/SINT path
This commit is contained in:
@@ -33,6 +33,8 @@ set(SHADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_float_to_depth.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.comp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth_stencil.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_sint.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_uint.frag
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#version 450 core
|
||||
|
||||
layout(binding = 0) uniform sampler2DMS msaa_in;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
ivec2 dst_offset;
|
||||
ivec2 src_offset;
|
||||
ivec2 scale;
|
||||
};
|
||||
|
||||
void main() {
|
||||
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
||||
const ivec2 msaa_coord = coord / scale;
|
||||
const ivec2 sample_offset = coord % scale;
|
||||
const int sample_id = sample_offset.x + scale.x * sample_offset.y;
|
||||
gl_FragDepth = texelFetch(msaa_in, msaa_coord, sample_id).r;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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 sampler2DMS depth_tex;
|
||||
layout(binding = 1) uniform usampler2DMS stencil_tex;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
ivec2 dst_offset;
|
||||
ivec2 src_offset;
|
||||
ivec2 scale;
|
||||
};
|
||||
|
||||
void main() {
|
||||
const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset;
|
||||
const ivec2 msaa_coord = coord / scale;
|
||||
const ivec2 sample_offset = coord % scale;
|
||||
const int sample_id = sample_offset.x + scale.x * sample_offset.y;
|
||||
gl_FragDepth = texelFetch(depth_tex, msaa_coord, sample_id).r;
|
||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, msaa_coord, sample_id).r);
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "video_core/host_shaders/convert_depth_to_float_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_depth_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_depth_stencil_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_sint_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_msaa_to_non_msaa_uint_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_non_msaa_to_msaa_frag_spv.h"
|
||||
@@ -636,6 +638,10 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
|
||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_SINT_FRAG_SPV)),
|
||||
convert_msaa_to_non_msaa_uint_frag(
|
||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_UINT_FRAG_SPV)),
|
||||
convert_msaa_to_non_msaa_depth_frag(
|
||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_DEPTH_FRAG_SPV)),
|
||||
convert_msaa_to_non_msaa_depth_stencil_frag(
|
||||
BuildShader(device, CONVERT_MSAA_TO_NON_MSAA_DEPTH_STENCIL_FRAG_SPV)),
|
||||
convert_non_msaa_to_msaa_frag(BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_FRAG_SPV)),
|
||||
convert_non_msaa_to_msaa_sint_frag(
|
||||
BuildShader(device, CONVERT_NON_MSAA_TO_MSAA_SINT_FRAG_SPV)),
|
||||
@@ -1606,14 +1612,15 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage
|
||||
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) {
|
||||
bool copy_stencil, bool msaa_to_non_msaa) {
|
||||
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);
|
||||
const VkSampleCountFlagBits samples =
|
||||
msaa_to_non_msaa ? VK_SAMPLE_COUNT_1_BIT : SampleCountFlag(num_samples);
|
||||
RenderPassKey renderpass_key{};
|
||||
renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid);
|
||||
renderpass_key.depth_format = dst_format;
|
||||
@@ -1622,7 +1629,7 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage
|
||||
const MSAACopyPipelineKey key{
|
||||
.renderpass = renderpass,
|
||||
.samples = samples,
|
||||
.msaa_to_non_msaa = false,
|
||||
.msaa_to_non_msaa = msaa_to_non_msaa,
|
||||
.format_class = MSAACopyFormatClass::Float,
|
||||
};
|
||||
const VkPipeline pipeline = FindOrEmplaceMSAACopyDepthPipeline(key, copy_stencil);
|
||||
@@ -1859,16 +1866,22 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip
|
||||
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);
|
||||
VkShaderModule frag_module;
|
||||
if (key.msaa_to_non_msaa) {
|
||||
frag_module = copy_stencil ? *convert_msaa_to_non_msaa_depth_stencil_frag
|
||||
: *convert_msaa_to_non_msaa_depth_frag;
|
||||
} else {
|
||||
frag_module = copy_stencil ? *convert_non_msaa_to_msaa_depth_stencil_frag
|
||||
: *convert_non_msaa_to_msaa_depth_frag;
|
||||
}
|
||||
const std::array stages = MakeStages(*clear_color_vert, frag_module);
|
||||
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,
|
||||
.sampleShadingEnable = key.msaa_to_non_msaa ? VK_FALSE : VK_TRUE,
|
||||
.minSampleShading = key.msaa_to_non_msaa ? 0.0f : 1.0f,
|
||||
.pSampleMask = nullptr,
|
||||
.alphaToCoverageEnable = VK_FALSE,
|
||||
.alphaToOneEnable = VK_FALSE,
|
||||
|
||||
@@ -132,7 +132,8 @@ public:
|
||||
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);
|
||||
std::span<const VideoCommon::ImageCopy> copies, bool copy_stencil,
|
||||
bool msaa_to_non_msaa);
|
||||
|
||||
private:
|
||||
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
@@ -207,6 +208,8 @@ private:
|
||||
vk::ShaderModule convert_msaa_to_non_msaa_frag;
|
||||
vk::ShaderModule convert_msaa_to_non_msaa_sint_frag;
|
||||
vk::ShaderModule convert_msaa_to_non_msaa_uint_frag;
|
||||
vk::ShaderModule convert_msaa_to_non_msaa_depth_frag;
|
||||
vk::ShaderModule convert_msaa_to_non_msaa_depth_stencil_frag;
|
||||
vk::ShaderModule convert_non_msaa_to_msaa_frag;
|
||||
vk::ShaderModule convert_non_msaa_to_msaa_sint_frag;
|
||||
vk::ShaderModule convert_non_msaa_to_msaa_uint_frag;
|
||||
|
||||
@@ -854,12 +854,10 @@ void RasterizerVulkan::WaitForIdle() {
|
||||
// fragment shaders can still write storage buffers.
|
||||
VkPipelineStageFlags flags =
|
||||
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (device.SupportsTessellationShader()) {
|
||||
flags |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (device.SupportsGeometryShader()) {
|
||||
flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
}
|
||||
|
||||
@@ -1749,8 +1749,20 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dst.AspectMask() != VK_IMAGE_ASPECT_COLOR_BIT ||
|
||||
VideoCore::Surface::IsPixelFormatInteger(dst.info.format)) {
|
||||
const VkImageAspectFlags dst_aspect_mask = dst.AspectMask();
|
||||
if ((dst_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) {
|
||||
const bool copies_stencil = (dst_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 &&
|
||||
device.IsExtShaderStencilExportSupported();
|
||||
if ((dst_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 && !copies_stencil) {
|
||||
UNIMPLEMENTED_MSG("Copying images with different samples is not supported.");
|
||||
return;
|
||||
}
|
||||
blit_image_helper.CopyMSAADepth(render_pass_cache, dst.Handle(), dst.info.format,
|
||||
src.Handle(), src.info.format, num_samples, copies,
|
||||
copies_stencil, msaa_to_non_msaa);
|
||||
return;
|
||||
}
|
||||
if ((dst_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) == 0) {
|
||||
UNIMPLEMENTED_MSG("Copying images with different samples is not supported.");
|
||||
return;
|
||||
}
|
||||
@@ -1767,7 +1779,17 @@ u64 TextureCacheRuntime::GetDeviceMemoryUsage() const {
|
||||
}
|
||||
|
||||
bool TextureCacheRuntime::CanDownloadMsaa(const VideoCommon::ImageInfo& info) const {
|
||||
return ImageAspectMask(info.format) == VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
const VkImageAspectFlags aspect_mask = ImageAspectMask(info.format);
|
||||
if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) {
|
||||
return true;
|
||||
}
|
||||
if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) == 0) {
|
||||
return false;
|
||||
}
|
||||
if ((aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) {
|
||||
return device.IsExtShaderStencilExportSupported();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextureCacheRuntime::CanReportMemoryUsage() const {
|
||||
@@ -1953,7 +1975,7 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
|
||||
runtime->blit_image_helper.CopyMSAADepth(runtime->render_pass_cache, Handle(),
|
||||
info.format, temp_vk_image, info.format,
|
||||
info.num_samples, image_copies,
|
||||
msaa_upload_copies_stencil);
|
||||
msaa_upload_copies_stencil, false);
|
||||
} else {
|
||||
runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, Handle(), info.format,
|
||||
temp_vk_image, info.format, info.num_samples,
|
||||
@@ -2024,33 +2046,53 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||
image_ci.format =
|
||||
MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format)
|
||||
.format;
|
||||
image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
const bool msaa_download_is_depth =
|
||||
(aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
const bool msaa_download_copies_stencil =
|
||||
msaa_download_is_depth && (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 &&
|
||||
runtime->device.IsExtShaderStencilExportSupported();
|
||||
image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
if (msaa_download_is_depth) {
|
||||
image_ci.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
} else {
|
||||
image_ci.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
vk::Image temp_image = runtime->memory_allocator.CreateImage(image_ci);
|
||||
const VkImage temp_vk_image = *temp_image;
|
||||
|
||||
const VkImageAspectFlags temp_aspect_mask = aspect_mask;
|
||||
const VkAccessFlags attachment_access =
|
||||
msaa_download_is_depth ? (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
|
||||
: (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
||||
const VkPipelineStageFlags attachment_stage =
|
||||
msaa_download_is_depth ? (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT)
|
||||
: VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
|
||||
scheduler->RequestOutsideRenderPassOperationContext();
|
||||
scheduler->Record([temp_vk_image](vk::CommandBuffer cmdbuf) {
|
||||
scheduler->Record([temp_vk_image, temp_aspect_mask, attachment_access,
|
||||
attachment_stage](vk::CommandBuffer cmdbuf) {
|
||||
const VkImageMemoryBarrier init_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = attachment_access,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = temp_vk_image,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.aspectMask = temp_aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
|
||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, attachment_stage, 0,
|
||||
init_barrier);
|
||||
});
|
||||
|
||||
@@ -2065,9 +2107,15 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||
image_copies.push_back(image_copy);
|
||||
}
|
||||
|
||||
runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, temp_vk_image,
|
||||
info.format, Handle(), info.format,
|
||||
info.num_samples, image_copies, true);
|
||||
if (msaa_download_is_depth) {
|
||||
runtime->blit_image_helper.CopyMSAADepth(
|
||||
runtime->render_pass_cache, temp_vk_image, info.format, Handle(), info.format,
|
||||
info.num_samples, image_copies, msaa_download_copies_stencil, true);
|
||||
} else {
|
||||
runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, temp_vk_image,
|
||||
info.format, Handle(), info.format,
|
||||
info.num_samples, image_copies, true);
|
||||
}
|
||||
|
||||
boost::container::small_vector<VkBuffer, 8> buffers_vector{};
|
||||
boost::container::small_vector<boost::container::small_vector<VkBufferImageCopy, 16>, 8>
|
||||
|
||||
@@ -1023,25 +1023,19 @@ FN_MAX_LIMIT_LIST
|
||||
return features2.features.multiViewport;
|
||||
}
|
||||
|
||||
bool SupportsTessellationShader() const {
|
||||
return features2.features.tessellationShader;
|
||||
}
|
||||
|
||||
bool SupportsGeometryShader() const {
|
||||
return features2.features.geometryShader;
|
||||
}
|
||||
|
||||
VkPipelineStageFlags AttachmentConsumerStages() const {
|
||||
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
if (features2.features.tessellationShader) {
|
||||
stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
if (features2.features.geometryShader) {
|
||||
stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user