diff --git a/VanguardEngine/Source/Rendering/Atmosphere.cpp b/VanguardEngine/Source/Rendering/Atmosphere.cpp index 4e0e241..4120cf1 100644 --- a/VanguardEngine/Source/Rendering/Atmosphere.cpp +++ b/VanguardEngine/Source/Rendering/Atmosphere.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -112,7 +111,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(transmittanceHandle, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.FlushBarriers(); - list.BindPipelineState(transmissionPrecompute); + list.BindPipeline(transmissionPrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -137,7 +136,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(deltaIrradianceTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.FlushBarriers(); - list.BindPipelineState(directIrradiancePrecompute); + list.BindPipeline(directIrradiancePrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -164,7 +163,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(deltaMieTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.FlushBarriers(); - list.BindPipelineState(singleScatteringPrecompute); + list.BindPipeline(singleScatteringPrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -199,7 +198,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(deltaIrradianceTexture, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); list.FlushBarriers(); - list.BindPipelineState(scatteringDensityPrecompute); + list.BindPipeline(scatteringDensityPrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -226,7 +225,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(deltaIrradianceTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.FlushBarriers(); - list.BindPipelineState(indirectIrradiancePrecompute); + list.BindPipeline(indirectIrradiancePrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -253,7 +252,7 @@ void Atmosphere::Precompute(CommandList& list, TextureHandle transmittanceHandle list.TransitionBarrier(deltaScatteringDensityTexture, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); list.FlushBarriers(); - list.BindPipelineState(multipleScatteringPrecompute); + list.BindPipeline(multipleScatteringPrecomputeLayout); list.BindDescriptorAllocator(device->GetDescriptorAllocator()); list.BindConstants("bindData", bindData); list.Dispatch((uint32_t)dispatchX, (uint32_t)dispatchY, (uint32_t)dispatchZ); @@ -288,32 +287,34 @@ void Atmosphere::Initialize(RenderDevice* inDevice, entt::registry& registry) { device = inDevice; - ComputePipelineStateDescription precomputeState; - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "TransmittanceLutMain" }; - transmissionPrecompute.Build(*device, precomputeState); + transmissionPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "TransmittanceLutMain" }); - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "DirectIrradianceLutMain" }; - directIrradiancePrecompute.Build(*device, precomputeState); + directIrradiancePrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "DirectIrradianceLutMain" }); - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "SingleScatteringLutMain" }; - singleScatteringPrecompute.Build(*device, precomputeState); + singleScatteringPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "SingleScatteringLutMain" }); - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "ScatteringDensityLutMain" }; - scatteringDensityPrecompute.Build(*device, precomputeState); + scatteringDensityPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "ScatteringDensityLutMain" }); - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "IndirectIrradianceLutMain" }; - indirectIrradiancePrecompute.Build(*device, precomputeState); + indirectIrradiancePrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "IndirectIrradianceLutMain" }); - precomputeState.shader = { "Atmosphere/AtmospherePrecompute", "MultipleScatteringLutMain" }; - multipleScatteringPrecompute.Build(*device, precomputeState); + multipleScatteringPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/AtmospherePrecompute", "MultipleScatteringLutMain" }); - ComputePipelineStateDescription sunTransmittanceStateDesc; - sunTransmittanceStateDesc.shader = { "Atmosphere/SunTransmittance", "Main" }; - sunTransmittanceState.Build(*device, sunTransmittanceStateDesc); + renderLayout = RenderPipelineLayout{} + .VertexShader({ "Atmosphere/AtmosphereRender", "VSMain" }) + .PixelShader({ "Atmosphere/AtmosphereRender", "PSMain" }) + .DepthEnabled(true, false, DepthTestFunction::GreaterEqual); // Draw where the depth buffer is at the clear value. - ComputePipelineStateDescription luminanceState; - luminanceState.shader = { "Atmosphere/Luminance", "Main" }; - luminancePrecompute.Build(*device, luminanceState); + sunTransmittanceLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/SunTransmittance", "Main" }); + + luminancePrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "Atmosphere/Luminance", "Main" }); TextureDescription transmittanceDesc{ .bindFlags = BindFlag::ShaderResource | BindFlag::UnorderedAccess, @@ -414,7 +415,7 @@ AtmosphereResources Atmosphere::ImportResources(RenderGraph& graph) return { transmittanceTag, scatteringTag, irradianceTag }; } -void Atmosphere::Render(RenderGraph& graph, AtmosphereResources resourceHandles, PipelineBuilder& pipelines, RenderResource cameraBuffer, +void Atmosphere::Render(RenderGraph& graph, AtmosphereResources resourceHandles, RenderResource cameraBuffer, RenderResource depthStencil, RenderResource outputHDR, entt::registry& registry) { if (dirty) @@ -459,7 +460,7 @@ void Atmosphere::Render(RenderGraph& graph, AtmosphereResources resourceHandles, bindData.cameraBuffer = resources.Get(cameraBuffer); bindData.cameraIndex = 0; // #TODO: Support multiple cameras. - list.BindPipelineState(pipelines["AtmosphereRender"]); + list.BindPipeline(renderLayout); list.BindConstants("bindData", bindData); list.DrawFullscreenQuad(); @@ -506,7 +507,7 @@ std::pair Atmosphere::RenderEnvironmentMap(Rende bindData.cameraBuffer = resources.Get(cameraBuffer); bindData.cameraIndex = 0; // #TODO: Support multiple cameras. - list.BindPipelineState(luminancePrecompute); + list.BindPipeline(luminancePrecomputeLayout); list.BindConstants("bindData", bindData); list.Dispatch(luminanceTextureSize / 8, luminanceTextureSize / 8, 6); @@ -545,7 +546,7 @@ std::pair Atmosphere::RenderEnvironmentMap(Rende bindData.cameraBuffer = resources.Get(cameraBuffer); bindData.cameraIndex = 0; // #TODO: Support multiple cameras. - list.BindPipelineState(sunTransmittanceState); + list.BindPipeline(sunTransmittanceLayout); list.BindConstants("bindData", bindData); list.Dispatch(1, 1, 1); diff --git a/VanguardEngine/Source/Rendering/Atmosphere.h b/VanguardEngine/Source/Rendering/Atmosphere.h index 515b628..d2f9e33 100644 --- a/VanguardEngine/Source/Rendering/Atmosphere.h +++ b/VanguardEngine/Source/Rendering/Atmosphere.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include @@ -80,22 +80,23 @@ class Atmosphere TextureHandle deltaScatteringDensityTexture; TextureHandle deltaIrradianceTexture; - PipelineState transmissionPrecompute; - PipelineState directIrradiancePrecompute; - PipelineState singleScatteringPrecompute; - PipelineState scatteringDensityPrecompute; - PipelineState indirectIrradiancePrecompute; - PipelineState multipleScatteringPrecompute; + RenderPipelineLayout transmissionPrecomputeLayout; + RenderPipelineLayout directIrradiancePrecomputeLayout; + RenderPipelineLayout singleScatteringPrecomputeLayout; + RenderPipelineLayout scatteringDensityPrecomputeLayout; + RenderPipelineLayout indirectIrradiancePrecomputeLayout; + RenderPipelineLayout multipleScatteringPrecomputeLayout; void Precompute(CommandList& list, TextureHandle transmittanceHandle, TextureHandle scatteringHandle, TextureHandle irradianceHandle); - PipelineState sunTransmittanceState; + RenderPipelineLayout renderLayout; + RenderPipelineLayout sunTransmittanceLayout; static constexpr uint32_t luminanceTextureSize = 1024; static_assert(luminanceTextureSize % 8 == 0, "luminanceTextureSize must be evenly divisible by 8."); TextureHandle luminanceTexture; - PipelineState luminancePrecompute; + RenderPipelineLayout luminancePrecomputeLayout; entt::entity sunLight; // Directional light entity for direct solar illumination. @@ -104,7 +105,7 @@ class Atmosphere void Initialize(RenderDevice* inDevice, entt::registry& registry); AtmosphereResources ImportResources(RenderGraph& graph); - void Render(RenderGraph& graph, AtmosphereResources resourceHandles, PipelineBuilder& pipeline, RenderResource cameraBuffer, + void Render(RenderGraph& graph, AtmosphereResources resourceHandles, RenderResource cameraBuffer, RenderResource depthStencil, RenderResource outputHDRs, entt::registry& registry); std::pair RenderEnvironmentMap(RenderGraph& graph, AtmosphereResources resourceHandles, RenderResource cameraBuffer); void MarkModelDirty() { dirty = true; } diff --git a/VanguardEngine/Source/Rendering/Bloom.cpp b/VanguardEngine/Source/Rendering/Bloom.cpp index 0519a11..c8ee713 100644 --- a/VanguardEngine/Source/Rendering/Bloom.cpp +++ b/VanguardEngine/Source/Rendering/Bloom.cpp @@ -15,17 +15,14 @@ void Bloom::Initialize(RenderDevice* inDevice) { device = inDevice; - ComputePipelineStateDescription extractStateDesc; - extractStateDesc.shader = { "Bloom/Extract.hlsl", "Main" }; - extractState.Build(*device, extractStateDesc); + extractLayout = RenderPipelineLayout{} + .ComputeShader({ "Bloom/Extract.hlsl", "Main" }); - ComputePipelineStateDescription downsampleStateDesc; - downsampleStateDesc.shader = { "Bloom/Downsample.hlsl", "Main" }; - downsampleState.Build(*device, downsampleStateDesc); + downsampleLayout = RenderPipelineLayout{} + .ComputeShader({ "Bloom/Downsample.hlsl", "Main" }); - ComputePipelineStateDescription upsampleStateDesc; - upsampleStateDesc.shader = { "Bloom/Upsample.hlsl", "Main" }; - upsampleState.Build(*device, upsampleStateDesc); + upsampleLayout = RenderPipelineLayout{} + .ComputeShader({ "Bloom/Upsample.hlsl", "Main" }); } void Bloom::Render(RenderGraph& graph, const RenderResource hdrSource) @@ -43,7 +40,7 @@ void Bloom::Render(RenderGraph& graph, const RenderResource hdrSource) .UAV("", 0)); extractPass.Bind([&, hdrSource, extractTexture](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(extractState); + list.BindPipeline(extractLayout); struct BindData { @@ -81,7 +78,7 @@ void Bloom::Render(RenderGraph& graph, const RenderResource hdrSource) downsamplePass.Write(extractTexture, downsampleExtractView); downsamplePass.Bind([this, extractTexture, downsampleExtractViewNames](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(downsampleState); + list.BindPipeline(downsampleLayout); auto& extractTextureComponent = device->GetResourceManager().Get(resources.GetTexture(extractTexture)); @@ -127,7 +124,7 @@ void Bloom::Render(RenderGraph& graph, const RenderResource hdrSource) .UAV("", 0)); compositionPass.Bind([this, extractTexture, hdrSource, upsampleExtractViewNames](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(upsampleState); + list.BindPipeline(upsampleLayout); auto& extractTextureComponent = device->GetResourceManager().Get(resources.GetTexture(extractTexture)); auto& hdrTextureComponent = device->GetResourceManager().Get(resources.GetTexture(hdrSource)); diff --git a/VanguardEngine/Source/Rendering/Bloom.h b/VanguardEngine/Source/Rendering/Bloom.h index 3be025e..3fc8b7e 100644 --- a/VanguardEngine/Source/Rendering/Bloom.h +++ b/VanguardEngine/Source/Rendering/Bloom.h @@ -2,7 +2,7 @@ #pragma once -#include +#include #include class RenderDevice; @@ -13,9 +13,9 @@ class Bloom private: RenderDevice* device; - PipelineState extractState; - PipelineState downsampleState; - PipelineState upsampleState; + RenderPipelineLayout extractLayout; + RenderPipelineLayout downsampleLayout; + RenderPipelineLayout upsampleLayout; uint32_t bloomPasses = 0; diff --git a/VanguardEngine/Source/Rendering/ClusteredLightCulling.cpp b/VanguardEngine/Source/Rendering/ClusteredLightCulling.cpp index 61d93b0..315754f 100644 --- a/VanguardEngine/Source/Rendering/ClusteredLightCulling.cpp +++ b/VanguardEngine/Source/Rendering/ClusteredLightCulling.cpp @@ -71,7 +71,7 @@ void ClusteredLightCulling::ComputeClusterGrid(CommandList& list, uint32_t camer bindData.cameraIndex = 0; // #TODO: Support multiple cameras. bindData.boundsBuffer = clusterBoundsBuffer; - list.BindPipelineState(boundsState); + list.BindPipeline(boundsLayout); list.BindConstants("bindData", bindData); list.Dispatch(std::ceil(gridInfo.x * gridInfo.y * gridInfo.z / 64.f), 1, 1); } @@ -83,7 +83,7 @@ ClusteredLightCulling::~ClusteredLightCulling() void ClusteredLightCulling::Initialize(RenderDevice* inDevice) { - VGScopedCPUStat("Clustered Light Culling Initialize") + VGScopedCPUStat("Clustered Light Culling Initialize"); device = inDevice; @@ -101,101 +101,34 @@ void ClusteredLightCulling::Initialize(RenderDevice* inDevice) clusterBounds = device->GetResourceManager().Create(clusterBoundsDesc, VGText("Cluster bounds")); - ComputePipelineStateDescription boundsStateDesc; - boundsStateDesc.shader = { "Clusters/ClusterBounds.hlsl", "Main" }; - boundsStateDesc.macros.emplace_back("FROXEL_SIZE", froxelSize); - boundsState.Build(*device, boundsStateDesc); - - GraphicsPipelineStateDescription depthCullStateDesc; - depthCullStateDesc.vertexShader = { "Clusters/ClusterDepthCulling.hlsl", "VSMain" }; - depthCullStateDesc.pixelShader = { "Clusters/ClusterDepthCulling.hlsl", "PSMain" }; - depthCullStateDesc.macros.emplace_back("FROXEL_SIZE", froxelSize); - depthCullStateDesc.blendDescription.AlphaToCoverageEnable = false; - depthCullStateDesc.blendDescription.IndependentBlendEnable = false; - depthCullStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - depthCullStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - depthCullStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - depthCullStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - depthCullStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - depthCullStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - depthCullStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - depthCullStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - depthCullStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - depthCullStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = 0; - depthCullStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - depthCullStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_NONE; // Transparents can't have back culling. - depthCullStateDesc.rasterizerDescription.FrontCounterClockwise = false; - depthCullStateDesc.rasterizerDescription.DepthBias = 0; - depthCullStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - depthCullStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - depthCullStateDesc.rasterizerDescription.DepthClipEnable = true; - depthCullStateDesc.rasterizerDescription.MultisampleEnable = false; - depthCullStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - depthCullStateDesc.rasterizerDescription.ForcedSampleCount = 0; - depthCullStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - depthCullStateDesc.depthStencilDescription.DepthEnable = true; - depthCullStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - depthCullStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; // Opaque and transparents receive lighting, so they cannot be culled. - depthCullStateDesc.depthStencilDescription.StencilEnable = false; - depthCullStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - depthCullStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - depthCullStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - depthCullStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - depthCullStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - depthCullState.Build(*device, depthCullStateDesc, false); - - ComputePipelineStateDescription compactionStateDesc; - compactionStateDesc.shader = { "Clusters/ClusterCompaction.hlsl", "Main" }; - compactionState.Build(*device, compactionStateDesc); - - ComputePipelineStateDescription binningStateDesc; - binningStateDesc.shader = { "Clusters/ClusterLightBinning.hlsl", "Main" }; - binningStateDesc.macros.emplace_back("MAX_LIGHTS_PER_FROXEL", maxLightsPerFroxel); - binningState.Build(*device, binningStateDesc); - - ComputePipelineStateDescription indirectGenerationStateDesc; - indirectGenerationStateDesc.shader = { "Clusters/ClusterIndirectBufferGeneration.hlsl", "Main" }; - indirectGenerationState.Build(*device, indirectGenerationStateDesc); + boundsLayout = RenderPipelineLayout{} + .ComputeShader({ "Clusters/ClusterBounds.hlsl", "Main" }) + .Macro({ "FROXEL_SIZE", froxelSize }); + + depthCullLayout = RenderPipelineLayout{} + .VertexShader({ "Clusters/ClusterDepthCulling.hlsl", "VSMain" }) + .PixelShader({ "Clusters/ClusterDepthCulling.hlsl", "PSMain" }) + .CullMode(D3D12_CULL_MODE_NONE) // Transparents can't have back culling. + .DepthEnabled(true, false, DepthTestFunction::GreaterEqual) // Opaque and transparents receive lighting, so they cannot be culled. + .Macro({ "FROXEL_SIZE", froxelSize }); + + compactionLayout = RenderPipelineLayout{} + .ComputeShader({ "Clusters/ClusterCompaction.hlsl", "Main" }); + + binningLayout = RenderPipelineLayout{} + .ComputeShader({ "Clusters/ClusterLightBinning.hlsl", "Main" }) + .Macro({ "MAX_LIGHTS_PER_FROXEL", maxLightsPerFroxel }); + + indirectGenerationLayout = RenderPipelineLayout{} + .ComputeShader({ "Clusters/ClusterIndirectBufferGeneration.hlsl", "Main" }); #if ENABLE_EDITOR - GraphicsPipelineStateDescription debugOverlayStateDesc{}; - debugOverlayStateDesc.vertexShader = { "Clusters/ClusterDebugOverlay.hlsl", "VSMain" }; - debugOverlayStateDesc.pixelShader = { "Clusters/ClusterDebugOverlay.hlsl", "PSMain" }; - debugOverlayStateDesc.macros.emplace_back("FROXEL_SIZE", froxelSize); - debugOverlayStateDesc.macros.emplace_back("MAX_LIGHTS_PER_FROXEL", maxLightsPerFroxel); - debugOverlayStateDesc.blendDescription.AlphaToCoverageEnable = false; - debugOverlayStateDesc.blendDescription.IndependentBlendEnable = false; - debugOverlayStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - debugOverlayStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - debugOverlayStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - debugOverlayStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - debugOverlayStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - debugOverlayStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - debugOverlayStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - debugOverlayStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - debugOverlayStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - debugOverlayStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - debugOverlayStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - debugOverlayStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_BACK; - debugOverlayStateDesc.rasterizerDescription.FrontCounterClockwise = false; - debugOverlayStateDesc.rasterizerDescription.DepthBias = 0; - debugOverlayStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - debugOverlayStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - debugOverlayStateDesc.rasterizerDescription.DepthClipEnable = true; - debugOverlayStateDesc.rasterizerDescription.MultisampleEnable = false; - debugOverlayStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - debugOverlayStateDesc.rasterizerDescription.ForcedSampleCount = 0; - debugOverlayStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - debugOverlayStateDesc.depthStencilDescription.DepthEnable = false; - debugOverlayStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - debugOverlayStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_NEVER; // Opaque and transparents receive lighting, so they cannot be culled. - debugOverlayStateDesc.depthStencilDescription.StencilEnable = false; - debugOverlayStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - debugOverlayStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - debugOverlayStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - debugOverlayStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - debugOverlayStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - debugOverlayState.Build(*device, debugOverlayStateDesc, false); + debugOverlayLayout = RenderPipelineLayout{} + .VertexShader({ "Clusters/ClusterDebugOverlay.hlsl", "VSMain" }) + .PixelShader({ "Clusters/ClusterDebugOverlay.hlsl", "PSMain" }) + .DepthEnabled(false) + .Macro({ "FROXEL_SIZE", froxelSize }) + .Macro({ "MAX_LIGHTS_PER_FROXEL", maxLightsPerFroxel }); #endif std::vector binningIndirectArgDescs; @@ -275,7 +208,7 @@ ClusterResources ClusteredLightCulling::Render(RenderGraph& graph, const entt::r bindData.dimensions[2] = gridInfo.z; bindData.logY = 1.f / std::log(gridInfo.depthFactor); - list.BindPipelineState(depthCullState); + list.BindPipeline(depthCullLayout); MeshSystem::Render(Renderer::Get(), registry, list, false, bindData); }); @@ -299,7 +232,7 @@ ClusterResources ClusteredLightCulling::Render(RenderGraph& graph, const entt::r { auto& denseClustersComponent = device->GetResourceManager().Get(resources.GetBuffer(denseClustersTag)); - list.BindPipelineState(compactionState); + list.BindPipeline(compactionLayout); struct BindData { @@ -335,7 +268,7 @@ ClusterResources ClusteredLightCulling::Render(RenderGraph& graph, const entt::r indirectBindData.indirectBuffer = resources.Get(indirectBufferTag); // Generate the indirect argument buffer. - list.BindPipelineState(indirectGenerationState); + list.BindPipeline(indirectGenerationLayout); list.BindConstants("bindData", indirectBindData); list.Dispatch(1, 1, 1); }); @@ -381,7 +314,7 @@ ClusterResources ClusteredLightCulling::Render(RenderGraph& graph, const entt::r list.UAVBarrier(resources.GetBuffer(lightInfoTag)); list.FlushBarriers(); - list.BindPipelineState(binningState); + list.BindPipeline(binningLayout); auto& lightComponent = device->GetResourceManager().Get(resources.GetBuffer(lightsBuffer)); @@ -429,7 +362,7 @@ RenderResource ClusteredLightCulling::RenderDebugOverlay(RenderGraph& graph, Ren overlayPass.Output(clusterDebugOverlayTag, OutputBind::RTV, LoadType::Preserve); overlayPass.Bind([&, lightInfoBuffer, clusterVisibilityBuffer](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(debugOverlayState); + list.BindPipeline(debugOverlayLayout); struct BindData { diff --git a/VanguardEngine/Source/Rendering/ClusteredLightCulling.h b/VanguardEngine/Source/Rendering/ClusteredLightCulling.h index 8dacece..57eb6bb 100644 --- a/VanguardEngine/Source/Rendering/ClusteredLightCulling.h +++ b/VanguardEngine/Source/Rendering/ClusteredLightCulling.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include @@ -48,15 +48,15 @@ class ClusteredLightCulling ClusterGridInfo gridInfo; BufferHandle clusterBounds; - PipelineState boundsState; - PipelineState depthCullState; - PipelineState compactionState; - PipelineState binningState; - PipelineState indirectGenerationState; + RenderPipelineLayout boundsLayout; + RenderPipelineLayout depthCullLayout; + RenderPipelineLayout compactionLayout; + RenderPipelineLayout binningLayout; + RenderPipelineLayout indirectGenerationLayout; #if ENABLE_EDITOR // Debugging visualizations. - PipelineState debugOverlayState; + RenderPipelineLayout debugOverlayLayout; #endif ResourcePtr binningIndirectSignature; diff --git a/VanguardEngine/Source/Rendering/CommandList.cpp b/VanguardEngine/Source/Rendering/CommandList.cpp index 602ac9b..436d417 100644 --- a/VanguardEngine/Source/Rendering/CommandList.cpp +++ b/VanguardEngine/Source/Rendering/CommandList.cpp @@ -2,6 +2,7 @@ #include #include +#include #include void ValidateTransition(const BufferDescription& description, D3D12_RESOURCE_STATES newState) @@ -126,11 +127,13 @@ void CommandList::BindResourceInternal(const std::string& bindName, BufferHandle } } -void CommandList::Create(RenderDevice* inDevice, D3D12_COMMAND_LIST_TYPE type) +void CommandList::Create(RenderDevice* inDevice, RenderGraph* inGraph, D3D12_COMMAND_LIST_TYPE type, size_t pass) { VGScopedCPUStat("Command List Create"); device = inDevice; + graph = inGraph; + passIndex = pass; auto result = device->Native()->CreateCommandAllocator(type, IID_PPV_ARGS(allocator.Indirect())); if (FAILED(result)) @@ -231,6 +234,12 @@ void CommandList::BindPipelineState(const PipelineState& state) list->SetPipelineState(state.Native()); } +void CommandList::BindPipeline(const RenderPipelineLayout& layout) +{ + const auto& pipeline = graph->RequestPipelineState(device, layout, passIndex); + BindPipelineState(pipeline); +} + void CommandList::BindDescriptorAllocator(DescriptorAllocator& allocator, bool visibleHeap) { VGScopedCPUStat("Bind Descriptor Allocator"); diff --git a/VanguardEngine/Source/Rendering/CommandList.h b/VanguardEngine/Source/Rendering/CommandList.h index 8675f49..aef4c38 100644 --- a/VanguardEngine/Source/Rendering/CommandList.h +++ b/VanguardEngine/Source/Rendering/CommandList.h @@ -10,7 +10,9 @@ #include class RenderDevice; +class RenderGraph; class PipelineState; +class RenderPipelineLayout; class DescriptorAllocator; struct PipelineStateReflection; @@ -20,6 +22,8 @@ class CommandList ResourcePtr allocator; // #TODO: Potentially share allocators? Something to look into in the future. ResourcePtr list; RenderDevice* device; + RenderGraph* graph; + size_t passIndex; // Stateful tracking of the bound pipeline. const PipelineState* boundPipeline = nullptr; @@ -33,7 +37,7 @@ class CommandList public: auto* Native() const noexcept { return list.Get(); } - void Create(RenderDevice* inDevice, D3D12_COMMAND_LIST_TYPE type); + void Create(RenderDevice* inDevice, RenderGraph* inGraph, D3D12_COMMAND_LIST_TYPE type, size_t pass); void SetName(std::wstring_view name); // #TODO: Support split barriers. @@ -46,6 +50,7 @@ class CommandList void FlushBarriers(); void BindPipelineState(const PipelineState& state); + void BindPipeline(const RenderPipelineLayout& layout); void BindDescriptorAllocator(DescriptorAllocator& allocator, bool visibleHeap = true); void BindConstants(const std::string& bindName, const std::vector& data, size_t offset = 0); template diff --git a/VanguardEngine/Source/Rendering/Device.cpp b/VanguardEngine/Source/Rendering/Device.cpp index 59c2a81..35aa8c7 100644 --- a/VanguardEngine/Source/Rendering/Device.cpp +++ b/VanguardEngine/Source/Rendering/Device.cpp @@ -237,7 +237,7 @@ RenderDevice::RenderDevice(void* window, bool software, bool enableDebugging) for (int i = 0; i < frameCount; ++i) { - directCommandList[i].Create(this, D3D12_COMMAND_LIST_TYPE_DIRECT); + directCommandList[i].Create(this, nullptr, D3D12_COMMAND_LIST_TYPE_DIRECT, -1); // Close all lists except the current frame's list. if (i > 0) @@ -503,13 +503,13 @@ std::pair RenderDevice::FrameAllocate(size_t size) return { frameBuffers[frameIndex], frameBufferOffsets[frameIndex] - size }; } -std::shared_ptr RenderDevice::AllocateFrameCommandList(D3D12_COMMAND_LIST_TYPE type) +std::shared_ptr RenderDevice::AllocateFrameCommandList(RenderGraph* graph, D3D12_COMMAND_LIST_TYPE type, size_t passIndex) { const auto frameIndex = GetFrameIndex(); const auto size = frameCommandLists[frameIndex].size(); frameCommandLists[frameIndex].emplace_back(std::make_shared()); - frameCommandLists[frameIndex][size]->Create(this, type); + frameCommandLists[frameIndex][size]->Create(this, graph, type, passIndex); frameCommandLists[frameIndex][size]->SetName(VGText("Frame command list")); return frameCommandLists[frameIndex][size]; diff --git a/VanguardEngine/Source/Rendering/Device.h b/VanguardEngine/Source/Rendering/Device.h index 2d4a476..b42eaa0 100644 --- a/VanguardEngine/Source/Rendering/Device.h +++ b/VanguardEngine/Source/Rendering/Device.h @@ -91,7 +91,7 @@ class RenderDevice std::pair FrameAllocate(size_t size); // Allocate a per-frame command list, disposed of automatically. - std::shared_ptr AllocateFrameCommandList(D3D12_COMMAND_LIST_TYPE type); + std::shared_ptr AllocateFrameCommandList(RenderGraph* graph, D3D12_COMMAND_LIST_TYPE type, size_t passIndex); DescriptorHandle AllocateDescriptor(DescriptorType type); diff --git a/VanguardEngine/Source/Rendering/ImageBasedLighting.cpp b/VanguardEngine/Source/Rendering/ImageBasedLighting.cpp index 8054b17..d7ec26e 100644 --- a/VanguardEngine/Source/Rendering/ImageBasedLighting.cpp +++ b/VanguardEngine/Source/Rendering/ImageBasedLighting.cpp @@ -18,16 +18,17 @@ void ImageBasedLighting::Initialize(RenderDevice* inDevice) { device = inDevice; - ComputePipelineStateDescription convolutionState; - convolutionState.shader = { "IBL/Convolution", "IrradianceMain" }; - convolutionState.macros.emplace_back("PREFILTER_LEVELS", prefilterLevels); - irradiancePrecompute.Build(*device, convolutionState); + irradiancePrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "IBL/Convolution", "IrradianceMain" }) + .Macro({ "PREFILTER_LEVELS", prefilterLevels }); - convolutionState.shader = { "IBL/Convolution", "PrefilterMain" }; - prefilterPrecompute.Build(*device, convolutionState); + prefilterPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "IBL/Convolution", "PrefilterMain" }) + .Macro({ "PREFILTER_LEVELS", prefilterLevels }); - convolutionState.shader = { "IBL/Convolution", "BRDFMain" }; - brdfPrecompute.Build(*device, convolutionState); + brdfPrecomputeLayout = RenderPipelineLayout{} + .ComputeShader({ "IBL/Convolution", "BRDFMain" }) + .Macro({ "PREFILTER_LEVELS", prefilterLevels }); TextureDescription irradianceDesc{ .bindFlags = BindFlag::ShaderResource | BindFlag::UnorderedAccess, @@ -81,7 +82,7 @@ IBLResources ImageBasedLighting::UpdateLuts(RenderGraph& graph, RenderResource l .UAV("", 0)); brdfPass.Bind([&, brdfTag](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(brdfPrecompute); + list.BindPipeline(brdfPrecomputeLayout); struct BindData { @@ -107,7 +108,7 @@ IBLResources ImageBasedLighting::UpdateLuts(RenderGraph& graph, RenderResource l .UAV("array", 0)); irradiancePass.Bind([&, luminanceTexture, irradianceTag](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(irradiancePrecompute); + list.BindPipeline(irradiancePrecomputeLayout); struct BindData { @@ -139,7 +140,7 @@ IBLResources ImageBasedLighting::UpdateLuts(RenderGraph& graph, RenderResource l prefilterPass.Write(prefilterTag, prefilterView); prefilterPass.Bind([&, luminanceTexture, prefilterTag, prefilterViewNames](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(prefilterPrecompute); + list.BindPipeline(prefilterPrecomputeLayout); struct BindData { diff --git a/VanguardEngine/Source/Rendering/ImageBasedLighting.h b/VanguardEngine/Source/Rendering/ImageBasedLighting.h index d470c58..d77082d 100644 --- a/VanguardEngine/Source/Rendering/ImageBasedLighting.h +++ b/VanguardEngine/Source/Rendering/ImageBasedLighting.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include class RenderDevice; @@ -36,9 +36,9 @@ class ImageBasedLighting TextureHandle brdfTexture; private: - PipelineState irradiancePrecompute; - PipelineState prefilterPrecompute; - PipelineState brdfPrecompute; + RenderPipelineLayout irradiancePrecomputeLayout; + RenderPipelineLayout prefilterPrecomputeLayout; + RenderPipelineLayout brdfPrecomputeLayout; RenderDevice* device = nullptr; bool brdfRendered = false; diff --git a/VanguardEngine/Source/Rendering/PipelineBuilder.h b/VanguardEngine/Source/Rendering/PipelineBuilder.h deleted file mode 100644 index ed459f5..0000000 --- a/VanguardEngine/Source/Rendering/PipelineBuilder.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2019-2022 Andrew Depke - -#pragma once - -#include -#include - -#include - -class PipelineBuilder -{ -private: - std::unordered_map pipelines; - -public: - void AddGraphicsState(RenderDevice* device, const std::string& name, const GraphicsPipelineStateDescription& description, bool backBufferOutput) - { - VGAssert(!pipelines.contains(name), "Duplicate pipeline name."); - - pipelines[name].Build(*device, description, backBufferOutput); - } - - void AddComputeState(RenderDevice* device, const std::string& name, const ComputePipelineStateDescription& description) - { - VGAssert(!pipelines.contains(name), "Duplicate pipeline name."); - - pipelines[name].Build(*device, description); - } - - const PipelineState& operator[](const std::string& name); -}; - -inline const PipelineState& PipelineBuilder::operator[](const std::string& name) -{ - VGAssert(pipelines.contains(name), "Attempted to use unregistered pipeline: '%s'", name.data()); - - return pipelines[name]; -} \ No newline at end of file diff --git a/VanguardEngine/Source/Rendering/PipelineState.cpp b/VanguardEngine/Source/Rendering/PipelineState.cpp index d62a744..50b2f04 100644 --- a/VanguardEngine/Source/Rendering/PipelineState.cpp +++ b/VanguardEngine/Source/Rendering/PipelineState.cpp @@ -177,7 +177,7 @@ void PipelineState::CreateRootSignature(RenderDevice& device) ReflectRootSignature(); } -void PipelineState::Build(RenderDevice& device, const GraphicsPipelineStateDescription& inDescription, bool backBufferOutput) +void PipelineState::Build(RenderDevice& device, const GraphicsPipelineStateDescription& inDescription) { VGScopedCPUStat("Build Pipeline"); @@ -214,9 +214,9 @@ void PipelineState::Build(RenderDevice& device, const GraphicsPipelineStateDescr case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST: case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: graphicsDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; } - graphicsDesc.NumRenderTargets = 1; // #TODO: Pull from render graph. - graphicsDesc.RTVFormats[0] = backBufferOutput ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R16G16B16A16_FLOAT; // #TODO: Pull from render graph. - graphicsDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + graphicsDesc.NumRenderTargets = inDescription.renderTargetCount; + std::copy(std::begin(inDescription.renderTargetFormats), std::end(inDescription.renderTargetFormats), std::begin(graphicsDesc.RTVFormats)); + graphicsDesc.DSVFormat = inDescription.depthStencilFormat; graphicsDesc.SampleDesc = { 1, 0 }; // #TODO: Support multi-sampling. graphicsDesc.NodeMask = 0; graphicsDesc.CachedPSO = { nullptr, 0 }; // #TODO: Pipeline caching. diff --git a/VanguardEngine/Source/Rendering/PipelineState.h b/VanguardEngine/Source/Rendering/PipelineState.h index 866ff18..67e2d2d 100644 --- a/VanguardEngine/Source/Rendering/PipelineState.h +++ b/VanguardEngine/Source/Rendering/PipelineState.h @@ -22,6 +22,9 @@ struct GraphicsPipelineStateDescription D3D12_RASTERIZER_DESC rasterizerDescription; D3D12_DEPTH_STENCIL_DESC depthStencilDescription; D3D12_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + uint32_t renderTargetCount = 1; // #TEMP, dont init! + DXGI_FORMAT renderTargetFormats[8] = { DXGI_FORMAT_R16G16B16A16_FLOAT }; // #TEMP, dont init! + DXGI_FORMAT depthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; // #TEMP, dont init! }; struct ComputePipelineStateDescription @@ -76,6 +79,6 @@ class PipelineState auto* GetReflectionData() const noexcept { return &reflection; } - void Build(RenderDevice& device, const GraphicsPipelineStateDescription& inDescription, bool backBufferOutput); + void Build(RenderDevice& device, const GraphicsPipelineStateDescription& inDescription); void Build(RenderDevice& device, const ComputePipelineStateDescription& inDescription); }; \ No newline at end of file diff --git a/VanguardEngine/Source/Rendering/RenderGraph.cpp b/VanguardEngine/Source/Rendering/RenderGraph.cpp index f599a29..0c83ee5 100644 --- a/VanguardEngine/Source/Rendering/RenderGraph.cpp +++ b/VanguardEngine/Source/Rendering/RenderGraph.cpp @@ -3,6 +3,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -229,6 +233,79 @@ std::pair RenderGraph::GetBackBufferResolution(RenderDevice* return std::make_pair(buffer.description.width, buffer.description.height); } +PipelineState& RenderGraph::RequestPipelineState(RenderDevice* device, const RenderPipelineLayout& layout, size_t passIndex) +{ + std::vector renderTargetFormats; + DXGI_FORMAT depthStencilFormat = DXGI_FORMAT_UNKNOWN; + renderTargetFormats.reserve(passes[passIndex]->outputBindInfo.size()); + + for (const auto& [resource, bindInfo] : passes[passIndex]->outputBindInfo) + { + const auto& texture = device->GetResourceManager().Get(resourceManager->GetTexture(resource)); + const auto format = texture.description.format; + + if (bindInfo.first == OutputBind::RTV) + renderTargetFormats.emplace_back(format); + else + { + depthStencilFormat = ConvertResourceFormatToTypedDepth(format); + } + } + + // If we don't have an output depth bind, we could still read from depth. + if (depthStencilFormat == DXGI_FORMAT_UNKNOWN) + { + for (const auto& [resource, bind] : passes[passIndex]->bindInfo) + { + if (bind == ResourceBind::DSV) + { + const auto& texture = device->GetResourceManager().Get(resourceManager->GetTexture(resource)); + const auto format = texture.description.format; + depthStencilFormat = ConvertResourceFormatToTypedDepth(format); + break; + } + } + } + + auto hash = std::hash{}(layout); + for (const auto format : renderTargetFormats) + { + HashCombine(hash, format); + } + HashCombine(hash, depthStencilFormat); + + if (const auto it = resourceManager->passPipelines.find(hash); it != resourceManager->passPipelines.end()) + { + return it->second; + } + + else + { + VGLog(logRendering, "Compiling new pipeline layout request for pass: '{}'", Str2WideStr(passes[passIndex]->stableName.data())); + + PipelineState state{}; + std::visit([device, &state, &renderTargetFormats, &depthStencilFormat](auto&& description) + { + // Modified description for just this pass. Note that this doesn't affect the hash! + auto passDescription = description; + + using T = std::decay_t; + if constexpr (std::is_same_v) + { + passDescription.renderTargetCount = renderTargetFormats.size(); + std::memset(passDescription.renderTargetFormats, DXGI_FORMAT_UNKNOWN, std::size(passDescription.renderTargetFormats) * sizeof(DXGI_FORMAT)); + std::copy(renderTargetFormats.begin(), renderTargetFormats.end(), std::begin(passDescription.renderTargetFormats)); + passDescription.depthStencilFormat = depthStencilFormat; + } + + if constexpr (!std::is_same_v) + state.Build(*device, passDescription); + }, layout.description); + + return resourceManager->passPipelines.emplace(std::move(hash), std::move(state)).first->second; + } +} + RenderPass& RenderGraph::AddPass(std::string_view stableName, ExecutionQueue execution) { return *passes.emplace_back(std::make_unique(resourceManager, stableName, execution)); @@ -259,7 +336,7 @@ void RenderGraph::Execute(RenderDevice* device) for (int i = 0; i < passes.size(); ++i) { - passLists.emplace_back(std::move(device->AllocateFrameCommandList(D3D12_COMMAND_LIST_TYPE_DIRECT))); + passLists.emplace_back(std::move(device->AllocateFrameCommandList(this, D3D12_COMMAND_LIST_TYPE_DIRECT, i))); } for (const auto i : sorted) diff --git a/VanguardEngine/Source/Rendering/RenderGraph.h b/VanguardEngine/Source/Rendering/RenderGraph.h index 50cd6e1..590e7c7 100644 --- a/VanguardEngine/Source/Rendering/RenderGraph.h +++ b/VanguardEngine/Source/Rendering/RenderGraph.h @@ -15,6 +15,8 @@ class CommandList; class Renderer; +class RenderPipelineLayout; +class PipelineState; enum class ResourceTag { @@ -53,11 +55,9 @@ class RenderGraph const RenderResource Import(const BufferHandle resource); const RenderResource Import(const TextureHandle resource); - void Tag(const RenderResource resource, ResourceTag tag); - + PipelineState& RequestPipelineState(RenderDevice* device, const RenderPipelineLayout& layout, size_t passIndex); RenderPass& AddPass(std::string_view stableName, ExecutionQueue execution); - void Build(); void Execute(RenderDevice* device); }; diff --git a/VanguardEngine/Source/Rendering/RenderGraphResourceManager.h b/VanguardEngine/Source/Rendering/RenderGraphResourceManager.h index 81c3cb8..88c4d6e 100644 --- a/VanguardEngine/Source/Rendering/RenderGraphResourceManager.h +++ b/VanguardEngine/Source/Rendering/RenderGraphResourceManager.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,8 @@ struct RenderPassViews class RenderGraphResourceManager { + friend class RenderGraph; + public: bool transientReuse = true; @@ -60,6 +63,8 @@ class RenderGraphResourceManager std::unordered_map passViews; + std::unordered_map passPipelines; + private: DescriptorHandle CreateDescriptorFromView(RenderDevice* device, const RenderResource resource, ShaderResourceViewDescription viewDesc); uint32_t GetDefaultDescriptor(RenderDevice* device, const RenderResource resource, ResourceBind bind); diff --git a/VanguardEngine/Source/Rendering/RenderPipeline.h b/VanguardEngine/Source/Rendering/RenderPipeline.h index b704efc..7f782bc 100644 --- a/VanguardEngine/Source/Rendering/RenderPipeline.h +++ b/VanguardEngine/Source/Rendering/RenderPipeline.h @@ -14,6 +14,14 @@ #include #include +// Don't provide less function since we have an inverse depth buffer. +enum class DepthTestFunction +{ + Equal, + Greater, + GreaterEqual +}; + class RenderPipelineLayout { friend class RenderGraph; @@ -126,12 +134,17 @@ class RenderPipelineLayout std::get(description).rasterizerDescription.CullMode = mode; return *this; } - RenderPipelineLayout& DepthEnabled(bool value, bool write = false, bool testEqual = false) + RenderPipelineLayout& DepthEnabled(bool value, bool write = false, DepthTestFunction function = DepthTestFunction::Greater) { InitDefaultGraphics(); std::get(description).depthStencilDescription.DepthEnable = true; std::get(description).depthStencilDescription.DepthWriteMask = write ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO; - std::get(description).depthStencilDescription.DepthFunc = testEqual ? D3D12_COMPARISON_FUNC_GREATER_EQUAL : D3D12_COMPARISON_FUNC_GREATER; // Inverse depth buffer. + switch (function) + { + case DepthTestFunction::Equal: std::get(description).depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL; break; + case DepthTestFunction::Greater: std::get(description).depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER; break; + case DepthTestFunction::GreaterEqual: std::get(description).depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; break; + } return *this; } RenderPipelineLayout& StencilEnabled(bool value, bool write, uint8_t mask = D3D12_DEFAULT_STENCIL_READ_MASK) diff --git a/VanguardEngine/Source/Rendering/Renderer.cpp b/VanguardEngine/Source/Rendering/Renderer.cpp index e4896e9..87737ad 100644 --- a/VanguardEngine/Source/Rendering/Renderer.cpp +++ b/VanguardEngine/Source/Rendering/Renderer.cpp @@ -86,201 +86,20 @@ void Renderer::UpdateCameraBuffer(const entt::registry& registry) void Renderer::CreatePipelines() { - GraphicsPipelineStateDescription prepassStateDesc; - - prepassStateDesc.vertexShader = { "Prepass", "VSMain" }; - - prepassStateDesc.blendDescription.AlphaToCoverageEnable = false; - prepassStateDesc.blendDescription.IndependentBlendEnable = false; - prepassStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - prepassStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - prepassStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - prepassStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - prepassStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - prepassStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - prepassStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - prepassStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - prepassStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - prepassStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = 0; - - prepassStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - prepassStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_BACK; - prepassStateDesc.rasterizerDescription.FrontCounterClockwise = false; - prepassStateDesc.rasterizerDescription.DepthBias = 0; - prepassStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - prepassStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - prepassStateDesc.rasterizerDescription.DepthClipEnable = true; - prepassStateDesc.rasterizerDescription.MultisampleEnable = false; - prepassStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - prepassStateDesc.rasterizerDescription.ForcedSampleCount = 0; - prepassStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - - prepassStateDesc.depthStencilDescription.DepthEnable = true; // Enable depth. - prepassStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; // Write to the depth buffer. - prepassStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER; // Inverse depth buffer. - prepassStateDesc.depthStencilDescription.StencilEnable = false; - prepassStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - prepassStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - prepassStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - prepassStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - - prepassStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - - pipelines.AddGraphicsState(device.get(), "Prepass", prepassStateDesc, false); - - GraphicsPipelineStateDescription forwardStateDesc; - - forwardStateDesc.vertexShader = { "Forward", "VSMain" }; - forwardStateDesc.pixelShader = { "Forward", "PSMain" }; - forwardStateDesc.macros.emplace_back("FROXEL_SIZE", clusteredCulling.froxelSize); - - forwardStateDesc.blendDescription.AlphaToCoverageEnable = false; - forwardStateDesc.blendDescription.IndependentBlendEnable = false; - forwardStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - forwardStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - forwardStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - forwardStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - forwardStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - forwardStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - forwardStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - forwardStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - forwardStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - forwardStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - - forwardStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - forwardStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_BACK; - forwardStateDesc.rasterizerDescription.FrontCounterClockwise = false; - forwardStateDesc.rasterizerDescription.DepthBias = 0; - forwardStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - forwardStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - forwardStateDesc.rasterizerDescription.DepthClipEnable = true; - forwardStateDesc.rasterizerDescription.MultisampleEnable = false; - forwardStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - forwardStateDesc.rasterizerDescription.ForcedSampleCount = 0; - forwardStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - - // Prepass depth. - forwardStateDesc.depthStencilDescription.DepthEnable = true; - forwardStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - forwardStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL; - forwardStateDesc.depthStencilDescription.StencilEnable = false; - forwardStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - forwardStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - forwardStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - forwardStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - - forwardStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - - pipelines.AddGraphicsState(device.get(), "ForwardOpaque", forwardStateDesc, false); - - // Disable back face culling. - forwardStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_NONE; - - // Transparency blending. - forwardStateDesc.blendDescription.AlphaToCoverageEnable = false; // Not using MSAA. - forwardStateDesc.blendDescription.IndependentBlendEnable = false; // Only rendering to a single render target, discard others. - forwardStateDesc.blendDescription.RenderTarget[0].BlendEnable = true; - forwardStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; // No special blend logic. - forwardStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; - forwardStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; - forwardStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - forwardStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA; - forwardStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; - forwardStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - forwardStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - forwardStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - - // Test against the prepass depth, but don't use EQUAL operation since we're not writing transparent object data - // into the buffer, so it would result in transparent pixels only being drawn when overlapping with an opaque pixel. - forwardStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER; - - pipelines.AddGraphicsState(device.get(), "ForwardTransparent", forwardStateDesc, false); - - GraphicsPipelineStateDescription atmosphereStateDesc; - - atmosphereStateDesc.vertexShader = { "Atmosphere/AtmosphereRender", "VSMain" }; - atmosphereStateDesc.pixelShader = { "Atmosphere/AtmosphereRender", "PSMain" }; - - atmosphereStateDesc.blendDescription.AlphaToCoverageEnable = false; - atmosphereStateDesc.blendDescription.IndependentBlendEnable = false; - atmosphereStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - atmosphereStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - atmosphereStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - atmosphereStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - atmosphereStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - atmosphereStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - atmosphereStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - atmosphereStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - atmosphereStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - atmosphereStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - - atmosphereStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - atmosphereStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_BACK; - atmosphereStateDesc.rasterizerDescription.FrontCounterClockwise = false; - atmosphereStateDesc.rasterizerDescription.DepthBias = 0; - atmosphereStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - atmosphereStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - atmosphereStateDesc.rasterizerDescription.DepthClipEnable = true; - atmosphereStateDesc.rasterizerDescription.MultisampleEnable = false; - atmosphereStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - atmosphereStateDesc.rasterizerDescription.ForcedSampleCount = 0; - atmosphereStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - - atmosphereStateDesc.depthStencilDescription.DepthEnable = true; - atmosphereStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - atmosphereStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; // Draw where the depth buffer is at the clear value. - atmosphereStateDesc.depthStencilDescription.StencilEnable = false; - atmosphereStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - atmosphereStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - atmosphereStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - atmosphereStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - - atmosphereStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - - pipelines.AddGraphicsState(device.get(), "AtmosphereRender", atmosphereStateDesc, false); - - GraphicsPipelineStateDescription postProcessStateDesc; - - postProcessStateDesc.vertexShader = { "PostProcess", "VSMain" }; - postProcessStateDesc.pixelShader = { "PostProcess", "PSMain" }; - - postProcessStateDesc.blendDescription.AlphaToCoverageEnable = false; - postProcessStateDesc.blendDescription.IndependentBlendEnable = false; - postProcessStateDesc.blendDescription.RenderTarget[0].BlendEnable = false; - postProcessStateDesc.blendDescription.RenderTarget[0].LogicOpEnable = false; - postProcessStateDesc.blendDescription.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - postProcessStateDesc.blendDescription.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; - postProcessStateDesc.blendDescription.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - postProcessStateDesc.blendDescription.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - postProcessStateDesc.blendDescription.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; - postProcessStateDesc.blendDescription.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - postProcessStateDesc.blendDescription.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP; - postProcessStateDesc.blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - - postProcessStateDesc.rasterizerDescription.FillMode = D3D12_FILL_MODE_SOLID; - postProcessStateDesc.rasterizerDescription.CullMode = D3D12_CULL_MODE_BACK; - postProcessStateDesc.rasterizerDescription.FrontCounterClockwise = false; - postProcessStateDesc.rasterizerDescription.DepthBias = 0; - postProcessStateDesc.rasterizerDescription.DepthBiasClamp = 0.f; - postProcessStateDesc.rasterizerDescription.SlopeScaledDepthBias = 0.f; - postProcessStateDesc.rasterizerDescription.DepthClipEnable = true; - postProcessStateDesc.rasterizerDescription.MultisampleEnable = false; - postProcessStateDesc.rasterizerDescription.AntialiasedLineEnable = false; - postProcessStateDesc.rasterizerDescription.ForcedSampleCount = 0; - postProcessStateDesc.rasterizerDescription.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - - postProcessStateDesc.depthStencilDescription.DepthEnable = false; - postProcessStateDesc.depthStencilDescription.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - postProcessStateDesc.depthStencilDescription.DepthFunc = D3D12_COMPARISON_FUNC_NEVER; - postProcessStateDesc.depthStencilDescription.StencilEnable = false; - postProcessStateDesc.depthStencilDescription.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; - postProcessStateDesc.depthStencilDescription.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; - postProcessStateDesc.depthStencilDescription.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - postProcessStateDesc.depthStencilDescription.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_NEVER; - - postProcessStateDesc.topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - - pipelines.AddGraphicsState(device.get(), "PostProcess", postProcessStateDesc, true); + prepassLayout = RenderPipelineLayout{} + .VertexShader({ "Prepass", "VSMain" }) + .DepthEnabled(true, true); + + forwardOpaqueLayout = RenderPipelineLayout{} + .VertexShader({ "Forward", "VSMain" }) + .PixelShader({ "Forward", "PSMain" }) + .DepthEnabled(true, false, DepthTestFunction::Equal) // Prepass provides depth. + .Macro({ "FROXEL_SIZE", clusteredCulling.froxelSize }); + + postProcessLayout = RenderPipelineLayout{} + .VertexShader({ "PostProcess", "VSMain" }) + .PixelShader({ "PostProcess", "PSMain" }) + .DepthEnabled(false); } BufferHandle Renderer::CreateLightBuffer(const entt::registry& registry) @@ -417,7 +236,7 @@ void Renderer::Render(entt::registry& registry) bindData.vertexAssemblyData.positionBuffer = resources.Get(meshResources.positionTag); bindData.vertexAssemblyData.extraBuffer = resources.Get(meshResources.extraTag); - list.BindPipelineState(pipelines["Prepass"]); + list.BindPipeline(prepassLayout); MeshSystem::Render(Renderer::Get(), registry, list, false, bindData); }); @@ -479,23 +298,14 @@ void Renderer::Render(entt::registry& registry) { VGScopedGPUStat("Opaque", device->GetDirectContext(), list.Native()); - list.BindPipelineState(pipelines["ForwardOpaque"]); + list.BindPipeline(forwardOpaqueLayout); MeshSystem::Render(Renderer::Get(), registry, list, false, bindData); } - - { - VGScopedGPUStat("Transparent", device->GetDirectContext(), list.Native()); - - list.BindPipelineState(pipelines["ForwardTransparent"]); - - // #TODO: Sort transparent mesh components by distance. - MeshSystem::Render(Renderer::Get(), registry, list, true, bindData); - } }); // #TODO: Don't have this here. - atmosphere.Render(graph, atmosphereResources, pipelines, cameraBufferTag, depthStencilTag, outputHDRTag, registry); + atmosphere.Render(graph, atmosphereResources, cameraBufferTag, depthStencilTag, outputHDRTag, registry); // #TODO: Don't have this here. bloom.Render(graph, outputHDRTag); @@ -508,7 +318,7 @@ void Renderer::Render(entt::registry& registry) postProcessPass.Output(outputLDRTag, OutputBind::RTV, LoadType::Clear); postProcessPass.Bind([&](CommandList& list, RenderPassResources& resources) { - list.BindPipelineState(pipelines["PostProcess"]); + list.BindPipeline(postProcessLayout); list.BindConstants("bindData", { resources.Get(outputHDRTag) }); list.DrawFullscreenQuad(); diff --git a/VanguardEngine/Source/Rendering/Renderer.h b/VanguardEngine/Source/Rendering/Renderer.h index 78625c5..f7b9f3d 100644 --- a/VanguardEngine/Source/Rendering/Renderer.h +++ b/VanguardEngine/Source/Rendering/Renderer.h @@ -8,11 +8,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -32,11 +32,13 @@ class Renderer : public Singleton private: RenderGraphResourceManager renderGraphResources; - PipelineBuilder pipelines; // Manages all the pipelines. - BufferHandle instanceBuffer; BufferHandle cameraBuffer; + RenderPipelineLayout prepassLayout; + RenderPipelineLayout forwardOpaqueLayout; + RenderPipelineLayout postProcessLayout; + public: float lastFrameTime = -1.f;