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.
This commit is contained in:
@@ -21,6 +21,10 @@ namespace NVFlinger {
|
|||||||
constexpr size_t SCREEN_REFRESH_RATE = 60;
|
constexpr size_t SCREEN_REFRESH_RATE = 60;
|
||||||
constexpr u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
|
constexpr u64 frame_ticks = static_cast<u64>(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() {
|
NVFlinger::NVFlinger() {
|
||||||
// Add the different displays to the list of displays.
|
// Add the different displays to the list of displays.
|
||||||
Display default_{0, "Default"};
|
Display default_{0, "Default"};
|
||||||
@@ -128,28 +132,50 @@ void NVFlinger::Compose() {
|
|||||||
// Search for a queued buffer and acquire it
|
// Search for a queued buffer and acquire it
|
||||||
auto buffer = buffer_queue->AcquireBuffer();
|
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
|
// There was no queued buffer to draw, render previous frame
|
||||||
Core::System::GetInstance().perf_stats.EndGameFrame();
|
Core::System::GetInstance().perf_stats.EndGameFrame();
|
||||||
VideoCore::g_renderer->SwapBuffers({});
|
VideoCore::g_renderer->SwapBuffers({});
|
||||||
continue;
|
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.
|
// Now send the buffer to the GPU for drawing.
|
||||||
auto nvdrv = Nvidia::nvdrv.lock();
|
auto nvdrv = Nvidia::nvdrv.lock();
|
||||||
ASSERT(nvdrv);
|
ASSERT(nvdrv);
|
||||||
|
|
||||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||||
// on which display we're drawing (Default, Internal, External, etc)
|
// on which display we're drawing (Default, Internal, External, etc)
|
||||||
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
|
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
|
||||||
ASSERT(nvdisp);
|
ASSERT(nvdisp);
|
||||||
|
|
||||||
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
||||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform);
|
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<Nvidia::Devices::nvdisp_disp0>("/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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user