diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp index 073ea68a..5a6c846d 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp @@ -1566,6 +1566,10 @@ namespace plume { auto makeBarrier = [&](ID3D12Resource *resource, D3D12_RESOURCE_STATES stateBefore, D3D12_RESOURCE_STATES stateAfter, bool supportsUAV, D3D12_RESOURCE_BARRIER &resourceBarrier) { resourceBarrier = {}; + if (type == RenderCommandListType::COPY) { + return false; + } + if (stateBefore != stateAfter) { resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; resourceBarrier.Transition.StateBefore = stateBefore; @@ -2228,11 +2232,13 @@ namespace plume { this->device = device; - HRESULT res = device->d3d->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d)); + HRESULT res = device->d3d->CreateFence(1, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d)); if (FAILED(res)) { fprintf(stderr, "CreateFence failed with error code 0x%lX.\n", res); return; } + + semaphoreValue = 1; } D3D12CommandSemaphore::~D3D12CommandSemaphore() { diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 2333dfb7..f4551db0 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -315,6 +315,10 @@ static std::unique_ptr g_copyQueue; static std::unique_ptr g_copyCommandList; static std::unique_ptr g_copyCommandFence; +static Mutex g_discardMutex; +static std::unique_ptr g_discardCommandList; +static std::unique_ptr g_discardCommandFence; + static std::unique_ptr g_swapChain; static bool g_swapChainValid; @@ -1724,23 +1728,10 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry) { bool redirectToVulkan = false; - if (deviceDescription.vendor == RenderDeviceVendor::AMD) - { - // AMD Drivers before this version have a known issue where MSAA resolve targets will fail to work correctly. - // If no specific graphics API was selected, we silently destroy this one and move to the next option as it'll - // just work incorrectly otherwise and result in visual glitches and 3D rendering not working in general. - constexpr uint64_t MinimumAMDDriverVersion = 0x1F00005DC2005CULL; // 31.0.24002.92 - if ((Config::GraphicsAPI == EGraphicsAPI::Auto) && (deviceDescription.driverVersion < MinimumAMDDriverVersion)) - redirectToVulkan = true; - } - else if (deviceDescription.vendor == RenderDeviceVendor::INTEL) - { - // Intel drivers on D3D12 are extremely buggy, introducing various graphical glitches. - // We will redirect users to Vulkan until a workaround can be found. - if (Config::GraphicsAPI == EGraphicsAPI::Auto) - redirectToVulkan = true; - } - + // ... + // There used to be driver redirections here, but they are all free from Vulkan purgatory for now... + // ... + if (redirectToVulkan) { g_device.reset(); @@ -1757,10 +1748,6 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry) continue; } } - - // Hardware resolve seems to be completely bugged on Intel D3D12 drivers. - g_hardwareResolve = (deviceDescription.vendor != RenderDeviceVendor::INTEL); - g_hardwareDepthResolve = (deviceDescription.vendor != RenderDeviceVendor::INTEL); } g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper); @@ -1849,6 +1836,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry) g_copyCommandList = g_device->createCommandList(RenderCommandListType::COPY); g_copyCommandFence = g_device->createCommandFence(); + if (!g_vulkan) + { + g_discardCommandList = g_device->createCommandList(RenderCommandListType::DIRECT); + g_discardCommandFence = g_device->createCommandFence(); + } + uint32_t bufferCount = 2; switch (Config::TripleBuffering) @@ -3093,6 +3086,27 @@ static RenderFormat ConvertFormat(uint32_t format) } } +static void DiscardTexture(GuestBaseTexture* texture, RenderTextureLayout layout) +{ + if (!g_vulkan) + { + std::lock_guard lock(g_discardMutex); + + g_discardCommandList->begin(); + if (texture->layout != layout) + { + g_discardCommandList->barriers(RenderBarrierStage::GRAPHICS, RenderTextureBarrier(texture->texture, layout)); + texture->layout = layout; + } + + g_discardCommandList->discardTexture(texture->texture); + g_discardCommandList->end(); + + g_queue->executeCommandLists(g_discardCommandList.get(), g_discardCommandFence.get()); + g_queue->waitForCommandFence(g_discardCommandFence.get()); + } +} + static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t depth, uint32_t levels, uint32_t usage, uint32_t format, uint32_t pool, uint32_t type) { const auto texture = g_userHeap.AllocPhysical(type == 17 ? ResourceType::VolumeTexture : ResourceType::Texture); @@ -3150,6 +3164,12 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep texture->texture->setName(fmt::format("Texture {:X}", g_memory.MapVirtual(texture))); #endif + if (desc.flags != RenderTextureFlag::NONE) + { + DiscardTexture(texture, desc.flags == RenderTextureFlag::RENDER_TARGET ? + RenderTextureLayout::COLOR_WRITE : RenderTextureLayout::DEPTH_WRITE); + } + return texture; } @@ -3218,6 +3238,9 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for surface->texture->setName(fmt::format("{} {:X}", desc.flags & RenderTextureFlag::RENDER_TARGET ? "Render Target" : "Depth Stencil", g_memory.MapVirtual(surface))); #endif + DiscardTexture(surface, desc.flags == RenderTextureFlag::RENDER_TARGET ? + RenderTextureLayout::COLOR_WRITE : RenderTextureLayout::DEPTH_WRITE); + return surface; }