mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-01 12:46:01 +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;
|
PipelineCache::~PipelineCache() = default;
|
||||||
|
|
||||||
const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() {
|
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()) {
|
if (!RefreshGraphicsKey()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,43 @@ void Rasterizer::CpSync() {
|
||||||
vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {});
|
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) {
|
void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
|
||||||
RENDERER_TRACE;
|
RENDERER_TRACE;
|
||||||
|
|
||||||
|
if (!FilterDraw()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
const auto& regs = liverpool->regs;
|
const auto& regs = liverpool->regs;
|
||||||
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
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) {
|
void Rasterizer::DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size) {
|
||||||
RENDERER_TRACE;
|
RENDERER_TRACE;
|
||||||
|
|
||||||
|
if (!FilterDraw()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
const auto& regs = liverpool->regs;
|
const auto& regs = liverpool->regs;
|
||||||
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
||||||
|
@ -258,6 +296,54 @@ void Rasterizer::BeginRendering(const GraphicsPipeline& pipeline) {
|
||||||
scheduler.BeginRendering(state);
|
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) {
|
void Rasterizer::InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds) {
|
||||||
buffer_cache.InlineData(address, value, num_bytes, is_gds);
|
buffer_cache.InlineData(address, value, num_bytes, is_gds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,11 +54,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BeginRendering(const GraphicsPipeline& pipeline);
|
void BeginRendering(const GraphicsPipeline& pipeline);
|
||||||
|
void Resolve();
|
||||||
|
|
||||||
void UpdateDynamicState(const GraphicsPipeline& pipeline);
|
void UpdateDynamicState(const GraphicsPipeline& pipeline);
|
||||||
void UpdateViewportScissorState();
|
void UpdateViewportScissorState();
|
||||||
void UpdateDepthStencilState();
|
void UpdateDepthStencilState();
|
||||||
|
|
||||||
|
bool FilterDraw();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
|
|
Loading…
Reference in a new issue