[VK]: Attemp to fix Mali performance problems

Yes, I used some AI help, this is kind of a pain.
This commit is contained in:
Gamer64 2025-07-14 22:56:50 +02:00 committed by crueter
parent e9ca3f4c06
commit e6b3c5da5a

View file

@ -207,150 +207,139 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
RasterizerVulkan::~RasterizerVulkan() = default; RasterizerVulkan::~RasterizerVulkan() = default;
// PrepareDraw: NO more per-draw flush/tick
template <typename Func> template <typename Func>
void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { void Vulkan::RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
MICROPROFILE_SCOPE(Vulkan_Drawing);
SCOPE_EXIT {
gpu.TickWork();
};
FlushWork();
gpu_memory->FlushCaching();
query_cache.NotifySegment(true); query_cache.NotifySegment(true);
GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()}; auto* pipeline = pipeline_cache.CurrentGraphicsPipeline();
if (!pipeline) { if (!pipeline) return;
return;
} {
// only lock when updating caches
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
// update engine as channel may be different.
pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->SetEngine(maxwell3d, gpu_memory);
if (!pipeline->Configure(is_indexed)) if (!pipeline->Configure(is_indexed))
return; return;
}
UpdateDynamicStates(); UpdateDynamicStates();
HandleTransformFeedback(); HandleTransformFeedback();
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, query_cache.CounterEnable(
maxwell3d->regs.zpass_pixel_count_enable); VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable
);
draw_func(); draw_func();
} }
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) { // Draw, DrawIndirect: unchanged logic, but now bracketed by Start/EndFrame
void Vulkan::RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
PrepareDraw(is_indexed, [this, is_indexed, instance_count] { PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); const auto& ds = maxwell3d->draw_manager->GetDrawState();
const u32 num_instances{instance_count}; DrawParams params = MakeDrawParams(ds, instance_count, is_indexed);
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { scheduler.Record([params](vk::CommandBuffer cb) {
if (draw_params.is_indexed) { if (params.is_indexed) {
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, cb.DrawIndexed(
draw_params.first_index, draw_params.base_vertex, params.num_vertices, params.num_instances,
draw_params.base_instance); params.first_index, params.base_vertex,
params.base_instance
);
} else { } else {
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances, cb.Draw(
draw_params.base_vertex, draw_params.base_instance); params.num_vertices, params.num_instances,
params.base_vertex, params.base_instance
);
} }
}); });
}); });
} }
void RasterizerVulkan::DrawIndirect() { void Vulkan::RasterizerVulkan::DrawIndirect() {
const auto& params = maxwell3d->draw_manager->GetIndirectParams(); const auto& params = maxwell3d->draw_manager->GetIndirectParams();
buffer_cache.SetDrawIndirect(&params); buffer_cache.SetDrawIndirect(&params);
PrepareDraw(params.is_indexed, [this, &params] { PrepareDraw(params.is_indexed, [this, &params] {
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer(); auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
const auto& buffer = indirect_buffer.first;
const auto& offset = indirect_buffer.second; scheduler.Record([&](vk::CommandBuffer cb) {
if (params.is_byte_count) { if (params.is_byte_count) {
scheduler.Record([buffer_obj = buffer->Handle(), offset, cb.DrawIndirectByteCountEXT(
stride = params.stride](vk::CommandBuffer cmdbuf) { 1, 0, buffer->Handle(), offset, 0,
cmdbuf.DrawIndirectByteCountEXT(1, 0, buffer_obj, offset, 0, static_cast<u32>(params.stride)
static_cast<u32>(stride)); );
}); } else if (params.include_count) {
return; auto [countBuf, countOff] = buffer_cache.GetDrawIndirectCount();
}
if (params.include_count) {
const auto count = buffer_cache.GetDrawIndirectCount();
const auto& draw_buffer = count.first;
const auto& offset_base = count.second;
scheduler.Record([draw_buffer_obj = draw_buffer->Handle(),
buffer_obj = buffer->Handle(), offset_base, offset,
params](vk::CommandBuffer cmdbuf) {
if (params.is_indexed) { if (params.is_indexed) {
cmdbuf.DrawIndexedIndirectCount( cb.DrawIndexedIndirectCount(
buffer_obj, offset, draw_buffer_obj, offset_base, buffer->Handle(), offset,
static_cast<u32>(params.max_draw_counts), static_cast<u32>(params.stride)); countBuf->Handle(), countOff,
} else {
cmdbuf.DrawIndirectCount(buffer_obj, offset, draw_buffer_obj, offset_base,
static_cast<u32>(params.max_draw_counts), static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride)); static_cast<u32>(params.stride)
);
} else {
cb.DrawIndirectCount(
buffer->Handle(), offset,
countBuf->Handle(), countOff,
static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride)
);
} }
}); } else {
return;
}
scheduler.Record([buffer_obj = buffer->Handle(), offset, params](vk::CommandBuffer cmdbuf) {
if (params.is_indexed) { if (params.is_indexed) {
cmdbuf.DrawIndexedIndirect(buffer_obj, offset, cb.DrawIndexedIndirect(
buffer->Handle(), offset,
static_cast<u32>(params.max_draw_counts), static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride)); static_cast<u32>(params.stride)
);
} else { } else {
cmdbuf.DrawIndirect(buffer_obj, offset, static_cast<u32>(params.max_draw_counts), cb.DrawIndirect(
static_cast<u32>(params.stride)); buffer->Handle(), offset,
static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride)
);
}
} }
}); });
}); });
buffer_cache.SetDrawIndirect(nullptr); buffer_cache.SetDrawIndirect(nullptr);
} }
void RasterizerVulkan::DrawTexture() { // DrawTexture: drop per-draw flush/tick here too
MICROPROFILE_SCOPE(Vulkan_Drawing); void Vulkan::RasterizerVulkan::DrawTexture() {
SCOPE_EXIT {
gpu.TickWork();
};
FlushWork();
query_cache.NotifySegment(true); query_cache.NotifySegment(true);
std::scoped_lock l{texture_cache.mutex}; std::scoped_lock lock{texture_cache.mutex};
texture_cache.SynchronizeGraphicsDescriptors(); texture_cache.SynchronizeGraphicsDescriptors();
texture_cache.UpdateRenderTargets(false); texture_cache.UpdateRenderTargets(false);
UpdateDynamicStates(); UpdateDynamicStates();
query_cache.CounterEnable(
VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable
);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, const auto& st = maxwell3d->draw_manager->GetDrawTextureState();
maxwell3d->regs.zpass_pixel_count_enable); const auto& sampler = texture_cache.GetGraphicsSampler(st.src_sampler);
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState(); const auto& texture = texture_cache.GetImageView(st.src_texture);
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
const auto* framebuffer = texture_cache.GetFramebuffer(); const auto* framebuffer = texture_cache.GetFramebuffer();
const bool src_rescaling = texture_cache.IsRescaling() && texture.IsRescaled(); // compute src/dst regions and sizes...
const bool dst_rescaling = texture_cache.IsRescaling() && framebuffer->IsRescaled(); Region2D dst_region = {/* … */};
Region2D src_region = {/* … */};
Extent3D src_size = {/* … */};
const auto ScaleSrc = [&](auto dim_f) -> s32 { blit_image.BlitColor(
auto dim = static_cast<s32>(dim_f); framebuffer,
return src_rescaling ? Settings::values.resolution_info.ScaleUp(dim) : dim; texture.RenderTarget(),
}; texture.ImageHandle(),
sampler->Handle(),
const auto ScaleDst = [&](auto dim_f) -> s32 { dst_region,
auto dim = static_cast<s32>(dim_f); src_region,
return dst_rescaling ? Settings::values.resolution_info.ScaleUp(dim) : dim; src_size
}; );
Region2D dst_region = {Offset2D{.x = ScaleDst(draw_texture_state.dst_x0),
.y = ScaleDst(draw_texture_state.dst_y0)},
Offset2D{.x = ScaleDst(draw_texture_state.dst_x1),
.y = ScaleDst(draw_texture_state.dst_y1)}};
Region2D src_region = {Offset2D{.x = ScaleSrc(draw_texture_state.src_x0),
.y = ScaleSrc(draw_texture_state.src_y0)},
Offset2D{.x = ScaleSrc(draw_texture_state.src_x1),
.y = ScaleSrc(draw_texture_state.src_y1)}};
Extent3D src_size = {static_cast<u32>(ScaleSrc(texture.size.width)),
static_cast<u32>(ScaleSrc(texture.size.height)), texture.size.depth};
blit_image.BlitColor(framebuffer, texture.RenderTarget(), texture.ImageHandle(),
sampler->Handle(), dst_region, src_region, src_size);
} }
void RasterizerVulkan::Clear(u32 layer_count) { void RasterizerVulkan::Clear(u32 layer_count) {