[texture_cache] Implement alpha copies and put barrier in compute stages

This commit is contained in:
JPikachu 2025-07-14 20:09:57 +01:00
parent 2e092010e6
commit 0102ad5b98
11 changed files with 135 additions and 9 deletions

0
.gdbinit Normal file
View file

View file

@ -21,6 +21,8 @@ set(SHADER_FILES
convert_abgr8_srgb_to_d24s8.frag convert_abgr8_srgb_to_d24s8.frag
convert_abgr8_to_d24s8.frag convert_abgr8_to_d24s8.frag
convert_abgr8_to_d32f.frag convert_abgr8_to_d32f.frag
convert_r8_to_abgr8.frag
convert_abgr8_to_r8.frag
convert_d32f_to_abgr8.frag convert_d32f_to_abgr8.frag
convert_d24s8_to_abgr8.frag convert_d24s8_to_abgr8.frag
convert_depth_to_float.frag convert_depth_to_float.frag

View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout(binding = 0) uniform sampler2D tex;
layout(location = 0) out float color;
layout(push_constant) uniform PushConstants {
uniform vec2 tex_scale;
uniform vec2 tex_offset;
};
void main() {
vec2 coord = gl_FragCoord.xy / tex_scale * textureSize(tex, 0);
float red = texelFetch(tex, ivec2(coord), 0).r;
color = red;
}

View file

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout(binding = 0) uniform sampler2D tex;
layout(push_constant) uniform PushConstants {
uniform vec2 tex_scale;
uniform vec2 tex_offset;
};
layout(location = 0) out vec4 color;
void main() {
vec2 coord = gl_FragCoord.xy / tex_scale * textureSize(tex, 0);
float red = texelFetch(tex, ivec2(coord), 0).r;
color = vec4(red, red, red, 1.0);
}

View file

@ -11,6 +11,7 @@
#include "video_core/host_shaders/convert_abgr8_to_d32f_frag_spv.h" #include "video_core/host_shaders/convert_abgr8_to_d32f_frag_spv.h"
#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_d32f_to_abgr8_frag_spv.h" #include "video_core/host_shaders/convert_d32f_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_r8_to_abgr8_frag_spv.h"
#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" #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_float_to_depth_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"
@ -29,6 +30,7 @@
#include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/host_shaders/convert_abgr8_srgb_to_d24s8_frag_spv.h" #include "video_core/host_shaders/convert_abgr8_srgb_to_d24s8_frag_spv.h"
#include "video_core/host_shaders/convert_abgr8_to_r8_frag_spv.h"
#include "video_core/host_shaders/convert_rgba8_to_bgra8_frag_spv.h" #include "video_core/host_shaders/convert_rgba8_to_bgra8_frag_spv.h"
#include "video_core/host_shaders/convert_yuv420_to_rgb_comp_spv.h" #include "video_core/host_shaders/convert_yuv420_to_rgb_comp_spv.h"
#include "video_core/host_shaders/convert_rgb_to_yuv420_comp_spv.h" #include "video_core/host_shaders/convert_rgb_to_yuv420_comp_spv.h"
@ -444,7 +446,8 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
one_texture_set_layout.address(), one_texture_set_layout.address(),
PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstants)>))), PUSH_CONSTANT_RANGE<VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstants)>
))),
two_textures_pipeline_layout( two_textures_pipeline_layout(
device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo(
two_textures_set_layout.address(), two_textures_set_layout.address(),
@ -461,6 +464,8 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
convert_abgr8_to_d32f_frag(BuildShader(device, CONVERT_ABGR8_TO_D32F_FRAG_SPV)), convert_abgr8_to_d32f_frag(BuildShader(device, CONVERT_ABGR8_TO_D32F_FRAG_SPV)),
convert_abgr8_to_r8_frag(BuildShader(device, CONVERT_ABGR8_TO_R8_FRAG_SPV)),
convert_r8_to_abgr8_frag(BuildShader(device, CONVERT_R8_TO_ABGR8_FRAG_SPV)),
convert_d32f_to_abgr8_frag(BuildShader(device, CONVERT_D32F_TO_ABGR8_FRAG_SPV)), convert_d32f_to_abgr8_frag(BuildShader(device, CONVERT_D32F_TO_ABGR8_FRAG_SPV)),
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)), convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
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)),
@ -588,6 +593,20 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
} }
void BlitImageHelper::ConvertR8ToABGR8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_r8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
convert_r8_to_abgr8_frag);
Convert(*convert_r8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertABGR8ToR8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
ConvertPipelineColorTargetEx(convert_abgr8_to_r8_pipeline, dst_framebuffer->RenderPass(),
convert_abgr8_to_r8_frag);
Convert(*convert_abgr8_to_r8_pipeline, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) { const ImageView& src_image_view) {
ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
@ -687,7 +706,7 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
const VkExtent2D extent = GetConversionExtent(src_image_view); const VkExtent2D extent = GetConversionExtent(src_image_view);
scheduler.RequestRenderpass(dst_framebuffer); scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) { scheduler.Record([pipeline, layout, sampler, src_view, extent, this, dst_framebuffer](vk::CommandBuffer cmdbuf) {
const VkOffset2D offset{ const VkOffset2D offset{
.x = 0, .x = 0,
.y = 0, .y = 0,
@ -704,10 +723,17 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
.offset = offset, .offset = offset,
.extent = extent, .extent = extent,
}; };
const PushConstants push_constants{ const PushConstants push_constants_vertex{
.tex_scale = {viewport.width, viewport.height}, .tex_scale = {viewport.width, viewport.height},
.tex_offset = {0.0f, 0.0f}, .tex_offset = {0.0f, 0.0f},
}; };
const PushConstants push_constants_frag{
.tex_scale = {
static_cast<float>(dst_framebuffer->RenderArea().width),
static_cast<float>(dst_framebuffer->RenderArea().height)
},
.tex_offset = {0.0f, 0.0f},
};
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view); UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
@ -717,7 +743,8 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
nullptr); nullptr);
cmdbuf.SetViewport(0, viewport); cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor); cmdbuf.SetScissor(0, scissor);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants_vertex);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants_frag);
cmdbuf.Draw(3, 1, 0, 0); cmdbuf.Draw(3, 1, 0, 0);
}); });
scheduler.InvalidateState(); scheduler.InvalidateState();

