mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 10:04:39 +00:00
vk_pipeline_cache: Add fallbacks for R8Srgb and B5G6R5 (#3264)
* vk_pipeline_cache: Add fallbacks for R8Srgb and B5G6R5 * blit_helper: Fix validation error * renderer_vulkan: Emulate B5G6R5 with swizzle
This commit is contained in:
parent
3019bfb978
commit
b56039b15a
@ -171,6 +171,7 @@ enum class MrtSwizzle : u8 {
|
|||||||
static constexpr u32 MaxColorBuffers = 8;
|
static constexpr u32 MaxColorBuffers = 8;
|
||||||
|
|
||||||
struct PsColorBuffer {
|
struct PsColorBuffer {
|
||||||
|
AmdGpu::DataFormat data_format : 6;
|
||||||
AmdGpu::NumberFormat num_format : 4;
|
AmdGpu::NumberFormat num_format : 4;
|
||||||
AmdGpu::NumberConversion num_conversion : 3;
|
AmdGpu::NumberConversion num_conversion : 3;
|
||||||
AmdGpu::Liverpool::ShaderExportFormat export_format : 4;
|
AmdGpu::Liverpool::ShaderExportFormat export_format : 4;
|
||||||
|
@ -248,6 +248,15 @@ constexpr CompMapping RemapSwizzle(const DataFormat format, const CompMapping sw
|
|||||||
result.a = swizzle.r;
|
result.a = swizzle.r;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
case DataFormat::Format5_6_5: {
|
||||||
|
// Remap to a more supported component order.
|
||||||
|
CompMapping result;
|
||||||
|
result.r = swizzle.b;
|
||||||
|
result.g = swizzle.g;
|
||||||
|
result.b = swizzle.r;
|
||||||
|
result.a = swizzle.a;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return swizzle;
|
return swizzle;
|
||||||
}
|
}
|
||||||
|
@ -671,7 +671,7 @@ std::span<const SurfaceFormatInfo> SurfaceFormats() {
|
|||||||
vk::Format::eR32G32B32A32Sfloat),
|
vk::Format::eR32G32B32A32Sfloat),
|
||||||
// 5_6_5
|
// 5_6_5
|
||||||
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_6_5, AmdGpu::NumberFormat::Unorm,
|
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_6_5, AmdGpu::NumberFormat::Unorm,
|
||||||
vk::Format::eB5G6R5UnormPack16),
|
vk::Format::eR5G6B5UnormPack16),
|
||||||
// 1_5_5_5
|
// 1_5_5_5
|
||||||
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm,
|
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm,
|
||||||
vk::Format::eA1R5G5B5UnormPack16),
|
vk::Format::eA1R5G5B5UnormPack16),
|
||||||
|
@ -244,9 +244,24 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
const auto depth_format =
|
const auto depth_format =
|
||||||
instance.GetSupportedFormat(LiverpoolToVK::DepthFormat(key.z_format, key.stencil_format),
|
instance.GetSupportedFormat(LiverpoolToVK::DepthFormat(key.z_format, key.stencil_format),
|
||||||
vk::FormatFeatureFlagBits2::eDepthStencilAttachment);
|
vk::FormatFeatureFlagBits2::eDepthStencilAttachment);
|
||||||
|
std::array<vk::Format, Shader::IR::NumRenderTargets> color_formats;
|
||||||
|
for (s32 i = 0; i < key.num_color_attachments; ++i) {
|
||||||
|
const auto& col_buf = key.color_buffers[i];
|
||||||
|
const auto format = LiverpoolToVK::SurfaceFormat(col_buf.data_format, col_buf.num_format);
|
||||||
|
const auto color_format =
|
||||||
|
instance.GetSupportedFormat(format, vk::FormatFeatureFlagBits2::eColorAttachment);
|
||||||
|
if (!instance.IsFormatSupported(color_format,
|
||||||
|
vk::FormatFeatureFlagBits2::eColorAttachment)) {
|
||||||
|
LOG_WARNING(Render_Vulkan,
|
||||||
|
"color buffer format {} does not support COLOR_ATTACHMENT_BIT",
|
||||||
|
vk::to_string(color_format));
|
||||||
|
}
|
||||||
|
color_formats[i] = color_format;
|
||||||
|
}
|
||||||
|
|
||||||
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = {
|
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = {
|
||||||
.colorAttachmentCount = key.num_color_attachments,
|
.colorAttachmentCount = key.num_color_attachments,
|
||||||
.pColorAttachmentFormats = key.color_formats.data(),
|
.pColorAttachmentFormats = color_formats.data(),
|
||||||
.depthAttachmentFormat = key.z_format != Liverpool::DepthBuffer::ZFormat::Invalid
|
.depthAttachmentFormat = key.z_format != Liverpool::DepthBuffer::ZFormat::Invalid
|
||||||
? depth_format
|
? depth_format
|
||||||
: vk::Format::eUndefined,
|
: vk::Format::eUndefined,
|
||||||
|
@ -36,7 +36,6 @@ struct GraphicsPipelineKey {
|
|||||||
std::array<vk::Format, MaxVertexBufferCount> vertex_buffer_formats;
|
std::array<vk::Format, MaxVertexBufferCount> vertex_buffer_formats;
|
||||||
u32 patch_control_points;
|
u32 patch_control_points;
|
||||||
u32 num_color_attachments;
|
u32 num_color_attachments;
|
||||||
std::array<vk::Format, Liverpool::NumColorBuffers> color_formats;
|
|
||||||
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
std::array<Shader::PsColorBuffer, Liverpool::NumColorBuffers> color_buffers;
|
||||||
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
|
||||||
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
|
||||||
|
@ -669,6 +669,12 @@ vk::Format Instance::GetSupportedFormat(const vk::Format format,
|
|||||||
if (IsFormatSupported(vk::Format::eD32SfloatS8Uint, flags)) {
|
if (IsFormatSupported(vk::Format::eD32SfloatS8Uint, flags)) {
|
||||||
return vk::Format::eD32SfloatS8Uint;
|
return vk::Format::eD32SfloatS8Uint;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case vk::Format::eR8Srgb:
|
||||||
|
if (IsFormatSupported(vk::Format::eR8Unorm, flags)) {
|
||||||
|
return vk::Format::eR8Unorm;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,6 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
// attachments. This might be not a case as HW color buffers can be bound in an arbitrary
|
// attachments. This might be not a case as HW color buffers can be bound in an arbitrary
|
||||||
// order. We need to do some arrays compaction at this stage
|
// order. We need to do some arrays compaction at this stage
|
||||||
key.num_color_attachments = 0;
|
key.num_color_attachments = 0;
|
||||||
key.color_formats.fill(vk::Format::eUndefined);
|
|
||||||
key.color_buffers.fill({});
|
key.color_buffers.fill({});
|
||||||
key.blend_controls.fill({});
|
key.blend_controls.fill({});
|
||||||
key.write_masks.fill({});
|
key.write_masks.fill({});
|
||||||
@ -351,16 +350,8 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8 ||
|
col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8 ||
|
||||||
col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8);
|
col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8);
|
||||||
|
|
||||||
const auto format =
|
|
||||||
LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt());
|
|
||||||
key.color_formats[remapped_cb] = format;
|
|
||||||
if (!instance.IsFormatSupported(format, vk::FormatFeatureFlagBits2::eColorAttachment)) {
|
|
||||||
LOG_WARNING(Render_Vulkan,
|
|
||||||
"color buffer format {} does not support COLOR_ATTACHMENT_BIT",
|
|
||||||
vk::to_string(format));
|
|
||||||
}
|
|
||||||
|
|
||||||
key.color_buffers[remapped_cb] = Shader::PsColorBuffer{
|
key.color_buffers[remapped_cb] = Shader::PsColorBuffer{
|
||||||
|
.data_format = col_buf.GetDataFmt(),
|
||||||
.num_format = col_buf.GetNumberFmt(),
|
.num_format = col_buf.GetNumberFmt(),
|
||||||
.num_conversion = col_buf.GetNumberConversion(),
|
.num_conversion = col_buf.GetNumberConversion(),
|
||||||
.export_format = regs.color_export_format.GetFormat(cb),
|
.export_format = regs.color_export_format.GetFormat(cb),
|
||||||
@ -479,9 +470,7 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
// Attachment is masked out by either color_target_mask or shader mrt_mask. In the case
|
// Attachment is masked out by either color_target_mask or shader mrt_mask. In the case
|
||||||
// of the latter we need to change format to undefined, and either way we need to
|
// of the latter we need to change format to undefined, and either way we need to
|
||||||
// increment the index for the null attachment binding.
|
// increment the index for the null attachment binding.
|
||||||
key.color_formats[remapped_cb] = vk::Format::eUndefined;
|
key.color_buffers[remapped_cb++] = {};
|
||||||
key.color_buffers[remapped_cb] = {};
|
|
||||||
++remapped_cb;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,13 +126,13 @@ void BlitHelper::BlitColorToMsDepth(Image& source, Image& dest) {
|
|||||||
.minDepth = 0.f,
|
.minDepth = 0.f,
|
||||||
.maxDepth = 1.f,
|
.maxDepth = 1.f,
|
||||||
};
|
};
|
||||||
cmdbuf.setViewport(0, viewport);
|
cmdbuf.setViewportWithCount(viewport);
|
||||||
|
|
||||||
const vk::Rect2D scissor = {
|
const vk::Rect2D scissor = {
|
||||||
.offset = {0, 0},
|
.offset = {0, 0},
|
||||||
.extent = {state.width, state.height},
|
.extent = {state.width, state.height},
|
||||||
};
|
};
|
||||||
cmdbuf.setScissor(0, scissor);
|
cmdbuf.setScissorWithCount(scissor);
|
||||||
|
|
||||||
cmdbuf.draw(3, 1, 0, 0);
|
cmdbuf.draw(3, 1, 0, 0);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) {
|
|||||||
if (info.IsDepthStencil()) {
|
if (info.IsDepthStencil()) {
|
||||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||||
} else {
|
} else {
|
||||||
if (!info.IsBlockCoded() && !info.IsPacked()) {
|
if (!info.IsBlockCoded()) {
|
||||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
}
|
}
|
||||||
// In cases where an image is created as a render/depth target and cleared with compute,
|
// In cases where an image is created as a render/depth target and cleared with compute,
|
||||||
|
@ -176,17 +176,6 @@ bool ImageInfo::IsBlockCoded() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageInfo::IsPacked() const {
|
|
||||||
switch (pixel_format) {
|
|
||||||
case vk::Format::eB5G5R5A1UnormPack16:
|
|
||||||
[[fallthrough]];
|
|
||||||
case vk::Format::eB5G6R5UnormPack16:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImageInfo::IsDepthStencil() const {
|
bool ImageInfo::IsDepthStencil() const {
|
||||||
switch (pixel_format) {
|
switch (pixel_format) {
|
||||||
case vk::Format::eD16Unorm:
|
case vk::Format::eD16Unorm:
|
||||||
|
@ -31,7 +31,6 @@ struct ImageInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsBlockCoded() const;
|
bool IsBlockCoded() const;
|
||||||
bool IsPacked() const;
|
|
||||||
bool IsDepthStencil() const;
|
bool IsDepthStencil() const;
|
||||||
bool HasStencil() const;
|
bool HasStencil() const;
|
||||||
|
|
||||||
|
@ -626,7 +626,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
|
|||||||
image_copy.push_back({
|
image_copy.push_back({
|
||||||
.bufferOffset = mip.offset,
|
.bufferOffset = mip.offset,
|
||||||
.bufferRowLength = mip_pitch,
|
.bufferRowLength = mip_pitch,
|
||||||
.bufferImageHeight = mip_height,
|
.bufferImageHeight = mip_height ? std::max(mip_height, 8U) : mip_height,
|
||||||
.imageSubresource{
|
.imageSubresource{
|
||||||
.aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
|
.aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
|
||||||
.mipLevel = m,
|
.mipLevel = m,
|
||||||
|
Loading…
Reference in New Issue
Block a user