renderer_vulkan: initial CMask support

This commit is contained in:
psucien 2024-06-26 12:22:41 +02:00
parent ac6a60d809
commit 2b5983844d
4 changed files with 81 additions and 3 deletions

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "video_core/amdgpu/pixel_format.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
namespace Vulkan::LiverpoolToVK {
@ -381,6 +382,13 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format,
case vk::Format::eB8G8R8A8Srgb:
return is_vo_surface ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
}
} else {
if (is_vo_surface && base_format == vk::Format::eR8G8B8A8Srgb) {
return vk::Format::eR8G8B8A8Unorm;
}
if (is_vo_surface && base_format == vk::Format::eB8G8R8A8Srgb) {
return vk::Format::eB8G8R8A8Unorm;
}
}
return base_format;
}
@ -422,4 +430,56 @@ void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) {
}
}
static constexpr float U8ToUnorm(u8 v) {
static constexpr auto c = 1.0f / 255.0f;
return float(v * c);
}
vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) {
const auto comp_swap = color_buffer.info.comp_swap.Value();
ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard ||
comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate,
"Unsupported component swap mode {}", static_cast<u32>(comp_swap));
const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate;
const auto& c0 = color_buffer.clear_word0;
const auto& c1 = color_buffer.clear_word1;
const auto num_bits = AmdGpu::NumBits(color_buffer.info.format);
vk::ClearColorValue color{};
switch (color_buffer.info.number_type) {
case AmdGpu::NumberFormat::Snorm:
[[fallthrough]];
case AmdGpu::NumberFormat::SnormNz:
[[fallthrough]];
case AmdGpu::NumberFormat::Unorm:
[[fallthrough]];
case AmdGpu::NumberFormat::Srgb: {
switch (num_bits) {
case 32: {
color.float32 = std::array{
U8ToUnorm((c0 >> (comp_swap_alt ? 16 : 0)) & 0xff),
U8ToUnorm((c0 >> 8) & 0xff),
U8ToUnorm((c0 >> (comp_swap_alt ? 0 : 16)) & 0xff),
U8ToUnorm((c0 >> 24) & 0xff),
};
break;
}
default: {
LOG_ERROR(Render_Vulkan, "Missing clear color conversion for bits {}", num_bits);
break;
}
}
break;
}
default: {
LOG_ERROR(Render_Vulkan, "Missing clear color conversion for type {}",
color_buffer.info.number_type.Value());
break;
}
}
return {.color = color};
}
} // namespace Vulkan::LiverpoolToVK

View file

@ -46,6 +46,10 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format,
vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format,
Liverpool::DepthBuffer::StencilFormat stencil_format);
vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer);
vk::ClearValue DepthClearValue();
void EmitQuadToTriangleListIndices(u8* out_indices, u32 num_vertices);
} // namespace Vulkan::LiverpoolToVK

View file

@ -109,6 +109,15 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s
: vk::DescriptorType::eUniformBuffer,
.pBufferInfo = &buffer_infos.back(),
});
if (buffer.is_storage) {
// In most of the cases we can skip the whole dispatch when meta is written
texture_cache.TouchMeta(addr, true);
} else {
if (texture_cache.IsMeta(addr)) {
LOG_WARNING(Render_Vulkan, "Unexpected meta data read by a CS shader");
}
}
}
for (const auto& image : info.images) {

View file

@ -44,8 +44,6 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers>
color_attachments{};
vk::RenderingAttachmentInfo depth_attachment{};
u32 num_depth_attachments{};
for (auto col_buf_id = 0u; col_buf_id < Liverpool::NumColorBuffers; ++col_buf_id) {
const auto& col_buf = regs.color_buffers[col_buf_id];
if (!col_buf) {
@ -55,13 +53,20 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
const auto& hint = liverpool->last_cb_extent[col_buf_id];
const auto& image_view = texture_cache.RenderTarget(col_buf, hint);
const bool is_clear = texture_cache.IsMetaCleared(col_buf.CmaskAddress());
color_attachments.push_back({
.imageView = *image_view.image_view,
.imageLayout = vk::ImageLayout::eGeneral,
.loadOp = vk::AttachmentLoadOp::eLoad,
.loadOp = is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore,
.clearValue =
is_clear ? LiverpoolToVK::ColorBufferClearValue(col_buf) : vk::ClearValue{},
});
texture_cache.TouchMeta(col_buf.CmaskAddress(), false);
}
vk::RenderingAttachmentInfo depth_attachment{};
u32 num_depth_attachments{};
if (pipeline->IsDepthEnabled() && regs.depth_buffer.Address() != 0) {
const bool is_clear = regs.depth_render_control.depth_clear_enable;
const auto& image_view =