Recreate internal framebuffers when swap chain gets resized.

This commit is contained in:
Skyth 2024-10-08 12:24:37 +03:00
parent 078bfef1d2
commit c5e195fef3
6 changed files with 63 additions and 15 deletions

View file

@ -3630,6 +3630,10 @@ namespace RT64 {
return countsSupported;
}
void D3D12Device::waitIdle() const {
assert(false && "Use fences to replicate wait idle behavior on D3D12.");
}
void D3D12Device::release() {
if (d3d != nullptr) {
d3d->Release();

View file

@ -433,6 +433,7 @@ namespace RT64 {
const RenderDeviceCapabilities &getCapabilities() const override;
const RenderDeviceDescription &getDescription() const override;
RenderSampleCounts getSampleCountsSupported(RenderFormat format) const override;
void waitIdle() const override;
void release();
bool isValid() const;
};

View file

@ -189,7 +189,7 @@ namespace RT64 {
// Concrete implementation shortcuts.
inline void executeCommandLists(const RenderCommandList *commandList, RenderCommandFence *signalFence = nullptr) {
executeCommandLists(&commandList, 1, nullptr, 0, nullptr, 0, signalFence);
executeCommandLists(commandList != nullptr ? &commandList : nullptr, commandList != nullptr ? 1 : 0, nullptr, 0, nullptr, 0, signalFence);
}
};
@ -223,6 +223,7 @@ namespace RT64 {
virtual const RenderDeviceCapabilities &getCapabilities() const = 0;
virtual const RenderDeviceDescription &getDescription() const = 0;
virtual RenderSampleCounts getSampleCountsSupported(RenderFormat format) const = 0;
virtual void waitIdle() const = 0;
};
struct RenderInterface {

View file

@ -3966,6 +3966,10 @@ namespace RT64 {
}
}
void VulkanDevice::waitIdle() const {
vkDeviceWaitIdle(vk);
}
void VulkanDevice::release() {
if (allocator != VK_NULL_HANDLE) {
vmaDestroyAllocator(allocator);

View file

@ -391,6 +391,7 @@ namespace RT64 {
const RenderDeviceCapabilities &getCapabilities() const override;
const RenderDeviceDescription &getDescription() const override;
RenderSampleCounts getSampleCountsSupported(RenderFormat format) const override;
void waitIdle() const override;
void release();
bool isValid() const;
};

View file

@ -3,6 +3,7 @@
#include <kernel/function.h>
#include <kernel/heap.h>
#include <cpu/code_cache.h>
#include <cpu/guest_code.h>
#include <kernel/memory.h>
#include <xxHashMap.h>
@ -562,13 +563,50 @@ static void CreateHostDevice()
static void WaitForGPU()
{
for (size_t i = 0; i < NUM_FRAMES; i++)
if (g_vulkan)
{
if (g_commandListStates[i])
g_device->waitIdle();
}
else
{
for (size_t i = 0; i < NUM_FRAMES; i++)
{
g_queue->waitForCommandFence(g_commandFences[i].get());
g_commandListStates[i] = false;
if (g_commandListStates[i])
{
g_queue->waitForCommandFence(g_commandFences[i].get());
g_commandListStates[i] = false;
}
}
g_queue->executeCommandLists(nullptr, g_commandFences[0].get());
g_queue->waitForCommandFence(g_commandFences[0].get());
}
}
static PPCRegister g_r3;
static PPCRegister g_r4;
static PPCRegister g_r5;
PPC_FUNC_IMPL(__imp__sub_8258C8A0);
PPC_FUNC(sub_8258C8A0)
{
g_r3 = ctx.r3;
g_r4 = ctx.r4;
g_r5 = ctx.r5;
__imp__sub_8258C8A0(ctx, base);
}
static void ResizeSwapChain()
{
WaitForGPU();
g_backBuffer->framebuffers.clear();
if (g_swapChain->resize() && g_r3.u32 != NULL)
{
auto ctx = GetPPCContext();
ctx->r3 = g_r3;
ctx->r4 = g_r4;
ctx->r5 = g_r5;
GuestCode::Run(__imp__sub_8258C8A0, ctx);
}
}
@ -585,21 +623,18 @@ static void BeginCommandList()
{
g_swapChainValid = g_swapChain->acquireTexture(g_acquireSemaphores[g_frame].get(), &g_backBufferIndex);
if (g_swapChainValid)
{
g_backBuffer->texture = g_swapChain->getTexture(g_backBufferIndex);
g_backBuffer->pendingBarrier = true;
}
}
else
{
WaitForGPU();
g_backBuffer->framebuffers.clear();
g_swapChain->resize();
ResizeSwapChain();
}
if (!g_swapChainValid)
g_backBuffer->texture = g_backBuffer->textureHolder.get();
g_backBuffer->pendingBarrier = true;
auto& commandList = g_commandLists[g_frame];
commandList->begin();
@ -1052,6 +1087,8 @@ static void FlushFramebuffer()
g_depthStencil->pendingBarrier = false;
}
FlushBarriers();
if (g_dirtyStates.renderTargetAndDepthStencil)
{
GuestSurface* framebufferContainer = nullptr;
@ -1102,8 +1139,6 @@ static void FlushFramebuffer()
g_dirtyStates.renderTargetAndDepthStencil = false;
}
FlushBarriers();
}
static void Clear(GuestDevice* device, uint32_t flags, uint32_t, be<float>* color, double z)
@ -2338,8 +2373,10 @@ void SetShadowResolutionMidAsmHook(PPCRegister& r11)
static void SetResolution(be<uint32_t>* device)
{
device[46] = 1920;
device[47] = 1080;
uint32_t width = g_swapChain->getWidth();
uint32_t height = g_swapChain->getHeight();
device[46] = width == 0 ? 880 : width;
device[47] = height == 0 ? 720 : height;
}
static uint32_t StubFunction()