diff --git a/MVS/3DGS-D3D12/CMakeLists.txt b/MVS/3DGS-D3D12/CMakeLists.txt index 83e4dbe4..a1df8573 100644 --- a/MVS/3DGS-D3D12/CMakeLists.txt +++ b/MVS/3DGS-D3D12/CMakeLists.txt @@ -42,6 +42,8 @@ add_executable(xc_3dgs_d3d12_mvs shaders/DeviceRadixSort.hlsl shaders/DebugPointsVS.hlsl shaders/DebugPointsPS.hlsl + shaders/CompositeVS.hlsl + shaders/CompositePS.hlsl ) set_source_files_properties( @@ -52,6 +54,8 @@ set_source_files_properties( shaders/DeviceRadixSort.hlsl shaders/DebugPointsVS.hlsl shaders/DebugPointsPS.hlsl + shaders/CompositeVS.hlsl + shaders/CompositePS.hlsl PROPERTIES HEADER_FILE_ONLY TRUE ) diff --git a/MVS/3DGS-D3D12/include/XC3DGSD3D12/App.h b/MVS/3DGS-D3D12/include/XC3DGSD3D12/App.h index 4282c018..20c97a07 100644 --- a/MVS/3DGS-D3D12/include/XC3DGSD3D12/App.h +++ b/MVS/3DGS-D3D12/include/XC3DGSD3D12/App.h @@ -67,10 +67,12 @@ private: bool InitializePreparePassResources(); bool InitializeSortResources(); bool InitializeDebugDrawResources(); + bool InitializeCompositeResources(); void ShutdownGaussianGpuResources(); void ShutdownPreparePassResources(); void ShutdownSortResources(); void ShutdownDebugDrawResources(); + void ShutdownCompositeResources(); void Shutdown(); bool CaptureSortSnapshot(); bool CapturePass3HistogramDebug(); @@ -137,6 +139,13 @@ private: XCEngine::RHI::RHIPipelineState* m_debugPipelineState = nullptr; XCEngine::RHI::RHIDescriptorPool* m_debugDescriptorPool = nullptr; XCEngine::RHI::RHIDescriptorSet* m_debugDescriptorSet = nullptr; + XCEngine::RHI::D3D12Texture m_splatRenderTargetTexture; + std::unique_ptr m_splatRenderTargetRtv; + std::unique_ptr m_splatRenderTargetSrv; + XCEngine::RHI::RHIPipelineLayout* m_compositePipelineLayout = nullptr; + XCEngine::RHI::RHIPipelineState* m_compositePipelineState = nullptr; + XCEngine::RHI::RHIDescriptorPool* m_compositeDescriptorPool = nullptr; + XCEngine::RHI::RHIDescriptorSet* m_compositeDescriptorSet = nullptr; XCEngine::RHI::D3D12Device m_device; XCEngine::RHI::D3D12CommandQueue m_commandQueue; diff --git a/MVS/3DGS-D3D12/shaders/CompositePS.hlsl b/MVS/3DGS-D3D12/shaders/CompositePS.hlsl new file mode 100644 index 00000000..3c83ed25 --- /dev/null +++ b/MVS/3DGS-D3D12/shaders/CompositePS.hlsl @@ -0,0 +1,12 @@ +Texture2D gSplatTexture : register(t0); + +struct PixelInput +{ + float4 position : SV_Position; +}; + +float4 MainPS(PixelInput input) : SV_Target0 +{ + float4 color = gSplatTexture.Load(int3(int2(input.position.xy), 0)); + return float4(color.rgb, color.a); +} diff --git a/MVS/3DGS-D3D12/shaders/CompositeVS.hlsl b/MVS/3DGS-D3D12/shaders/CompositeVS.hlsl new file mode 100644 index 00000000..7c4bd857 --- /dev/null +++ b/MVS/3DGS-D3D12/shaders/CompositeVS.hlsl @@ -0,0 +1,12 @@ +struct VertexOutput +{ + float4 position : SV_Position; +}; + +VertexOutput MainVS(uint vertexId : SV_VertexID) +{ + VertexOutput output = (VertexOutput)0; + float2 quadPosition = float2(vertexId & 1, (vertexId >> 1) & 1) * 4.0 - 1.0; + output.position = float4(quadPosition, 1.0, 1.0); + return output; +} diff --git a/MVS/3DGS-D3D12/shaders/DebugPointsVS.hlsl b/MVS/3DGS-D3D12/shaders/DebugPointsVS.hlsl index 359fa4c5..62e32d9a 100644 --- a/MVS/3DGS-D3D12/shaders/DebugPointsVS.hlsl +++ b/MVS/3DGS-D3D12/shaders/DebugPointsVS.hlsl @@ -37,10 +37,8 @@ VertexOutput MainVS(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID float2 quadPosition = float2(vertexId & 1, (vertexId >> 1) & 1) * 2.0 - 1.0; quadPosition *= 2.0; - float2 scaledAxis1 = view.axis1 * gSettings.w; - float2 scaledAxis2 = view.axis2 * gSettings.w; float2 deltaScreenPosition = - (quadPosition.x * scaledAxis1 + quadPosition.y * scaledAxis2) * 2.0 / gScreenParams.xy; + (quadPosition.x * view.axis1 + quadPosition.y * view.axis2) * 2.0 / gScreenParams.xy; output.position = view.clipPosition; output.position.xy += deltaScreenPosition * view.clipPosition.w; diff --git a/MVS/3DGS-D3D12/shaders/PrepareGaussiansCS.hlsl b/MVS/3DGS-D3D12/shaders/PrepareGaussiansCS.hlsl index 74254483..ff5d3975 100644 --- a/MVS/3DGS-D3D12/shaders/PrepareGaussiansCS.hlsl +++ b/MVS/3DGS-D3D12/shaders/PrepareGaussiansCS.hlsl @@ -143,7 +143,7 @@ float3 CalcCovariance2D(float3 worldPosition, float3 covariance0, float3 covaria focal / viewPosition.z, 0, -(focal * viewPosition.x) / (viewPosition.z * viewPosition.z), 0, focal / viewPosition.z, -(focal * viewPosition.y) / (viewPosition.z * viewPosition.z), 0, 0, 0); - float3x3 worldToView = (float3x3)gView; + float3x3 worldToView = transpose((float3x3)gView); float3x3 transform = mul(jacobian, worldToView); float3x3 covariance = float3x3( covariance0.x, covariance0.y, covariance0.z, @@ -253,6 +253,9 @@ void MainCS(uint3 dispatchThreadId : SV_DispatchThreadID) float3 covariance0; float3 covariance1; CalcCovariance3D(rotationScale, covariance0, covariance1); + float splatScaleSquared = gSettings.w * gSettings.w; + covariance0 *= splatScaleSquared; + covariance1 *= splatScaleSquared; float3 covariance2D = CalcCovariance2D(position, covariance0, covariance1); DecomposeCovariance(covariance2D, view.axis1, view.axis2); diff --git a/MVS/3DGS-D3D12/src/App.cpp b/MVS/3DGS-D3D12/src/App.cpp index b2bc451a..0a33ee0f 100644 --- a/MVS/3DGS-D3D12/src/App.cpp +++ b/MVS/3DGS-D3D12/src/App.cpp @@ -1140,6 +1140,118 @@ bool App::InitializeDebugDrawResources() { return true; } +bool App::InitializeCompositeResources() { + D3D12_RESOURCE_DESC splatRenderTargetDesc = {}; + splatRenderTargetDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + splatRenderTargetDesc.Alignment = 0; + splatRenderTargetDesc.Width = static_cast(m_width); + splatRenderTargetDesc.Height = static_cast(m_height); + splatRenderTargetDesc.DepthOrArraySize = 1; + splatRenderTargetDesc.MipLevels = 1; + splatRenderTargetDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + splatRenderTargetDesc.SampleDesc.Count = 1; + splatRenderTargetDesc.SampleDesc.Quality = 0; + splatRenderTargetDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + splatRenderTargetDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + + if (!m_splatRenderTargetTexture.Initialize( + m_device.GetDevice(), + splatRenderTargetDesc, + D3D12_RESOURCE_STATE_RENDER_TARGET)) { + m_lastErrorMessage = L"Failed to create the splat accumulation render target texture."; + return false; + } + m_splatRenderTargetTexture.SetState(ResourceStates::RenderTarget); + + ResourceViewDesc renderTargetViewDesc = {}; + renderTargetViewDesc.dimension = ResourceViewDimension::Texture2D; + renderTargetViewDesc.format = static_cast(Format::R16G16B16A16_Float); + m_splatRenderTargetRtv.reset(static_cast( + m_device.CreateRenderTargetView(&m_splatRenderTargetTexture, renderTargetViewDesc))); + if (!m_splatRenderTargetRtv) { + m_lastErrorMessage = L"Failed to create the splat accumulation render target view."; + return false; + } + + m_splatRenderTargetSrv.reset(static_cast( + m_device.CreateShaderResourceView(&m_splatRenderTargetTexture, renderTargetViewDesc))); + if (!m_splatRenderTargetSrv) { + m_lastErrorMessage = L"Failed to create the splat accumulation shader resource view."; + return false; + } + + DescriptorSetLayoutBinding bindings[1] = {}; + bindings[0].binding = 0; + bindings[0].type = static_cast(DescriptorType::SRV); + bindings[0].count = 1; + bindings[0].visibility = static_cast(ShaderVisibility::Pixel); + bindings[0].resourceDimension = ResourceViewDimension::Texture2D; + + DescriptorSetLayoutDesc setLayout = {}; + setLayout.bindings = bindings; + setLayout.bindingCount = 1; + + RHIPipelineLayoutDesc pipelineLayoutDesc = {}; + pipelineLayoutDesc.setLayouts = &setLayout; + pipelineLayoutDesc.setLayoutCount = 1; + + m_compositePipelineLayout = m_device.CreatePipelineLayout(pipelineLayoutDesc); + if (m_compositePipelineLayout == nullptr) { + m_lastErrorMessage = L"Failed to create the composite pipeline layout."; + return false; + } + + DescriptorPoolDesc poolDesc = {}; + poolDesc.type = DescriptorHeapType::CBV_SRV_UAV; + poolDesc.descriptorCount = 1; + poolDesc.shaderVisible = true; + m_compositeDescriptorPool = m_device.CreateDescriptorPool(poolDesc); + if (m_compositeDescriptorPool == nullptr) { + m_lastErrorMessage = L"Failed to create the composite descriptor pool."; + return false; + } + + m_compositeDescriptorSet = m_compositeDescriptorPool->AllocateSet(setLayout); + if (m_compositeDescriptorSet == nullptr) { + m_lastErrorMessage = L"Failed to allocate the composite descriptor set."; + return false; + } + m_compositeDescriptorSet->Update(0, m_splatRenderTargetSrv.get()); + + GraphicsPipelineDesc pipelineDesc = {}; + pipelineDesc.pipelineLayout = m_compositePipelineLayout; + pipelineDesc.topologyType = static_cast(PrimitiveTopologyType::Triangle); + pipelineDesc.renderTargetCount = 1; + pipelineDesc.renderTargetFormats[0] = static_cast(Format::R8G8B8A8_UNorm); + pipelineDesc.depthStencilFormat = static_cast(Format::Unknown); + pipelineDesc.sampleCount = 1; + pipelineDesc.sampleQuality = 0; + pipelineDesc.rasterizerState.cullMode = static_cast(CullMode::None); + pipelineDesc.depthStencilState.depthTestEnable = false; + pipelineDesc.depthStencilState.depthWriteEnable = false; + pipelineDesc.blendState.blendEnable = true; + pipelineDesc.blendState.srcBlend = static_cast(BlendFactor::SrcAlpha); + pipelineDesc.blendState.dstBlend = static_cast(BlendFactor::InvSrcAlpha); + pipelineDesc.blendState.srcBlendAlpha = static_cast(BlendFactor::One); + pipelineDesc.blendState.dstBlendAlpha = static_cast(BlendFactor::InvSrcAlpha); + + pipelineDesc.vertexShader.fileName = ResolveShaderPath(L"CompositeVS.hlsl").wstring(); + pipelineDesc.vertexShader.entryPoint = L"MainVS"; + pipelineDesc.vertexShader.profile = L"vs_5_0"; + + pipelineDesc.fragmentShader.fileName = ResolveShaderPath(L"CompositePS.hlsl").wstring(); + pipelineDesc.fragmentShader.entryPoint = L"MainPS"; + pipelineDesc.fragmentShader.profile = L"ps_5_0"; + + m_compositePipelineState = m_device.CreatePipelineState(pipelineDesc); + if (m_compositePipelineState == nullptr) { + m_lastErrorMessage = L"Failed to create the composite pipeline state."; + return false; + } + + return true; +} + void App::ShutdownGaussianGpuResources() { m_gaussianColorView.reset(); m_gaussianShView.reset(); @@ -1256,6 +1368,20 @@ void App::ShutdownDebugDrawResources() { ShutdownAndDelete(m_debugPipelineLayout); } +void App::ShutdownCompositeResources() { + if (m_compositeDescriptorSet != nullptr) { + m_compositeDescriptorSet->Shutdown(); + delete m_compositeDescriptorSet; + m_compositeDescriptorSet = nullptr; + } + ShutdownAndDelete(m_compositeDescriptorPool); + ShutdownAndDelete(m_compositePipelineState); + ShutdownAndDelete(m_compositePipelineLayout); + m_splatRenderTargetSrv.reset(); + m_splatRenderTargetRtv.reset(); + m_splatRenderTargetTexture.Shutdown(); +} + void App::Shutdown() { AppendTrace("Shutdown: begin"); if (!m_isInitialized && m_hwnd == nullptr) { @@ -1670,8 +1796,8 @@ void App::RenderFrame(bool captureScreenshot) { const int currentBackBufferIndex = m_swapChain.GetCurrentBackBufferIndex(); D3D12Texture& backBuffer = m_swapChain.GetBackBuffer(currentBackBufferIndex); - m_commandList.TransitionBarrier(backBuffer.GetResource(), ResourceStates::Present, ResourceStates::RenderTarget); + backBuffer.SetState(ResourceStates::RenderTarget); const CPUDescriptorHandle rtvCpuHandle = m_rtvHeap.GetCPUDescriptorHandle(currentBackBufferIndex); const CPUDescriptorHandle dsvCpuHandle = m_dsvHeap.GetCPUDescriptorHandle(0); @@ -2034,12 +2160,14 @@ void App::RenderFrame(bool captureScreenshot) { m_commandAllocator.Reset(); m_commandList.Reset(); m_commandList.TransitionBarrier(backBuffer.GetResource(), ResourceStates::RenderTarget, ResourceStates::Present); + backBuffer.SetState(ResourceStates::Present); m_commandList.Close(); void* presentCommandLists[] = { &m_commandList }; AppendTrace("RenderFrame: execute final present-transition list"); m_commandQueue.ExecuteCommandLists(1, presentCommandLists); } else { m_commandList.TransitionBarrier(backBuffer.GetResource(), ResourceStates::RenderTarget, ResourceStates::Present); + backBuffer.SetState(ResourceStates::Present); m_commandList.Close(); void* commandLists[] = { &m_commandList }; AppendTrace("RenderFrame: execute+present");