From e926da31e66408f8f726647dedd3df0c6130beb9 Mon Sep 17 00:00:00 2001 From: cpasjuste Date: Thu, 15 Feb 2018 11:58:21 +0100 Subject: [PATCH 1/2] libnx: crappy fix for GfxMode_TiledSingle rendering mode This fix yuzu only rendering the first frame with libnx and GfxMode_TiledSingle mode. It can maybe have some side effect. --- src/core/hle/service/nvflinger/nvflinger.cpp | 50 +++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index a54239b0fe..3a2cb1b4d3 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -21,6 +21,10 @@ namespace NVFlinger { constexpr size_t SCREEN_REFRESH_RATE = 60; constexpr u64 frame_ticks = static_cast(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); +// libnx "GfxMode_TiledSingle" hack. libnx does not use queue/dequeue buffer +// in GfxMode_TiledSingle mode, we maintain a pointer to the last queued buffer +static BufferQueue::Buffer nxBuffer{}; + NVFlinger::NVFlinger() { // Add the different displays to the list of displays. Display default_{0, "Default"}; @@ -128,28 +132,50 @@ void NVFlinger::Compose() { // Search for a queued buffer and acquire it auto buffer = buffer_queue->AcquireBuffer(); - if (buffer == boost::none) { + if (buffer == boost::none && nxBuffer.status == BufferQueue::Buffer::Status::Free) { // There was no queued buffer to draw, render previous frame Core::System::GetInstance().perf_stats.EndGameFrame(); VideoCore::g_renderer->SwapBuffers({}); continue; + } else if(nxBuffer.status == BufferQueue::Buffer::Status::Free) { + nxBuffer.slot = buffer->slot; + nxBuffer.status = BufferQueue::Buffer::Status::Queued; + memcpy(&nxBuffer.igbp_buffer, &buffer->igbp_buffer, sizeof(IGBPBuffer)); + memcpy(&nxBuffer.transform, &buffer->transform, sizeof(BufferQueue::BufferTransformFlags)); } - auto& igbp_buffer = buffer->igbp_buffer; + if(buffer == boost::none && nxBuffer.status != BufferQueue::Buffer::Status::Free) { + auto &igbp_buffer = nxBuffer.igbp_buffer; - // Now send the buffer to the GPU for drawing. - auto nvdrv = Nvidia::nvdrv.lock(); - ASSERT(nvdrv); + // Now send the buffer to the GPU for drawing. + auto nvdrv = Nvidia::nvdrv.lock(); + ASSERT(nvdrv); - // TODO(Subv): Support more than just disp0. The display device selection is probably based - // on which display we're drawing (Default, Internal, External, etc) - auto nvdisp = nvdrv->GetDevice("/dev/nvdisp_disp0"); - ASSERT(nvdisp); + // TODO(Subv): Support more than just disp0. The display device selection is probably based + // on which display we're drawing (Default, Internal, External, etc) + auto nvdisp = nvdrv->GetDevice("/dev/nvdisp_disp0"); + ASSERT(nvdisp); - nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, - igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform); + nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, + igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, nxBuffer.transform); - buffer_queue->ReleaseBuffer(buffer->slot); + } else { + auto &igbp_buffer = buffer->igbp_buffer; + + // Now send the buffer to the GPU for drawing. + auto nvdrv = Nvidia::nvdrv.lock(); + ASSERT(nvdrv); + + // TODO(Subv): Support more than just disp0. The display device selection is probably based + // on which display we're drawing (Default, Internal, External, etc) + auto nvdisp = nvdrv->GetDevice("/dev/nvdisp_disp0"); + ASSERT(nvdisp); + + nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, + igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform); + + buffer_queue->ReleaseBuffer(buffer->slot); + } } } From b92c58dae50f66dee2b543212192bba5c3308b9d Mon Sep 17 00:00:00 2001 From: cpasjuste Date: Wed, 21 Feb 2018 11:34:44 +0100 Subject: [PATCH 2/2] remove spamming nvdisp log --- src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 7674d332de..ff9d0ea16e 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -22,9 +22,9 @@ u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector& input, std::vector void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) { VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); - LOG_WARNING(Service, - "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", - addr, offset, width, height, stride, format); + //LOG_WARNING(Service, + // "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", + // addr, offset, width, height, stride, format); using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; using Flags = NVFlinger::BufferQueue::BufferTransformFlags;