View file

@ -65,6 +65,10 @@ public:
void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertR8ToABGR8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8ToR8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
void ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); void ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
@ -144,6 +148,8 @@ private:
vk::ShaderModule convert_float_to_depth_frag; vk::ShaderModule convert_float_to_depth_frag;
vk::ShaderModule convert_abgr8_to_d24s8_frag; vk::ShaderModule convert_abgr8_to_d24s8_frag;
vk::ShaderModule convert_abgr8_to_d32f_frag; vk::ShaderModule convert_abgr8_to_d32f_frag;
vk::ShaderModule convert_abgr8_to_r8_frag;
vk::ShaderModule convert_r8_to_abgr8_frag;
vk::ShaderModule convert_d32f_to_abgr8_frag; vk::ShaderModule convert_d32f_to_abgr8_frag;
vk::ShaderModule convert_d24s8_to_abgr8_frag; vk::ShaderModule convert_d24s8_to_abgr8_frag;
vk::ShaderModule convert_s8d24_to_abgr8_frag; vk::ShaderModule convert_s8d24_to_abgr8_frag;
@ -176,6 +182,8 @@ private:
vk::Pipeline convert_d32f_to_abgr8_pipeline; vk::Pipeline convert_d32f_to_abgr8_pipeline;
vk::Pipeline convert_d24s8_to_abgr8_pipeline; vk::Pipeline convert_d24s8_to_abgr8_pipeline;
vk::Pipeline convert_s8d24_to_abgr8_pipeline; vk::Pipeline convert_s8d24_to_abgr8_pipeline;
vk::Pipeline convert_r8_to_abgr8_pipeline;
vk::Pipeline convert_abgr8_to_r8_pipeline;
vk::Pipeline convert_abgr8_srgb_to_d24s8_pipeline; vk::Pipeline convert_abgr8_srgb_to_d24s8_pipeline;
vk::Pipeline convert_rgba_to_bgra_pipeline; vk::Pipeline convert_rgba_to_bgra_pipeline;
vk::Pipeline convert_yuv420_to_rgb_pipeline; vk::Pipeline convert_yuv420_to_rgb_pipeline;

View file

@ -518,6 +518,14 @@ void RasterizerVulkan::DispatchCompute() {
} }
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
static constexpr VkMemoryBarrier READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
};
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, READ_BARRIER); });
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); }); scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
} }

View file

