mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-08 00:58:43 +00:00
renderer_vulkan: skip redundant FCE and FMask decompression passes
This commit is contained in:
parent
2b5983844d
commit
9982f1be6f
3 changed files with 44 additions and 2 deletions
|
@ -606,6 +606,20 @@ struct Liverpool {
|
||||||
BitField<30, 1, u32> enable;
|
BitField<30, 1, u32> enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union ColorControl {
|
||||||
|
enum class OperationMode : u32 {
|
||||||
|
Disable = 0u,
|
||||||
|
Normal = 1u,
|
||||||
|
EliminateFastClear = 2u,
|
||||||
|
Resolve = 3u,
|
||||||
|
FmaskDecompress = 5u,
|
||||||
|
};
|
||||||
|
|
||||||
|
BitField<3, 1, u32> degamma_enable;
|
||||||
|
BitField<4, 3, OperationMode> mode;
|
||||||
|
BitField<16, 8, u32> rop3;
|
||||||
|
};
|
||||||
|
|
||||||
struct ColorBuffer {
|
struct ColorBuffer {
|
||||||
enum class EndianSwap : u32 {
|
enum class EndianSwap : u32 {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -825,7 +839,8 @@ struct Liverpool {
|
||||||
u32 draw_initiator;
|
u32 draw_initiator;
|
||||||
INSERT_PADDING_WORDS(0xA200 - 0xA1F9 - 4);
|
INSERT_PADDING_WORDS(0xA200 - 0xA1F9 - 4);
|
||||||
DepthControl depth_control;
|
DepthControl depth_control;
|
||||||
INSERT_PADDING_WORDS(2);
|
INSERT_PADDING_WORDS(1);
|
||||||
|
ColorControl color_control;
|
||||||
DepthBufferControl depth_buffer_control;
|
DepthBufferControl depth_buffer_control;
|
||||||
ClipperControl clipper_control;
|
ClipperControl clipper_control;
|
||||||
PolygonControl polygon_control;
|
PolygonControl polygon_control;
|
||||||
|
@ -995,6 +1010,7 @@ static_assert(GFX6_3D_REG_INDEX(blend_control) == 0xA1E0);
|
||||||
static_assert(GFX6_3D_REG_INDEX(index_base_address) == 0xA1F9);
|
static_assert(GFX6_3D_REG_INDEX(index_base_address) == 0xA1F9);
|
||||||
static_assert(GFX6_3D_REG_INDEX(draw_initiator) == 0xA1FC);
|
static_assert(GFX6_3D_REG_INDEX(draw_initiator) == 0xA1FC);
|
||||||
static_assert(GFX6_3D_REG_INDEX(depth_control) == 0xA200);
|
static_assert(GFX6_3D_REG_INDEX(depth_control) == 0xA200);
|
||||||
|
static_assert(GFX6_3D_REG_INDEX(color_control) == 0xA202);
|
||||||
static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204);
|
static_assert(GFX6_3D_REG_INDEX(clipper_control) == 0xA204);
|
||||||
static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206);
|
static_assert(GFX6_3D_REG_INDEX(viewport_control) == 0xA206);
|
||||||
static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207);
|
static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207);
|
||||||
|
|
|
@ -120,6 +120,11 @@ void PipelineCache::RefreshGraphicsKey() {
|
||||||
key.depth_format = LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format);
|
key.depth_format = LiverpoolToVK::DepthFormat(db.z_info.format, db.stencil_info.format);
|
||||||
key.depth.depth_enable.Assign(key.depth_format != vk::Format::eUndefined);
|
key.depth.depth_enable.Assign(key.depth_format != vk::Format::eUndefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should be a check for `OperationMode::Disable` once we emulate HW state init packet
|
||||||
|
// sent by system software.
|
||||||
|
const auto skip_cb_binding = false;
|
||||||
|
|
||||||
// `RenderingInfo` is assumed to be initialized with a contiguous array of valid color
|
// `RenderingInfo` is assumed to be initialized with a contiguous array of valid color
|
||||||
// attachments. This might be not a case as HW color buffers can be bound in an arbitrary order.
|
// 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
|
// We need to do some arrays compaction at this stage
|
||||||
|
@ -129,7 +134,7 @@ void PipelineCache::RefreshGraphicsKey() {
|
||||||
int remapped_cb{};
|
int remapped_cb{};
|
||||||
for (auto cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) {
|
for (auto cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) {
|
||||||
auto const& col_buf = regs.color_buffers[cb];
|
auto const& col_buf = regs.color_buffers[cb];
|
||||||
if (!col_buf) {
|
if (!col_buf || skip_cb_binding) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto base_format =
|
const auto base_format =
|
||||||
|
@ -160,6 +165,19 @@ void PipelineCache::RefreshGraphicsKey() {
|
||||||
std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
|
std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
|
||||||
const auto& regs = liverpool->regs;
|
const auto& regs = liverpool->regs;
|
||||||
|
|
||||||
|
// 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 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {};
|
||||||
|
}
|
||||||
|
|
||||||
u32 binding{};
|
u32 binding{};
|
||||||
std::array<Shader::IR::Program, MaxShaderStages> programs;
|
std::array<Shader::IR::Program, MaxShaderStages> programs;
|
||||||
std::array<const Shader::Info*, MaxShaderStages> infos{};
|
std::array<const Shader::Info*, MaxShaderStages> infos{};
|
||||||
|
|
|
@ -40,6 +40,10 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
|
||||||
const auto& regs = liverpool->regs;
|
const auto& regs = liverpool->regs;
|
||||||
const u32 num_indices = SetupIndexBuffer(is_indexed, index_offset);
|
const u32 num_indices = SetupIndexBuffer(is_indexed, index_offset);
|
||||||
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
||||||
|
if (!pipeline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
||||||
|
|
||||||
boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers>
|
boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers>
|
||||||
|
@ -117,6 +121,10 @@ void Rasterizer::DispatchDirect() {
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
const auto& cs_program = liverpool->regs.cs_program;
|
const auto& cs_program = liverpool->regs.cs_program;
|
||||||
const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline();
|
const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline();
|
||||||
|
if (!pipeline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
||||||
|
|
||||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
|
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue