mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-29 11:06:07 +00:00
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
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:
parent
5a071f3137
commit
8e08756b6e
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue