Handle color control mode resolve (#1413)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions

This commit is contained in:
Lander Gallastegi 2024-10-20 12:14:01 +02:00 committed by GitHub
parent 5a071f3137
commit 8e08756b6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 89 additions and 20 deletions

View file

@ -181,26 +181,6 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
PipelineCache::~PipelineCache() = default;
const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() {
const auto& regs = liverpool->regs;
// Tessellation is unsupported so skip the draw to avoid locking up the driver.
if (regs.primitive_type == AmdGpu::PrimitiveType::PatchPrimitive) {
return nullptr;
}
// There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an
// actual draw hence can skip pipeline creation.
if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) {
LOG_TRACE(Render_Vulkan, "FCE pass skipped");
return nullptr;
}
if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) {
// TODO: check for a valid MRT1 to promote the draw to the resolve pass.
LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped");
return nullptr;
}
if (regs.primitive_type == AmdGpu::PrimitiveType::None) {
LOG_TRACE(Render_Vulkan, "Primitive type 'None' skipped");
return nullptr;
}
if (!RefreshGraphicsKey()) {
return nullptr;
}

View file

@ -41,9 +41,43 @@ void Rasterizer::CpSync() {
vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {});
}
bool Rasterizer::FilterDraw() {
const auto& regs = liverpool->regs;
// Tessellation is unsupported so skip the draw to avoid locking up the driver.
if (regs.primitive_type == AmdGpu::PrimitiveType::PatchPrimitive) {
return false;
}
// There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an
// actual draw hence can skip pipeline creation.
if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) {
LOG_TRACE(Render_Vulkan, "FCE pass skipped");
return false;
}
if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) {
// TODO: check for a valid MRT1 to promote the draw to the resolve pass.
LOG_TRACE(Render_Vulkan, "FMask decompression pass skipped");
return false;
}
if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::Resolve) {
LOG_TRACE(Render_Vulkan, "Resolve pass");
Resolve();
return false;
}
if (regs.primitive_type == AmdGpu::PrimitiveType::None) {
LOG_TRACE(Render_Vulkan, "Primitive type 'None' skipped");
return false;
}
return true;
}
void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
RENDERER_TRACE;
if (!FilterDraw()) {
return;
}
const auto cmdbuf = scheduler.CommandBuffer();
const auto& regs = liverpool->regs;
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
@ -80,6 +114,10 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
void Rasterizer::DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size) {
RENDERER_TRACE;
if (!FilterDraw()) {
return;
}
const auto cmdbuf = scheduler.CommandBuffer();
const auto& regs = liverpool->regs;
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
@ -258,6 +296,54 @@ void Rasterizer::BeginRendering(const GraphicsPipeline& pipeline) {
scheduler.BeginRendering(state);
}
void Rasterizer::Resolve() {
const auto cmdbuf = scheduler.CommandBuffer();
// Read from MRT0, average all samples, and write to MRT1, which is one-sample
const auto& mrt0_hint = liverpool->last_cb_extent[0];
const auto& mrt1_hint = liverpool->last_cb_extent[1];
VideoCore::ImageInfo mrt0_info{liverpool->regs.color_buffers[0], mrt0_hint};
VideoCore::ImageInfo mrt1_info{liverpool->regs.color_buffers[1], mrt1_hint};
auto& mrt0_image = texture_cache.GetImage(texture_cache.FindImage(mrt0_info));
auto& mrt1_image = texture_cache.GetImage(texture_cache.FindImage(mrt1_info));
VideoCore::SubresourceRange mrt0_range;
mrt0_range.base.layer = liverpool->regs.color_buffers[0].view.slice_start;
mrt0_range.extent.layers = liverpool->regs.color_buffers[0].NumSlices() - mrt0_range.base.layer;
VideoCore::SubresourceRange mrt1_range;
mrt1_range.base.layer = liverpool->regs.color_buffers[1].view.slice_start;
mrt1_range.extent.layers = liverpool->regs.color_buffers[1].NumSlices() - mrt1_range.base.layer;
vk::ImageResolve region = {
.srcSubresource =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.mipLevel = 0,
.baseArrayLayer = mrt0_range.base.layer,
.layerCount = mrt0_range.extent.layers,
},
.srcOffset = {0, 0, 0},
.dstSubresource =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.mipLevel = 0,
.baseArrayLayer = mrt1_range.base.layer,
.layerCount = mrt1_range.extent.layers,
},
.dstOffset = {0, 0, 0},
.extent = {mrt1_image.info.size.width, mrt1_image.info.size.height, 1},
};
mrt0_image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead,
mrt0_range);
mrt1_image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite,
mrt1_range);
cmdbuf.resolveImage(mrt0_image.image, vk::ImageLayout::eTransferSrcOptimal, mrt1_image.image,
vk::ImageLayout::eTransferDstOptimal, region);
}
void Rasterizer::InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds) {
buffer_cache.InlineData(address, value, num_bytes, is_gds);
}

View file

@ -54,11 +54,14 @@ public:
private:
void BeginRendering(const GraphicsPipeline& pipeline);
void Resolve();
void UpdateDynamicState(const GraphicsPipeline& pipeline);
void UpdateViewportScissorState();
void UpdateDepthStencilState();
bool FilterDraw();
private:
const Instance& instance;
Scheduler& scheduler;