mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-21 03:54:45 +00:00
driver: Make flip blocking
This commit is contained in:
parent
2e4f32a840
commit
502dc1cbf3
5 changed files with 20 additions and 20 deletions
|
@ -296,7 +296,7 @@ static void ResetSubmissionLock(Platform::InterruptId irq) {
|
|||
cv_lock.notify_all();
|
||||
}
|
||||
|
||||
static void WaitGpuIdle() {
|
||||
void WaitGpuIdle() {
|
||||
HLE_TRACE;
|
||||
std::unique_lock lock{m_submission};
|
||||
cv_lock.wait(lock, [] { return submission_lock == 0; });
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
extern std::unique_ptr<Vulkan::RendererVulkan> renderer;
|
||||
extern std::unique_ptr<AmdGpu::Liverpool> liverpool;
|
||||
|
||||
namespace Libraries::GnmDriver {
|
||||
void WaitGpuIdle();
|
||||
}
|
||||
|
||||
namespace Libraries::VideoOut {
|
||||
|
||||
constexpr static bool Is32BppPixelFormat(PixelFormat format) {
|
||||
|
@ -189,6 +193,11 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
|
|||
bool is_eop /*= false*/) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
if (!is_eop) {
|
||||
liverpool->SubmitDone();
|
||||
GnmDriver::WaitGpuIdle();
|
||||
}
|
||||
|
||||
Vulkan::Frame* frame;
|
||||
if (index == -1) {
|
||||
frame = renderer->PrepareBlankFrame();
|
||||
|
|
|
@ -362,11 +362,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||
}
|
||||
case PM4ItOpcode::EventWriteEop: {
|
||||
const auto* event_eop = reinterpret_cast<const PM4CmdEventWriteEop*>(header);
|
||||
// Guest can wait for GfxEop event to submit CPU flips.
|
||||
// Flush command list to ensure order.
|
||||
if (rasterizer && event_eop->int_sel == InterruptSelect::IrqWhenWriteConfirm) {
|
||||
rasterizer->Flush();
|
||||
}
|
||||
event_eop->SignalFence();
|
||||
break;
|
||||
}
|
||||
|
@ -380,11 +375,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||
const u32 data_size = (header->type3.count.Value() - 2) * 4;
|
||||
u64* address = write_data->Address<u64*>();
|
||||
if (!write_data->wr_one_addr.Value()) {
|
||||
// Guest can poll VO label before submitting CPU flips.
|
||||
// Flush command list before signalling to ensure order.
|
||||
if (rasterizer && vo_port->IsVoLabel(address)) {
|
||||
rasterizer->Flush();
|
||||
}
|
||||
std::memcpy(address, write_data->data, data_size);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -65,10 +65,9 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
|
|||
|
||||
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
|
||||
: window{window_}, liverpool{liverpool_}, instance{window, Config::getGpuId(), Config::vkValidationEnabled()},
|
||||
schedulers{Scheduler{instance}, Scheduler{instance}, Scheduler{instance}},
|
||||
swapchain{instance, window}, texture_cache{instance, schedulers[SchedulerType::Draw]} {
|
||||
rasterizer = std::make_unique<Rasterizer>(instance, schedulers[SchedulerType::Draw],
|
||||
texture_cache, liverpool);
|
||||
draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance},
|
||||
swapchain{instance, window}, texture_cache{instance, draw_scheduler} {
|
||||
rasterizer = std::make_unique<Rasterizer>(instance, draw_scheduler, texture_cache, liverpool);
|
||||
const u32 num_images = swapchain.GetImageCount();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
|
||||
|
@ -82,7 +81,7 @@ RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool*
|
|||
}
|
||||
|
||||
RendererVulkan::~RendererVulkan() {
|
||||
schedulers[SchedulerType::Draw].Finish();
|
||||
draw_scheduler.Finish();
|
||||
const vk::Device device = instance.GetDevice();
|
||||
for (auto& frame : present_frames) {
|
||||
vmaDestroyImage(instance.GetAllocator(), frame.image, frame.allocation);
|
||||
|
@ -170,7 +169,7 @@ bool RendererVulkan::ShowSplash(Frame* frame /*= nullptr*/) {
|
|||
info.pitch = splash->GetImageInfo().width;
|
||||
info.guest_address = VAddr(splash->GetImageData().data());
|
||||
info.guest_size_bytes = splash->GetImageData().size();
|
||||
splash_img.emplace(instance, schedulers[SchedulerType::Present], info);
|
||||
splash_img.emplace(instance, present_scheduler, info);
|
||||
texture_cache.RefreshImage(*splash_img);
|
||||
}
|
||||
frame = PrepareFrameInternal(*splash_img);
|
||||
|
@ -186,7 +185,7 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop
|
|||
// EOP flips are triggered from GPU thread to use the drawing scheduler to record
|
||||
// commands. Otherwise we are dealing with a CPU flip which could have arrived
|
||||
// from any guest thread. Use a separate scheduler for that.
|
||||
auto& scheduler = schedulers[is_eop ? SchedulerType::Draw : SchedulerType::CpuFlip];
|
||||
auto& scheduler = is_eop ? draw_scheduler : flip_scheduler;
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
|
||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead,
|
||||
|
@ -253,7 +252,7 @@ void RendererVulkan::Present(Frame* frame) {
|
|||
|
||||
const vk::Image swapchain_image = swapchain.Image();
|
||||
|
||||
auto& scheduler = schedulers[SchedulerType::Present];
|
||||
auto& scheduler = present_scheduler;
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
{
|
||||
auto* profiler_ctx = instance.GetProfilerContext();
|
||||
|
|
|
@ -83,7 +83,9 @@ private:
|
|||
Frontend::WindowSDL& window;
|
||||
AmdGpu::Liverpool* liverpool;
|
||||
Instance instance;
|
||||
std::array<Scheduler, 3> schedulers;
|
||||
Scheduler draw_scheduler;
|
||||
Scheduler present_scheduler;
|
||||
Scheduler flip_scheduler;
|
||||
Swapchain swapchain;
|
||||
std::unique_ptr<Rasterizer> rasterizer;
|
||||
VideoCore::TextureCache texture_cache;
|
||||
|
|
Loading…
Add table
Reference in a new issue