From 1b5ad34c8e36ec53cb1e759b5500bc3dbd5da946 Mon Sep 17 00:00:00 2001 From: flyinghead Date: Tue, 3 May 2022 17:47:43 +0200 Subject: [PATCH] dx11: (oit) use temporary render target for multipass Render to temporary render target at end of pass and swap with regular RT. Fixes Tony Hawk 2 missing transparent geometry and character shadow. Issue #618 --- core/rend/dx11/dx11_renderer.cpp | 1 + core/rend/dx11/dx11_renderer.h | 1 + core/rend/dx11/dx11context.cpp | 2 +- core/rend/dx11/oit/dx11_oitrenderer.cpp | 86 ++++++++++++++++++------- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/core/rend/dx11/dx11_renderer.cpp b/core/rend/dx11/dx11_renderer.cpp index a650acdcc..b1a6bca65 100644 --- a/core/rend/dx11/dx11_renderer.cpp +++ b/core/rend/dx11/dx11_renderer.cpp @@ -1243,6 +1243,7 @@ void DX11Renderer::prepareRttRenderTarget(u32 texAddress) vp.MinDepth = 0.f; vp.MaxDepth = 1.f; deviceContext->RSSetViewports(1, &vp); + setRTTSize(fbw2, fbh2); } void DX11Renderer::readRttRenderTarget(u32 texAddress) diff --git a/core/rend/dx11/dx11_renderer.h b/core/rend/dx11/dx11_renderer.h index f5cf9347b..554287176 100644 --- a/core/rend/dx11/dx11_renderer.h +++ b/core/rend/dx11/dx11_renderer.h @@ -95,6 +95,7 @@ protected: void readRttRenderTarget(u32 texAddress); void renderFramebuffer(); void setCullMode(int mode); + virtual void setRTTSize(int width, int height) {} ComPtr device; ComPtr deviceContext; diff --git a/core/rend/dx11/dx11context.cpp b/core/rend/dx11/dx11context.cpp index c7b6e3592..5e486fe91 100644 --- a/core/rend/dx11/dx11context.cpp +++ b/core/rend/dx11/dx11context.cpp @@ -70,7 +70,7 @@ bool DX11Context::init(bool keepCurrentWindow) nullptr, // Specify nullptr to use the default adapter. D3D_DRIVER_TYPE_HARDWARE, nullptr, - D3D11_CREATE_DEVICE_BGRA_SUPPORT, // | D3D11_CREATE_DEVICE_DEBUG, + D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, diff --git a/core/rend/dx11/oit/dx11_oitrenderer.cpp b/core/rend/dx11/oit/dx11_oitrenderer.cpp index 204d0eacf..627abcf08 100644 --- a/core/rend/dx11/oit/dx11_oitrenderer.cpp +++ b/core/rend/dx11/oit/dx11_oitrenderer.cpp @@ -97,28 +97,44 @@ struct DX11OITRenderer : public DX11Renderer return success; } + void checkMaxSize(int width, int height) + { + if (!opaqueTex || width > maxWidth || height > maxHeight) + { + maxWidth = std::max(maxWidth, width); + maxHeight = std::max(maxHeight, height); + + buffers.resize(maxWidth, maxHeight); + createTexAndRenderTarget(opaqueTex, opaqueRenderTarget, maxWidth, maxHeight); + multipassTex.reset(); + multipassRenderTarget.reset(); + multipassTextureView.reset(); + opaqueTextureView.reset(); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{}; + viewDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = 1; + device->CreateShaderResourceView(opaqueTex, &viewDesc, &opaqueTextureView.get()); + + // For depth pass. Use a 32-bit format for depth to avoid loss of precision + createDepthTexAndView(depthStencilTex2, depthStencilView2, maxWidth, maxHeight, DXGI_FORMAT_R32G8X24_TYPELESS, D3D11_BIND_SHADER_RESOURCE); + stencilView.reset(); + viewDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + device->CreateShaderResourceView(depthStencilTex2, &viewDesc, &stencilView.get()); + + depthView.reset(); + viewDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + device->CreateShaderResourceView(depthStencilTex2, &viewDesc, &depthView.get()); + } + } + void Resize(int w, int h) override { DX11Renderer::Resize(w, h); - buffers.resize(w, h); + checkMaxSize(w, h); + } - // FIXME must be used by RTT too - createTexAndRenderTarget(opaqueTex, opaqueRenderTarget, w, h); - opaqueTextureView.reset(); - D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{}; - viewDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - viewDesc.Texture2D.MipLevels = 1; - device->CreateShaderResourceView(opaqueTex, &viewDesc, &opaqueTextureView.get()); - - // For depth pass. Use a 32-bit format for depth to avoid loss of precision - createDepthTexAndView(depthStencilTex2, depthStencilView2, width, height, DXGI_FORMAT_R32G8X24_TYPELESS, D3D11_BIND_SHADER_RESOURCE); - stencilView.reset(); - viewDesc.Format = DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; - device->CreateShaderResourceView(depthStencilTex2, &viewDesc, &stencilView.get()); - - depthView.reset(); - viewDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - device->CreateShaderResourceView(depthStencilTex2, &viewDesc, &depthView.get()); + void setRTTSize(int width, int height) override { + checkMaxSize(width, height); } void Term() override @@ -126,6 +142,9 @@ struct DX11OITRenderer : public DX11Renderer vtxPolyConstants.reset(); finalInputLayout.reset(); mainInputLayout.reset(); + multipassTextureView.reset(); + multipassRenderTarget.reset(); + multipassTex.reset(); opaqueTextureView.reset(); opaqueRenderTarget.reset(); opaqueTex.reset(); @@ -414,9 +433,11 @@ struct DX11OITRenderer : public DX11Renderer deviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0); } - void renderABuffer() + void renderABuffer(bool lastPass) { - if (pvrrc.isRTT) + if (!lastPass) + deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &multipassRenderTarget.get(), nullptr, 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr); + else if (pvrrc.isRTT) deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &rttRenderTarget.get(), nullptr, 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr); else deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &fbRenderTarget.get(), nullptr, 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr); @@ -563,7 +584,21 @@ struct DX11OITRenderer : public DX11Renderer // // PASS 3c: Render a-buffer to temporary texture // - renderABuffer(); + if (!multipassTex) + { + createTexAndRenderTarget(multipassTex, multipassRenderTarget, maxWidth, maxHeight); + multipassTextureView.reset(); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{}; + viewDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = 1; + device->CreateShaderResourceView(multipassTex, &viewDesc, &multipassTextureView.get()); + } + + renderABuffer(false); + std::swap(opaqueTex, multipassTex); + std::swap(opaqueRenderTarget, multipassRenderTarget); + std::swap(opaqueTextureView, multipassTextureView); deviceContext->PSSetShaderResources(0, 1, &p); deviceContext->IASetInputLayout(mainInputLayout); @@ -577,7 +612,7 @@ struct DX11OITRenderer : public DX11Renderer // // PASS 4: Render a-buffers to screen // - renderABuffer(); + renderABuffer(true); } bool Render() override @@ -638,9 +673,14 @@ struct DX11OITRenderer : public DX11Renderer private: Buffers buffers; DX11OITShaders shaders; + int maxWidth = 0; + int maxHeight = 0; ComPtr opaqueTex; ComPtr opaqueRenderTarget; ComPtr opaqueTextureView; + ComPtr multipassTex; + ComPtr multipassRenderTarget; + ComPtr multipassTextureView; ComPtr stencilView; ComPtr depthView; ComPtr depthStencilTex2;