mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-21 15:28:19 +00:00
[TEST] Blitting on MSAA
This commit is contained in:
@@ -8,5 +8,5 @@ layout(binding = 0) uniform sampler2DMS depth_tex;
|
||||
layout(location = 0) in vec2 texcoord;
|
||||
|
||||
void main() {
|
||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), 0).r;
|
||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), gl_SampleID).r;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ layout(binding = 1) uniform usampler2DMS stencil_tex;
|
||||
layout(location = 0) in vec2 texcoord;
|
||||
|
||||
void main() {
|
||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), 0).r;
|
||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, ivec2(texcoord), 0).r);
|
||||
gl_FragDepth = texelFetch(depth_tex, ivec2(texcoord), gl_SampleID).r;
|
||||
gl_FragStencilRefARB = int(texelFetch(stencil_tex, ivec2(texcoord), gl_SampleID).r);
|
||||
}
|
||||
|
||||
@@ -710,6 +710,46 @@ void BlitImageHelper::BlitColorMSAA(const Framebuffer* dst_framebuffer,
|
||||
scheduler.InvalidateState();
|
||||
}
|
||||
|
||||
void BlitImageHelper::BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, const Region2D& dst_region,
|
||||
const Region2D& src_region) {
|
||||
const bool blit_stencil =
|
||||
dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported();
|
||||
const BlitMSAAPipelineKey key{
|
||||
.renderpass = dst_framebuffer->RenderPass(),
|
||||
.samples = dst_framebuffer->Samples(),
|
||||
};
|
||||
const VkPipeline pipeline = FindOrEmplaceBlitDepthStencilMSAAPipeline(key, blit_stencil);
|
||||
const VkPipelineLayout layout =
|
||||
blit_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout;
|
||||
const VkSampler sampler = *nearest_sampler;
|
||||
const VkImageView src_depth_view = src_image_view.DepthView();
|
||||
const VkImageView src_stencil_view =
|
||||
blit_stencil ? src_image_view.StencilView() : VK_NULL_HANDLE;
|
||||
|
||||
RecordShaderReadBarrier(scheduler, src_image_view);
|
||||
scheduler.RequestRenderpass(dst_framebuffer);
|
||||
scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler, src_depth_view,
|
||||
src_stencil_view, blit_stencil](vk::CommandBuffer cmdbuf) {
|
||||
if (blit_stencil) {
|
||||
const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
|
||||
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
|
||||
src_stencil_view);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||
nullptr);
|
||||
} else {
|
||||
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_depth_view);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||
nullptr);
|
||||
}
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
BindBlitState(cmdbuf, layout, dst_region, src_region);
|
||||
cmdbuf.Draw(3, 1, 0, 0);
|
||||
});
|
||||
scheduler.InvalidateState();
|
||||
}
|
||||
|
||||
void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, const Region2D& dst_region,
|
||||
const Region2D& src_region) {
|
||||
@@ -1394,6 +1434,55 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip
|
||||
return *blit_msaa_color_pipelines.back();
|
||||
}
|
||||
|
||||
VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline(
|
||||
const BlitMSAAPipelineKey& key, bool blit_stencil) {
|
||||
auto& keys = blit_stencil ? blit_msaa_depth_stencil_keys : blit_msaa_depth_keys;
|
||||
auto& pipelines = blit_stencil ? blit_msaa_depth_stencil_pipelines : blit_msaa_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(*full_screen_vert,
|
||||
blit_stencil ? *blit_depth_stencil_msaa_frag : *blit_depth_msaa_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,
|
||||
};
|
||||
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 = blit_stencil ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
|
||||
: &PIPELINE_DEPTH_ONLY_STATE_CREATE_INFO,
|
||||
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
|
||||
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.layout = blit_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout,
|
||||
.renderPass = key.renderpass,
|
||||
.subpass = 0,
|
||||
.basePipelineHandle = VK_NULL_HANDLE,
|
||||
.basePipelineIndex = 0,
|
||||
}, device.StaticPipelineCache()));
|
||||
return *pipelines.back();
|
||||
}
|
||||
|
||||
VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
||||
bool resolve_stencil) {
|
||||
auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys;
|
||||
|
||||
@@ -78,6 +78,9 @@ public:
|
||||
void BlitColorMSAA(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
const Region2D& dst_region, const Region2D& src_region);
|
||||
|
||||
void BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
const Region2D& dst_region, const Region2D& src_region);
|
||||
|
||||
void ResolveDepthStencil(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
const Region2D& dst_region, const Region2D& src_region);
|
||||
|
||||
@@ -140,6 +143,8 @@ private:
|
||||
[[nodiscard]] VkPipeline FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPipelineKey& key,
|
||||
bool copy_stencil);
|
||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key);
|
||||
[[nodiscard]] VkPipeline FindOrEmplaceBlitDepthStencilMSAAPipeline(
|
||||
const BlitMSAAPipelineKey& key, bool blit_stencil);
|
||||
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass,
|
||||
bool resolve_stencil);
|
||||
|
||||
@@ -210,6 +215,10 @@ private:
|
||||
std::vector<vk::Pipeline> msaa_copy_depth_stencil_pipelines;
|
||||
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
|
||||
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
|
||||
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_keys;
|
||||
std::vector<vk::Pipeline> blit_msaa_depth_pipelines;
|
||||
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_stencil_keys;
|
||||
std::vector<vk::Pipeline> blit_msaa_depth_stencil_pipelines;
|
||||
std::vector<VkRenderPass> resolve_depth_keys;
|
||||
std::vector<vk::Pipeline> resolve_depth_pipelines;
|
||||
std::vector<VkRenderPass> resolve_depth_stencil_keys;
|
||||
|
||||
@@ -682,6 +682,11 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool HaveSameExtent(const Region2D& dst_region, const Region2D& src_region) {
|
||||
return dst_region.end.x - dst_region.start.x == src_region.end.x - src_region.start.x &&
|
||||
dst_region.end.y - dst_region.start.y == src_region.end.y - src_region.start.y;
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region,
|
||||
const Region2D& src_region,
|
||||
const VkImageSubresourceLayers& dst_layers,
|
||||
@@ -779,15 +784,15 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.Record([dst_image, src_image, extent, resources, aspect_mask, resolution, is_2d,
|
||||
vk_filter, up_scaling](vk::CommandBuffer cmdbuf) {
|
||||
const u32 scaled_width = resolution.ScaleUp(extent.width);
|
||||
const u32 scaled_height = is_2d ? resolution.ScaleUp(extent.height) : extent.height;
|
||||
const VkOffset2D src_size{
|
||||
.x = static_cast<s32>(up_scaling ? extent.width : resolution.ScaleUp(extent.width)),
|
||||
.y = static_cast<s32>(is_2d && up_scaling ? extent.height
|
||||
: resolution.ScaleUp(extent.height)),
|
||||
.x = static_cast<s32>(up_scaling ? extent.width : scaled_width),
|
||||
.y = static_cast<s32>(up_scaling ? extent.height : scaled_height),
|
||||
};
|
||||
const VkOffset2D dst_size{
|
||||
.x = static_cast<s32>(up_scaling ? resolution.ScaleUp(extent.width) : extent.width),
|
||||
.y = static_cast<s32>(is_2d && up_scaling ? resolution.ScaleUp(extent.height)
|
||||
: extent.height),
|
||||
.x = static_cast<s32>(up_scaling ? scaled_width : extent.width),
|
||||
.y = static_cast<s32>(up_scaling ? scaled_height : extent.height),
|
||||
};
|
||||
boost::container::small_vector<VkImageBlit, 4> regions;
|
||||
regions.reserve(resources.levels);
|
||||
@@ -1286,8 +1291,14 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||
blit_image_helper.BlitColorMSAA(dst_framebuffer, src, dst_region, src_region);
|
||||
return;
|
||||
}
|
||||
if (is_msaa_to_msaa && device.CantBlitMSAA()) {
|
||||
UNIMPLEMENTED_MSG("MSAA to MSAA depth-stencil blit is not supported on this driver");
|
||||
if (is_msaa_to_msaa) {
|
||||
blit_image_helper.BlitDepthStencilMSAA(dst_framebuffer, src, dst_region, src_region);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool is_resolve = is_src_msaa && !is_dst_msaa;
|
||||
if (is_resolve && !HaveSameExtent(dst_region, src_region)) {
|
||||
blit_image_helper.BlitColorMSAA(dst_framebuffer, src, dst_region, src_region);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1295,7 +1306,6 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||
const VkImage src_image = src.ImageHandle();
|
||||
const VkImageSubresourceLayers dst_layers = MakeSubresourceLayers(&dst);
|
||||
const VkImageSubresourceLayers src_layers = MakeSubresourceLayers(&src);
|
||||
const bool is_resolve = is_src_msaa && !is_dst_msaa;
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.Record([filter, dst_region, src_region, dst_image, src_image, dst_layers, src_layers,
|
||||
aspect_mask, is_resolve](vk::CommandBuffer cmdbuf) {
|
||||
@@ -2335,12 +2345,21 @@ bool Image::BlitScaleHelper(bool scale_up) {
|
||||
runtime->blit_image_helper.BlitColor(&*blit_framebuffer, *blit_view,
|
||||
dst_region, src_region, operation, BLIT_OPERATION);
|
||||
}
|
||||
} else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
||||
info.num_samples == 1) {
|
||||
} else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
if (!blit_framebuffer)
|
||||
blit_framebuffer.emplace(*runtime, nullptr, view_ptr, extent, scale_up);
|
||||
runtime->blit_image_helper.BlitDepthStencil(&*blit_framebuffer, *blit_view,
|
||||
dst_region, src_region, operation, BLIT_OPERATION);
|
||||
if (info.num_samples > 1) {
|
||||
runtime->blit_image_helper.BlitDepthStencilMSAA(&*blit_framebuffer, *blit_view,
|
||||
dst_region, src_region);
|
||||
} else {
|
||||
runtime->blit_image_helper.BlitDepthStencil(&*blit_framebuffer, *blit_view,
|
||||
dst_region, src_region, operation, BLIT_OPERATION);
|
||||
}
|
||||
} else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT && info.num_samples > 1) {
|
||||
if (!blit_framebuffer)
|
||||
blit_framebuffer.emplace(*runtime, nullptr, view_ptr, extent, scale_up);
|
||||
runtime->blit_image_helper.BlitDepthStencilMSAA(&*blit_framebuffer, *blit_view, dst_region,
|
||||
src_region);
|
||||
} else {
|
||||
// TODO: Use helper blits where applicable
|
||||
flags &= ~ImageFlagBits::Rescaled;
|
||||
@@ -2352,9 +2371,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
|
||||
|
||||
bool Image::NeedsScaleHelper() const {
|
||||
const auto& device = runtime->device;
|
||||
const bool needs_msaa_helper = info.num_samples > 1 &&
|
||||
(device.CantBlitMSAA() || aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
if (needs_msaa_helper) {
|
||||
if (info.num_samples > 1) {
|
||||
return true;
|
||||
}
|
||||
static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
|
||||
|
||||
@@ -659,13 +659,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
features.shader_float16_int8.shaderFloat16 = false;
|
||||
}
|
||||
|
||||
if (is_intel_windows) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Intel proprietary drivers do not support MSAA->MSAA image blits. "
|
||||
"MSAA scaling will use 3D helpers. MSAA resolves work normally.");
|
||||
cant_blit_msaa = true;
|
||||
}
|
||||
|
||||
has_broken_compute =
|
||||
CheckBrokenCompute(properties.driver.driverID, properties.properties.driverVersion) &&
|
||||
!Settings::values.enable_compute_pipelines.GetValue();
|
||||
|
||||
@@ -955,10 +955,6 @@ FN_MAX_LIMIT_LIST
|
||||
return supports_d24_depth;
|
||||
}
|
||||
|
||||
bool CantBlitMSAA() const {
|
||||
return cant_blit_msaa;
|
||||
}
|
||||
|
||||
bool MustEmulateScaledFormats() const {
|
||||
return must_emulate_scaled_formats;
|
||||
}
|
||||
@@ -1230,7 +1226,6 @@ private:
|
||||
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
|
||||
bool has_radeon_gpu_profiler{}; ///< Has Radeon GPU Profiler attached.
|
||||
bool supports_d24_depth{}; ///< Supports D24 depth buffers.
|
||||
bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting.
|
||||
bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation
|
||||
bool dynamic_state3_blending{}; ///< Has blending features of dynamic_state3.
|
||||
bool dynamic_state3_enables{}; ///< Has at least one enable feature of dynamic_state3.
|
||||
|
||||
Reference in New Issue
Block a user