@ -1219,8 +1219,16 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view); return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view);
} }
break; break;
case PixelFormat::R8_UNORM:
if (src_view.format == PixelFormat::A8B8G8R8_UNORM) {
return blit_image_helper.ConvertABGR8ToR8(dst, src_view);
}
break;
case PixelFormat::A8B8G8R8_UNORM: case PixelFormat::A8B8G8R8_UNORM:
if (src_view.format == PixelFormat::R8_UNORM) {
return blit_image_helper.ConvertR8ToABGR8(dst, src_view);
}
break;
case PixelFormat::A8B8G8R8_SNORM: case PixelFormat::A8B8G8R8_SNORM:
case PixelFormat::A8B8G8R8_SINT: case PixelFormat::A8B8G8R8_SINT:
case PixelFormat::A8B8G8R8_UINT: case PixelFormat::A8B8G8R8_UINT:
@ -1232,7 +1240,6 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
case PixelFormat::A2R10G10B10_UNORM: case PixelFormat::A2R10G10B10_UNORM:
case PixelFormat::A1B5G5R5_UNORM: case PixelFormat::A1B5G5R5_UNORM:
case PixelFormat::A5B5G5R1_UNORM: case PixelFormat::A5B5G5R1_UNORM:
case PixelFormat::R8_UNORM:
case PixelFormat::R8_SNORM: case PixelFormat::R8_SNORM:
case PixelFormat::R8_SINT: case PixelFormat::R8_SINT:
case PixelFormat::R8_UINT: case PixelFormat::R8_UINT:
@ -1325,6 +1332,7 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
default: default:
break; break;
} }
LOG_WARNING(Render_Vulkan, "Unimplemented texture conversion from {} to {} format type", src_view.format, dst_view.format);
} }
VkFormat TextureCacheRuntime::GetSupportedFormat(VkFormat requested_format, VkFormat TextureCacheRuntime::GetSupportedFormat(VkFormat requested_format,

View file

@ -237,6 +237,37 @@ SurfaceType GetFormatType(PixelFormat pixel_format) {
return SurfaceType::Invalid; return SurfaceType::Invalid;
} }
bool HasAlpha(PixelFormat pixel_format) {
switch (pixel_format) {
case PixelFormat::A8B8G8R8_UNORM:
case PixelFormat::A8B8G8R8_SNORM:
case PixelFormat::A8B8G8R8_SINT:
case PixelFormat::A8B8G8R8_UINT:
case PixelFormat::A1R5G5B5_UNORM:
case PixelFormat::A2B10G10R10_UNORM:
case PixelFormat::A2B10G10R10_UINT:
case PixelFormat::A2R10G10B10_UNORM:
case PixelFormat::A1B5G5R5_UNORM:
case PixelFormat::A5B5G5R1_UNORM:
case PixelFormat::R16G16B16A16_FLOAT:
case PixelFormat::R16G16B16A16_UNORM:
case PixelFormat::R16G16B16A16_SNORM:
case PixelFormat::R16G16B16A16_SINT:
case PixelFormat::R16G16B16A16_UINT:
case PixelFormat::R32G32B32A32_UINT:
case PixelFormat::BC1_RGBA_UNORM:
case PixelFormat::B8G8R8A8_UNORM:
case PixelFormat::R32G32B32A32_FLOAT:
case PixelFormat::R32G32B32A32_SINT:
case PixelFormat::A8B8G8R8_SRGB:
case PixelFormat::BC1_RGBA_SRGB:
case PixelFormat::A4B4G4R4_UNORM:
return true;
default:
return false;
}
}
bool IsPixelFormatASTC(PixelFormat format) { bool IsPixelFormatASTC(PixelFormat format) {
switch (format) { switch (format) {
case PixelFormat::ASTC_2D_4X4_UNORM: case PixelFormat::ASTC_2D_4X4_UNORM:

View file

@ -503,6 +503,8 @@ PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format);
SurfaceType GetFormatType(PixelFormat pixel_format); SurfaceType GetFormatType(PixelFormat pixel_format);
bool HasAlpha(PixelFormat pixel_format);
bool IsPixelFormatASTC(PixelFormat format); bool IsPixelFormatASTC(PixelFormat format);
bool IsPixelFormatBCn(PixelFormat format); bool IsPixelFormatBCn(PixelFormat format);

View file

@ -26,6 +26,7 @@ namespace VideoCommon {
using Tegra::Texture::TICEntry; using Tegra::Texture::TICEntry;
using Tegra::Texture::TSCEntry; using Tegra::Texture::TSCEntry;
using VideoCore::Surface::GetFormatType; using VideoCore::Surface::GetFormatType;
using VideoCore::Surface::HasAlpha;
using VideoCore::Surface::PixelFormat; using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::SurfaceType; using VideoCore::Surface::SurfaceType;
using namespace Common::Literals; using namespace Common::Literals;
@ -2398,7 +2399,7 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
} }
const auto dst_format_type = GetFormatType(dst.info.format); const auto dst_format_type = GetFormatType(dst.info.format);
const auto src_format_type = GetFormatType(src.info.format); const auto src_format_type = GetFormatType(src.info.format);
if (src_format_type == dst_format_type) { if (src_format_type == dst_format_type && HasAlpha(src.info.format) == HasAlpha(dst.info.format)) {
if constexpr (HAS_EMULATED_COPIES) { if constexpr (HAS_EMULATED_COPIES) {
if (!runtime.CanImageBeCopied(dst, src)) { if (!runtime.CanImageBeCopied(dst, src)) {
return runtime.EmulateCopyImage(dst, src, copies); return runtime.EmulateCopyImage(dst, src, copies);
@ -2406,8 +2407,8 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
} }
return runtime.CopyImage(dst, src, copies); return runtime.CopyImage(dst, src, copies);
} }
UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D); UNIMPLEMENTED_IF(dst.info.type != ImageType::e2D && dst.info.type != ImageType::Linear);
UNIMPLEMENTED_IF(src.info.type != ImageType::e2D); UNIMPLEMENTED_IF(src.info.type != ImageType::e2D && dst.info.type != ImageType::Linear);
if (runtime.ShouldReinterpret(dst, src)) { if (runtime.ShouldReinterpret(dst, src)) {
return runtime.ReinterpretImage(dst, src, copies); return runtime.ReinterpretImage(dst, src, copies);
} }