mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 12:51:42 +00:00
Implement dynamic depth bias.
This commit is contained in:
parent
3b9e072ecb
commit
05cfd9e85c
7 changed files with 90 additions and 16 deletions
|
|
@ -1815,6 +1815,11 @@ namespace plume {
|
|||
}
|
||||
}
|
||||
|
||||
void D3D12CommandList::setDepthBias(float depthBias, float depthBiasClamp, float slopeScaledDepthBias) {
|
||||
assert(device->capabilities.dynamicDepthBias && "Dynamic depth bias is unsupported on this device.");
|
||||
d3d->RSSetDepthBias(depthBias, depthBiasClamp, slopeScaledDepthBias);
|
||||
}
|
||||
|
||||
void D3D12CommandList::clearColor(uint32_t attachmentIndex, RenderColor colorValue, const RenderRect *clearRects, uint32_t clearRectsCount) {
|
||||
assert(targetFramebuffer != nullptr);
|
||||
assert(attachmentIndex < targetFramebuffer->colorTargets.size());
|
||||
|
|
@ -2718,6 +2723,10 @@ namespace plume {
|
|||
psoDesc.RasterizerState.DepthBias = desc.depthBias;
|
||||
psoDesc.RasterizerState.SlopeScaledDepthBias = desc.slopeScaledDepthBias;
|
||||
|
||||
if (desc.dynamicDepthBiasEnabled) {
|
||||
psoDesc.Flags |= D3D12_PIPELINE_STATE_FLAG_DYNAMIC_DEPTH_BIAS;
|
||||
}
|
||||
|
||||
switch (desc.cullMode) {
|
||||
case RenderCullMode::NONE:
|
||||
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||
|
|
@ -3307,6 +3316,14 @@ namespace plume {
|
|||
triangleFanSupportOption = d3d12Options15.TriangleFanSupported;
|
||||
}
|
||||
|
||||
// Check if dynamic depth bias is supported.
|
||||
bool dynamicDepthBiasOption = false;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS16 d3d12Options16 = {};
|
||||
res = deviceOption->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &d3d12Options16, sizeof(d3d12Options16));
|
||||
if (SUCCEEDED(res)) {
|
||||
dynamicDepthBiasOption = d3d12Options16.DynamicDepthBiasSupported;
|
||||
}
|
||||
|
||||
// Pick this adapter and device if it has better feature support than the current one.
|
||||
bool preferOverNothing = (adapter == nullptr) || (d3d == nullptr);
|
||||
bool preferVideoMemory = adapterDesc.DedicatedVideoMemory > description.dedicatedVideoMemory;
|
||||
|
|
@ -3328,6 +3345,7 @@ namespace plume {
|
|||
capabilities.raytracingStateUpdate = rtStateUpdateSupportOption;
|
||||
capabilities.sampleLocations = samplePositionsOption;
|
||||
capabilities.triangleFan = triangleFanSupportOption;
|
||||
capabilities.dynamicDepthBias = dynamicDepthBiasOption;
|
||||
description.name = Utf16ToUtf8(adapterDesc.Description);
|
||||
description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory;
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ namespace plume {
|
|||
};
|
||||
|
||||
struct D3D12CommandList : RenderCommandList {
|
||||
ID3D12GraphicsCommandList4 *d3d = nullptr;
|
||||
ID3D12GraphicsCommandList9 *d3d = nullptr;
|
||||
ID3D12CommandAllocator *commandAllocator = nullptr;
|
||||
D3D12Device *device = nullptr;
|
||||
RenderCommandListType type = RenderCommandListType::UNKNOWN;
|
||||
|
|
@ -184,6 +184,7 @@ namespace plume {
|
|||
void setViewports(const RenderViewport *viewports, uint32_t count) override;
|
||||
void setScissors(const RenderRect *scissorRects, uint32_t count) override;
|
||||
void setFramebuffer(const RenderFramebuffer *framebuffer) override;
|
||||
void setDepthBias(float depthBias, float depthBiasClamp, float slopeScaledDepthBias) override;
|
||||
void clearColor(uint32_t attachmentIndex, RenderColor colorValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
|
||||
void clearDepth(bool clearDepth, float depthValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
|
||||
void copyBufferRegion(RenderBufferReference dstBuffer, RenderBufferReference srcBuffer, uint64_t size) override;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ namespace plume {
|
|||
virtual void setViewports(const RenderViewport *viewports, uint32_t count) = 0;
|
||||
virtual void setScissors(const RenderRect *scissorRects, uint32_t count) = 0;
|
||||
virtual void setFramebuffer(const RenderFramebuffer *framebuffer) = 0;
|
||||
virtual void setDepthBias(float depthBias, float depthBiasClamp, float slopeScaledDepthBias) = 0;
|
||||
virtual void clearColor(uint32_t attachmentIndex = 0, RenderColor colorValue = RenderColor(), const RenderRect *clearRects = nullptr, uint32_t clearRectsCount = 0) = 0;
|
||||
virtual void clearDepth(bool clearDepth = true, float depthValue = 1.0f, const RenderRect *clearRects = nullptr, uint32_t clearRectsCount = 0) = 0;
|
||||
virtual void copyBufferRegion(RenderBufferReference dstBuffer, RenderBufferReference srcBuffer, uint64_t size) = 0;
|
||||
|
|
|
|||
|
|
@ -1171,6 +1171,7 @@ namespace plume {
|
|||
bool depthClipEnabled = false;
|
||||
int32_t depthBias = 0;
|
||||
float slopeScaledDepthBias = 0.0f;
|
||||
bool dynamicDepthBiasEnabled = false;
|
||||
bool depthEnabled = false;
|
||||
bool depthWriteEnabled = false;
|
||||
RenderMultisampling multisampling;
|
||||
|
|
@ -1778,6 +1779,7 @@ namespace plume {
|
|||
|
||||
// Draw.
|
||||
bool triangleFan = false;
|
||||
bool dynamicDepthBias = false;
|
||||
};
|
||||
|
||||
struct RenderInterfaceCapabilities {
|
||||
|
|
|
|||
|
|
@ -1432,7 +1432,10 @@ namespace plume {
|
|||
rasterization.cullMode = toVk(desc.cullMode);
|
||||
rasterization.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
|
||||
if (desc.depthBias != 0 || desc.slopeScaledDepthBias != 0.0f) {
|
||||
if (desc.dynamicDepthBiasEnabled) {
|
||||
rasterization.depthBiasEnable = true;
|
||||
}
|
||||
else if (desc.depthBias != 0 || desc.slopeScaledDepthBias != 0.0f) {
|
||||
rasterization.depthBiasEnable = true;
|
||||
rasterization.depthBiasConstantFactor = float(desc.depthBias);
|
||||
rasterization.depthBiasSlopeFactor = desc.slopeScaledDepthBias;
|
||||
|
|
@ -1510,6 +1513,10 @@ namespace plume {
|
|||
dynamicStates.emplace_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
dynamicStates.emplace_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||
|
||||
if (desc.dynamicDepthBiasEnabled) {
|
||||
dynamicStates.emplace_back(VK_DYNAMIC_STATE_DEPTH_BIAS);
|
||||
}
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
|
@ -2848,6 +2855,10 @@ namespace plume {
|
|||
}
|
||||
}
|
||||
|
||||
void VulkanCommandList::setDepthBias(float depthBias, float depthBiasClamp, float slopeScaledDepthBias) {
|
||||
vkCmdSetDepthBias(vk, depthBias, depthBiasClamp, slopeScaledDepthBias);
|
||||
}
|
||||
|
||||
static void clearCommonRectVector(uint32_t width, uint32_t height, const RenderRect *clearRects, uint32_t clearRectsCount, std::vector<VkClearRect> &rectVector) {
|
||||
rectVector.clear();
|
||||
|
||||
|
|
@ -3783,6 +3794,7 @@ namespace plume {
|
|||
capabilities.displayTiming = supportedOptionalExtensions.find(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME) != supportedOptionalExtensions.end();
|
||||
capabilities.preferHDR = memoryHeapSize > (512 * 1024 * 1024);
|
||||
capabilities.triangleFan = true;
|
||||
capabilities.dynamicDepthBias = true;
|
||||
|
||||
// Fill Vulkan-only capabilities.
|
||||
loadStoreOpNoneSupported = supportedOptionalExtensions.find(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME) != supportedOptionalExtensions.end();
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ namespace plume {
|
|||
void setViewports(const RenderViewport *viewports, uint32_t count) override;
|
||||
void setScissors(const RenderRect *scissorRects, uint32_t count) override;
|
||||
void setFramebuffer(const RenderFramebuffer *framebuffer) override;
|
||||
void setDepthBias(float depthBias, float depthBiasClamp, float slopeScaledDepthBias) override;
|
||||
void clearColor(uint32_t attachmentIndex, RenderColor colorValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
|
||||
void clearDepth(bool clearDepth, float depthValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
|
||||
void copyBufferRegion(RenderBufferReference dstBuffer, RenderBufferReference srcBuffer, uint64_t size) override;
|
||||
|
|
|
|||
|
|
@ -131,12 +131,18 @@ struct SharedConstants
|
|||
float alphaThreshold{};
|
||||
};
|
||||
|
||||
// Depth bias values here are only used when the render device has
|
||||
// dynamic depth bias capability enabled. Otherwise, they get unused
|
||||
// and the values get assigned in the pipeline state instead.
|
||||
|
||||
static GuestSurface* g_renderTarget;
|
||||
static GuestSurface* g_depthStencil;
|
||||
static RenderFramebuffer* g_framebuffer;
|
||||
static RenderViewport g_viewport(0.0f, 0.0f, 1280.0f, 720.0f);
|
||||
static bool g_halfPixel = true;
|
||||
static PipelineState g_pipelineState;
|
||||
static int32_t g_depthBias;
|
||||
static float g_slopeScaledDepthBias;
|
||||
static SharedConstants g_sharedConstants;
|
||||
static RenderSamplerDesc g_samplerDescs[16];
|
||||
static bool g_scissorTestEnable = false;
|
||||
|
|
@ -150,6 +156,7 @@ struct DirtyStates
|
|||
bool renderTargetAndDepthStencil;
|
||||
bool viewport;
|
||||
bool pipelineState;
|
||||
bool depthBias;
|
||||
bool sharedConstants;
|
||||
bool scissorRect;
|
||||
bool vertexShaderConstants;
|
||||
|
|
@ -162,6 +169,7 @@ struct DirtyStates
|
|||
: renderTargetAndDepthStencil(value)
|
||||
, viewport(value)
|
||||
, pipelineState(value)
|
||||
, depthBias(value)
|
||||
, sharedConstants(value)
|
||||
, scissorRect(value)
|
||||
, vertexShaderConstants(value)
|
||||
|
|
@ -194,7 +202,7 @@ static constexpr bool g_vulkan = true;
|
|||
static std::unique_ptr<RenderInterface> g_interface;
|
||||
static std::unique_ptr<RenderDevice> g_device;
|
||||
|
||||
static bool g_triangleFanSupported;
|
||||
static RenderDeviceCapabilities g_capabilities;
|
||||
|
||||
static constexpr size_t NUM_FRAMES = 2;
|
||||
|
||||
|
|
@ -1019,12 +1027,20 @@ static void ProcSetRenderState(const RenderCommand& cmd)
|
|||
}
|
||||
case D3DRS_SLOPESCALEDEPTHBIAS:
|
||||
{
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.slopeScaledDepthBias, *reinterpret_cast<float*>(&value));
|
||||
if (g_capabilities.dynamicDepthBias)
|
||||
SetDirtyValue(g_dirtyStates.depthBias, g_slopeScaledDepthBias, *reinterpret_cast<float*>(&value));
|
||||
else
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.slopeScaledDepthBias, *reinterpret_cast<float*>(&value));
|
||||
|
||||
break;
|
||||
}
|
||||
case D3DRS_DEPTHBIAS:
|
||||
{
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.depthBias, int32_t(*reinterpret_cast<float*>(&value) * (1 << 24)));
|
||||
if (g_capabilities.dynamicDepthBias)
|
||||
SetDirtyValue(g_dirtyStates.depthBias, g_depthBias, int32_t(*reinterpret_cast<float*>(&value) * (1 << 24)));
|
||||
else
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.depthBias, int32_t(*reinterpret_cast<float*>(&value)* (1 << 24)));
|
||||
|
||||
break;
|
||||
}
|
||||
case D3DRS_SRCBLENDALPHA:
|
||||
|
|
@ -1430,7 +1446,7 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
|
|||
|
||||
g_device = g_interface->createDevice();
|
||||
|
||||
g_triangleFanSupported = g_device->getCapabilities().triangleFan;
|
||||
g_capabilities = g_device->getCapabilities();
|
||||
|
||||
g_queue = g_device->createCommandQueue(RenderCommandListType::DIRECT);
|
||||
|
||||
|
|
@ -1991,9 +2007,8 @@ static void DrawProfiler()
|
|||
ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024)));
|
||||
ImGui::NewLine();
|
||||
|
||||
auto capabilities = g_device->getCapabilities();
|
||||
ImGui::Text("Present Wait: %s", capabilities.presentWait ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Fan: %s", capabilities.triangleFan ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
|
||||
ImGui::NewLine();
|
||||
|
||||
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
|
||||
|
|
@ -3164,6 +3179,8 @@ static void SanitizePipelineState(PipelineState& pipelineState)
|
|||
pipelineState.depthStencilFormat = RenderFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
assert(!g_capabilities.dynamicDepthBias || (pipelineState.depthBias == 0 && pipelineState.slopeScaledDepthBias == 0.0f));
|
||||
|
||||
if (pipelineState.slopeScaledDepthBias == 0.0f)
|
||||
pipelineState.slopeScaledDepthBias = 0.0f; // Remove sign.
|
||||
|
||||
|
|
@ -3214,6 +3231,7 @@ static std::unique_ptr<RenderPipeline> CreateGraphicsPipeline(const PipelineStat
|
|||
desc.depthWriteEnabled = pipelineState.zWriteEnable;
|
||||
desc.depthBias = pipelineState.depthBias;
|
||||
desc.slopeScaledDepthBias = pipelineState.slopeScaledDepthBias;
|
||||
desc.dynamicDepthBiasEnabled = g_capabilities.dynamicDepthBias;
|
||||
desc.depthClipEnabled = true;
|
||||
desc.primitiveTopology = pipelineState.primitiveTopology;
|
||||
desc.cullMode = pipelineState.cullMode;
|
||||
|
|
@ -3583,8 +3601,18 @@ static void FlushRenderStateForRenderThread()
|
|||
auto& commandList = g_commandLists[g_frame];
|
||||
|
||||
if (g_dirtyStates.pipelineState)
|
||||
{
|
||||
commandList->setPipeline(CreateGraphicsPipelineInRenderThread(g_pipelineState));
|
||||
|
||||
// D3D12 sets the depth bias values to the values in the pipeline.
|
||||
// TODO: Put the common depth bias values to shadow pipelines to reduce redundant calls.
|
||||
if (!g_vulkan && g_capabilities.dynamicDepthBias)
|
||||
g_dirtyStates.depthBias |= (g_depthBias != 0) || (g_slopeScaledDepthBias != 0.0f);
|
||||
}
|
||||
|
||||
if (g_dirtyStates.depthBias && g_capabilities.dynamicDepthBias)
|
||||
commandList->setDepthBias(g_depthBias, 0.0f, g_slopeScaledDepthBias);
|
||||
|
||||
if (g_dirtyStates.sharedConstants)
|
||||
{
|
||||
auto sharedConstants = g_uploadAllocators[g_frame].allocate<false>(&g_sharedConstants, sizeof(g_sharedConstants), 0x100);
|
||||
|
|
@ -3622,7 +3650,7 @@ static RenderPrimitiveTopology ConvertPrimitiveType(uint32_t primitiveType)
|
|||
case D3DPT_TRIANGLESTRIP:
|
||||
return RenderPrimitiveTopology::TRIANGLE_STRIP;
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
return g_triangleFanSupported ? RenderPrimitiveTopology::TRIANGLE_FAN : RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
return g_capabilities.triangleFan ? RenderPrimitiveTopology::TRIANGLE_FAN : RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
default:
|
||||
assert(false && "Unknown primitive type");
|
||||
return RenderPrimitiveTopology::UNKNOWN;
|
||||
|
|
@ -3748,7 +3776,7 @@ static void ProcDrawPrimitiveUP(const RenderCommand& cmd)
|
|||
|
||||
if (args.primitiveType == D3DPT_QUADLIST)
|
||||
indexCount = g_quadIndexData.prepare(args.primitiveCount);
|
||||
else if (!g_triangleFanSupported && args.primitiveType == D3DPT_TRIANGLEFAN)
|
||||
else if (!g_capabilities.triangleFan && args.primitiveType == D3DPT_TRIANGLEFAN)
|
||||
indexCount = g_triangleFanIndexData.prepare(args.primitiveCount);
|
||||
|
||||
if (args.csdFilterState != CsdFilterState::Unknown &&
|
||||
|
|
@ -4994,7 +5022,7 @@ static const be<uint16_t> g_particleTestIndexBuffer[] =
|
|||
|
||||
bool ParticleTestIndexBufferMidAsmHook(PPCRegister& r30)
|
||||
{
|
||||
if (!g_triangleFanSupported)
|
||||
if (!g_capabilities.triangleFan)
|
||||
{
|
||||
auto buffer = CreateIndexBuffer(sizeof(g_particleTestIndexBuffer), 0, D3DFMT_INDEX16);
|
||||
void* memory = LockIndexBuffer(buffer, 0, 0, 0);
|
||||
|
|
@ -5009,7 +5037,7 @@ bool ParticleTestIndexBufferMidAsmHook(PPCRegister& r30)
|
|||
|
||||
void ParticleTestDrawIndexedPrimitiveMidAsmHook(PPCRegister& r7)
|
||||
{
|
||||
if (!g_triangleFanSupported)
|
||||
if (!g_capabilities.triangleFan)
|
||||
r7.u64 = std::size(g_particleTestIndexBuffer);
|
||||
}
|
||||
|
||||
|
|
@ -5289,8 +5317,13 @@ static void CompileMeshPipeline(const Mesh& mesh, CompilationArgs& args)
|
|||
pipelineState.vertexDeclaration = mesh.vertexDeclaration;
|
||||
pipelineState.cullMode = mesh.material->m_DoubleSided ? RenderCullMode::NONE : RenderCullMode::BACK;
|
||||
pipelineState.zFunc = RenderComparisonFunction::LESS_EQUAL;
|
||||
pipelineState.depthBias = (1 << 24) * (*reinterpret_cast<be<float>*>(g_memory.Translate(0x83302760)));
|
||||
pipelineState.slopeScaledDepthBias = *reinterpret_cast<be<float>*>(g_memory.Translate(0x83302764));
|
||||
|
||||
if (!g_capabilities.dynamicDepthBias)
|
||||
{
|
||||
pipelineState.depthBias = (1 << 24) * (*reinterpret_cast<be<float>*>(g_memory.Translate(0x83302760)));
|
||||
pipelineState.slopeScaledDepthBias = *reinterpret_cast<be<float>*>(g_memory.Translate(0x83302764));
|
||||
}
|
||||
|
||||
pipelineState.colorWriteEnable = 0;
|
||||
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP;
|
||||
pipelineState.vertexStrides[0] = mesh.vertexSize;
|
||||
|
|
@ -5941,9 +5974,15 @@ static void ModelConsumerThread()
|
|||
pipelineState.vertexDeclaration = g_vertexDeclarations[reinterpret_cast<XXH64_hash_t>(pipelineState.vertexDeclaration)];
|
||||
}
|
||||
|
||||
if (!g_triangleFanSupported && pipelineState.primitiveTopology == RenderPrimitiveTopology::TRIANGLE_FAN)
|
||||
if (!g_capabilities.triangleFan && pipelineState.primitiveTopology == RenderPrimitiveTopology::TRIANGLE_FAN)
|
||||
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
|
||||
if (g_capabilities.dynamicDepthBias)
|
||||
{
|
||||
pipelineState.depthBias = 0;
|
||||
pipelineState.slopeScaledDepthBias = 0.0f;
|
||||
}
|
||||
|
||||
if (Config::GITextureFiltering == EGITextureFiltering::Bicubic)
|
||||
pipelineState.specConstants |= SPEC_CONSTANT_BICUBIC_GI_FILTER;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue