diff options
Diffstat (limited to 'Projects/Asteroids/src/asteroids_DE.cpp')
| -rw-r--r-- | Projects/Asteroids/src/asteroids_DE.cpp | 137 |
1 files changed, 91 insertions, 46 deletions
diff --git a/Projects/Asteroids/src/asteroids_DE.cpp b/Projects/Asteroids/src/asteroids_DE.cpp index 35fb0da..ba1dc4d 100644 --- a/Projects/Asteroids/src/asteroids_DE.cpp +++ b/Projects/Asteroids/src/asteroids_DE.cpp @@ -73,17 +73,24 @@ namespace Diligent namespace AsteroidsDE { -struct DrawConstantBuffer { - DirectX::XMFLOAT4X4 mWorld; +struct DrawConstantBuffer +{ DirectX::XMFLOAT4X4 mViewProjection; - DirectX::XMFLOAT3 mSurfaceColor; + DirectX::XMFLOAT4X4 mWorld; + DirectX::XMFLOAT3 mSurfaceColor; float unused0; DirectX::XMFLOAT3 mDeepColor; float unused1; +}; - Uint32 mTextureIndex; - Uint32 unused3[3]; +struct AsteroidData +{ + DirectX::XMFLOAT4X4 mWorld; + DirectX::XMFLOAT3 mSurfaceColor; + float unused0; + DirectX::XMFLOAT3 mDeepColor; + Uint32 mTextureIndex; }; struct SkyboxConstantBuffer { @@ -239,13 +246,30 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G mBackBufferHeight = mSwapChain->GetDesc().Height; const auto MaxAsteroidsInSubset = (NUM_ASTEROIDS + mNumSubsets - 1) / mNumSubsets; + { + BufferDesc desc; + desc.Name = "Asteroids constant buffer"; + // In bindless mode we will be updating the buffer with UpdateBuffer method + desc.Usage = (m_BindingMode == BindingMode::Bindless) ? USAGE_DEFAULT : USAGE_DYNAMIC; + desc.CPUAccessFlags = CPU_ACCESS_WRITE; + desc.BindFlags = BIND_UNIFORM_BUFFER; + // In bindless mode, we will only write view-projection matrix + desc.uiSizeInBytes = static_cast<Uint32>( (m_BindingMode == BindingMode::Bindless) ? sizeof(DirectX::XMFLOAT4X4) : sizeof(DrawConstantBuffer) ); + mDevice->CreateBuffer(desc, nullptr, &mDrawConstantBuffer); + if (m_BindingMode != BindingMode::Bindless) + Barriers.emplace_back(mDrawConstantBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_CONSTANT_BUFFER, true); + } + if (m_BindingMode == BindingMode::Bindless) { { + // In Direct3D there is no easy way to pass draw call number into the shader, + // so we will use this auxiliary buffer that solely contains integers in ascending order + // (0, 1, 2, ...) and we will acess it with FirstInstanceLocation. BufferDesc desc; - desc.Name = "Instance ID buffer"; - desc.Usage = USAGE_STATIC; - desc.BindFlags = BIND_VERTEX_BUFFER; + desc.Name = "Instance ID buffer"; + desc.Usage = USAGE_STATIC; + desc.BindFlags = BIND_VERTEX_BUFFER; desc.uiSizeInBytes = static_cast<Uint32>(sizeof(Uint32)) * MaxAsteroidsInSubset; std::vector<Uint32> Ids(MaxAsteroidsInSubset); for (Uint32 i=0; i < Ids.size(); ++i) @@ -254,14 +278,17 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G mDevice->CreateBuffer(desc, &Data, &mInstanceIDBuffer); Barriers.emplace_back(mInstanceIDBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_VERTEX_BUFFER, true); } + { + // Structured buffer that contains asteroid data. Evey thread needs to use + // its own buffer. BufferDesc desc; - desc.Name = "Asteroids data buffer"; - desc.Usage = USAGE_DYNAMIC; - desc.BindFlags = BIND_SHADER_RESOURCE; - desc.Mode = BUFFER_MODE_STRUCTURED; - desc.CPUAccessFlags = CPU_ACCESS_WRITE; - desc.ElementByteStride = static_cast<Uint32>(sizeof(DrawConstantBuffer)); + desc.Name = "Asteroids data buffer"; + desc.Usage = USAGE_DYNAMIC; + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.Mode = BUFFER_MODE_STRUCTURED; + desc.CPUAccessFlags = CPU_ACCESS_WRITE; + desc.ElementByteStride = static_cast<Uint32>(sizeof(AsteroidData)); desc.uiSizeInBytes = desc.ElementByteStride * MaxAsteroidsInSubset; mAsteroidsDataBuffers.resize(mNumSubsets); for(Uint32 i=0; i < mNumSubsets; ++i) @@ -270,17 +297,6 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G } } } - else - { - BufferDesc desc; - desc.Name = "Asteroids constant buffer"; - desc.Usage = USAGE_DYNAMIC; - desc.CPUAccessFlags = CPU_ACCESS_WRITE; - desc.BindFlags = BIND_UNIFORM_BUFFER; - desc.uiSizeInBytes = (Uint32) sizeof(DrawConstantBuffer); - mDevice->CreateBuffer(desc, nullptr, &mDrawConstantBuffer); - Barriers.emplace_back(mDrawConstantBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_CONSTANT_BUFFER, true); - } // create pipeline state { @@ -293,6 +309,7 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G }; PSODesc.GraphicsPipeline.InputLayout.LayoutElements = inputDesc; + // In bindless mode we will use instance ID buffer as the third input PSODesc.GraphicsPipeline.InputLayout.NumElements = (m_BindingMode == BindingMode::Bindless) ? 3 : 2; PSODesc.GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_GREATER_EQUAL; @@ -302,8 +319,8 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G ShaderCreateInfo attribs; attribs.Desc.ShaderType = SHADER_TYPE_VERTEX; attribs.Desc.Name = "Asteroids VS"; - attribs.EntryPoint = "asteroid_vs"; - attribs.FilePath = "asteroid_vs.hlsl"; + attribs.EntryPoint = "asteroid_vs_diligent"; + attribs.FilePath = "asteroid_vs_diligent.hlsl"; attribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; attribs.pShaderSourceStreamFactory = pShaderSourceFactory; attribs.UseCombinedTextureSamplers = true; @@ -369,29 +386,32 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G PSODesc.GraphicsPipeline.pVS = vs; PSODesc.GraphicsPipeline.pPS = ps; + mDevice->CreatePipelineState(PSODesc, &mAsteroidsPSO); + mAsteroidsPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "DrawConstantBuffer")->Set(mDrawConstantBuffer); + Uint32 NumSRBs = 0; if(m_BindingMode == BindingMode::Dynamic) { + // Create one SRB per subset for dynamic binding mode NumSRBs = mNumSubsets; } else if(m_BindingMode == BindingMode::Mutable) { + // Create one SRB per asteroid in mutable binding mode PSODesc.SRBAllocationGranularity = 1024; NumSRBs = NUM_ASTEROIDS; } else if(m_BindingMode == BindingMode::TextureMutable) { + // Create one SRB per texture in texture-mutable binding mode PSODesc.SRBAllocationGranularity = NUM_UNIQUE_TEXTURES; NumSRBs = NUM_UNIQUE_TEXTURES; } else if(m_BindingMode == BindingMode::Bindless) { + // Create one SRB per subset for bindless mode NumSRBs = mNumSubsets; } - mDevice->CreatePipelineState(PSODesc, &mAsteroidsPSO); - if (m_BindingMode != BindingMode::Bindless) - mAsteroidsPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "DrawConstantBuffer")->Set(mDrawConstantBuffer); - mAsteroidsSRBs.resize(NumSRBs); for(size_t srb = 0; srb < mAsteroidsSRBs.size(); ++srb) { @@ -583,6 +603,7 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G InitializeTextureData(); if( m_BindingMode == BindingMode::Mutable ) { + // Bind the corresponding texture to the asteroids's SRB for(size_t srb = 0; srb < NUM_ASTEROIDS; ++srb) { auto staticData = &mAsteroids->StaticData()[srb]; @@ -591,6 +612,7 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G } else if( m_BindingMode == BindingMode::TextureMutable ) { + // Bind the corresponding texture to the textures's SRB for(size_t srb = 0; srb < NUM_UNIQUE_TEXTURES; ++srb) { mAsteroidsSRBs[srb]->GetVariableByName(SHADER_TYPE_PIXEL, "Tex")->Set(mTextureSRVs[srb]); @@ -598,6 +620,7 @@ Asteroids::Asteroids(const Settings &settings, AsteroidsSimulation* asteroids, G } else if( m_BindingMode == BindingMode::Bindless ) { + // Bind all textures to every subset's SRB. The textures will be dynamically indexed in the shader. IDeviceObject* SRVArray[NUM_UNIQUE_TEXTURES]; for(Uint32 t = 0; t < NUM_UNIQUE_TEXTURES; ++t) SRVArray[t] = mTextureSRVs[t]; @@ -624,7 +647,6 @@ Asteroids::~Asteroids() } - void Asteroids::ResizeSwapChain(HWND outputWindow, unsigned int width, unsigned int height) { mSwapChain->Resize(width, height); @@ -833,32 +855,37 @@ void Asteroids::RenderSubset(Diligent::Uint32 SubsetNum, { IBuffer* ia_buffers[] = { mVertexBuffer, mInstanceIDBuffer }; Uint32 ia_offsets[_countof(ia_buffers)] = {}; + // Bind instance data buffer in bindless mode pCtx->SetVertexBuffers(0, (m_BindingMode == BindingMode::Bindless) ? 2 : 1, ia_buffers, ia_offsets, RESOURCE_STATE_TRANSITION_MODE_VERIFY, SET_VERTEX_BUFFERS_FLAG_NONE); pCtx->SetIndexBuffer(mIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_VERIFY); } - auto viewProjection = camera.ViewProjection(); - if (m_BindingMode == BindingMode::Bindless) { { - MapHelper<DrawConstantBuffer> drawConstants(pCtx, mAsteroidsDataBuffers[SubsetNum], MAP_WRITE, MAP_FLAG_DISCARD); + // Update asteroid data buffer + MapHelper<AsteroidData> asteroidData(pCtx, mAsteroidsDataBuffers[SubsetNum], MAP_WRITE, MAP_FLAG_DISCARD); UINT i=0; for (UINT drawIdx = startIdx; drawIdx < startIdx+numAsteroids; ++drawIdx, ++i) { const auto staticData = &staticAsteroidData[drawIdx]; const auto dynamicData = &dynamicAsteroidData[drawIdx]; - XMStoreFloat4x4(&drawConstants[i].mWorld, dynamicData->world); - XMStoreFloat4x4(&drawConstants[i].mViewProjection, viewProjection); - drawConstants[i].mSurfaceColor = staticData->surfaceColor; - drawConstants[i].mDeepColor = staticData->deepColor; - drawConstants[i].mTextureIndex = staticData->textureIndex; + XMStoreFloat4x4(&asteroidData[i].mWorld, dynamicData->world); + asteroidData[i].mSurfaceColor = staticData->surfaceColor; + asteroidData[i].mDeepColor = staticData->deepColor; + asteroidData[i].mTextureIndex = staticData->textureIndex; } } - pCtx->CommitShaderResources(mAsteroidsSRBs[SubsetNum], RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + + StateTransitionDesc Barrier{mAsteroidsDataBuffers[SubsetNum], RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_SHADER_RESOURCE, true}; + pCtx->TransitionResourceStates(1, &Barrier); + + // Commit and verify resources + pCtx->CommitShaderResources(mAsteroidsSRBs[SubsetNum], RESOURCE_STATE_TRANSITION_MODE_VERIFY); } + const auto& viewProjection = camera.ViewProjection(); auto pVar = m_BindingMode == BindingMode::Dynamic ? mAsteroidsSRBs[SubsetNum]->GetVariableByName(SHADER_TYPE_PIXEL, "Tex") : nullptr; for (UINT drawIdx = startIdx; drawIdx < startIdx+numAsteroids; ++drawIdx) { @@ -872,8 +899,8 @@ void Asteroids::RenderSubset(Diligent::Uint32 SubsetNum, XMStoreFloat4x4(&drawConstants->mViewProjection, viewProjection); drawConstants->mSurfaceColor = staticData->surfaceColor; drawConstants->mDeepColor = staticData->deepColor; - drawConstants->mTextureIndex = staticData->textureIndex; } + // No need to update the buffer in bindless mode if( m_BindingMode == BindingMode::Dynamic ) { @@ -891,8 +918,16 @@ void Asteroids::RenderSubset(Diligent::Uint32 SubsetNum, DrawIndexedAttribs attribs(dynamicData->indexCount, VT_UINT16, DRAW_FLAG_VERIFY_ALL); attribs.FirstIndexLocation = dynamicData->indexStart; - attribs.BaseVertex = staticData->vertexStart; - attribs.FirstInstanceLocation = drawIdx - startIdx; + attribs.BaseVertex = staticData->vertexStart; + + if( m_BindingMode == BindingMode::Bindless ) + { + // It is very important to speciy this flag to make sure the engine does not do extra + // work processing buffers that stay intact. + attribs.Flags |= DRAW_FLAG_RESOURCE_BUFFERS_INTACT; + attribs.FirstInstanceLocation = drawIdx - startIdx; + } + pCtx->DrawIndexed(attribs); } } @@ -915,13 +950,23 @@ void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Setting auto SubsetSize = NUM_ASTEROIDS / mNumSubsets; + if (m_BindingMode == BindingMode::Bindless) + { + // Write view-projection matrix into the buffer + const auto& viewProjection = camera.ViewProjection(); + mDeviceCtxt->UpdateBuffer(mDrawConstantBuffer, 0, sizeof(DirectX::XMFLOAT4X4), (void*)&viewProjection, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + // Explicitly transition the buffer to CONSTANT_BUFFER state + StateTransitionDesc Barrier{mDrawConstantBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_CONSTANT_BUFFER, true}; + mDeviceCtxt->TransitionResourceStates(1, &Barrier); + } + if (settings.multithreadedRendering) { m_NumThreadsCompleted = 0; mUpdateSubsetsSignal.Trigger(true); } - + // Update all subsets in this thread when multithreadedRendering is false for(Uint32 i=0; i < (!settings.multithreadedRendering ? mNumSubsets : 1); ++i) mAsteroids->Update(frameTime, camera.Eye(), settings, SubsetSize * i, SubsetSize); @@ -933,7 +978,6 @@ void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Setting // Reset mUpdateSubsetsSignal while all threads are waiting for mRenderSubsetsSignal mUpdateSubsetsSignal.Reset(); } - QueryPerformanceCounter((LARGE_INTEGER*)&currCounter); mUpdateTicks = currCounter-mUpdateTicks; @@ -947,6 +991,7 @@ void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Setting mRenderSubsetsSignal.Trigger(true); } + // Render all subsets in this thread when multithreadedRendering is false for(Uint32 i=0; i < (!settings.multithreadedRendering ? mNumSubsets : 1); ++i) RenderSubset(i, mDeviceCtxt, camera, SubsetSize * i, SubsetSize); |
