diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-10-20 08:06:12 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-10-20 08:06:12 +0000 |
| commit | 76b7f63d8140d501c5df2e56c0f8f005e42c038e (patch) | |
| tree | 4b208bebfbebb5ea66f5d0780a5ac0e418460b93 /Projects | |
| parent | Updated core (API version 240035) and shader res array test (diff) | |
| download | DiligentEngine-76b7f63d8140d501c5df2e56c0f8f005e42c038e.tar.gz DiligentEngine-76b7f63d8140d501c5df2e56c0f8f005e42c038e.zip | |
Updated core; finished bindless mode in Asteroids sample (closed https://github.com/DiligentGraphics/DiligentEngine/issues/57)
Diffstat (limited to 'Projects')
| -rw-r--r-- | Projects/Asteroids/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | Projects/Asteroids/src/WinWrapper.cpp | 6 | ||||
| -rw-r--r-- | Projects/Asteroids/src/asteroid_vs.hlsl | 39 | ||||
| -rw-r--r-- | Projects/Asteroids/src/asteroid_vs_diligent.hlsl | 62 | ||||
| -rw-r--r-- | Projects/Asteroids/src/asteroids_DE.cpp | 137 | ||||
| -rw-r--r-- | Projects/Asteroids/src/shader_common.h | 13 |
6 files changed, 170 insertions, 89 deletions
diff --git a/Projects/Asteroids/CMakeLists.txt b/Projects/Asteroids/CMakeLists.txt index d932a61..291369c 100644 --- a/Projects/Asteroids/CMakeLists.txt +++ b/Projects/Asteroids/CMakeLists.txt @@ -45,6 +45,7 @@ set(PIXEL_SHADERS set(VERTEX_SHADERS src/asteroid_vs.hlsl + src/asteroid_vs_diligent.hlsl src/skybox_vs.hlsl src/sprite_vs.hlsl ) @@ -141,6 +142,7 @@ source_group("include" FILES ${INCLUDE}) source_group("shaders" FILES ${SHADERS} src/common_defines.h + src/shader_common.h ) source_group("SDK" FILES SDK/Include/d3dx12.h) source_group("GUI" FILES ${GUI}) diff --git a/Projects/Asteroids/src/WinWrapper.cpp b/Projects/Asteroids/src/WinWrapper.cpp index fd126b4..952c3ab 100644 --- a/Projects/Asteroids/src/WinWrapper.cpp +++ b/Projects/Asteroids/src/WinWrapper.cpp @@ -480,10 +480,10 @@ int main(int argc, char** argv) if (gSettings.mode == Settings::RenderMode::Undefined) { - if (gVulkanAvailable) - gSettings.mode = Settings::RenderMode::DiligentVulkan; - else if (gd3d12Available) + if (gd3d12Available) gSettings.mode = Settings::RenderMode::DiligentD3D12; + else if (gVulkanAvailable) + gSettings.mode = Settings::RenderMode::DiligentVulkan; else gSettings.mode = Settings::RenderMode::DiligentD3D11; } diff --git a/Projects/Asteroids/src/asteroid_vs.hlsl b/Projects/Asteroids/src/asteroid_vs.hlsl index 3498d33..bc9ed8b 100644 --- a/Projects/Asteroids/src/asteroid_vs.hlsl +++ b/Projects/Asteroids/src/asteroid_vs.hlsl @@ -1,46 +1,31 @@ #include "shader_common.h" -#ifdef BINDLESS - -StructuredBuffer<AsteroidData> g_Data; - -#else - cbuffer DrawConstantBuffer { - AsteroidData g_Data; + float4x4 mWorld; + float4x4 mViewProjection; + float4 mSurfaceColor; + float4 mDeepColor; + uint mTextureIndex; }; -#endif - float linstep(float min, float max, float s) { return saturate((s - min) / (max - min)); } - -void asteroid_vs(in float3 in_pos : ATTRIB0, - in float3 in_normal : ATTRIB1, -#ifdef BINDLESS - in uint AsteroidId : ATTRIB2, // SV_InstanceId is not affected by BaseInstance -#endif +void asteroid_vs(in float3 in_pos : ATTRIB0, + in float3 in_normal : ATTRIB1, out float4 position : SV_Position, out VSOut vs_output) { -#ifdef BINDLESS - AsteroidData Data = g_Data[AsteroidId]; -#else - AsteroidData Data = g_Data; -#endif - - float3 positionWorld = mul(Data.World, float4(in_pos, 1.0f)).xyz; - position = mul(Data.ViewProjection, float4(positionWorld, 1.0f)); + float3 positionWorld = mul(mWorld, float4(in_pos, 1.0f)).xyz; + position = mul(mViewProjection, float4(positionWorld, 1.0f)); vs_output.positionModel = in_pos; - vs_output.normalWorld = mul(Data.World, float4(in_normal, 0.0f)).xyz; // No non-uniform scaling + vs_output.normalWorld = mul(mWorld, float4(in_normal, 0.0f)).xyz; // No non-uniform scaling float depth = linstep(0.5f, 0.7f, length(in_pos.xyz)); - vs_output.albedo = lerp(Data.DeepColor.xyz, Data.SurfaceColor.xyz, depth); - - vs_output.textureId = Data.TextureIndex; + vs_output.albedo = lerp(mDeepColor.xyz, mSurfaceColor.xyz, depth); + vs_output.textureId = mTextureIndex; } diff --git a/Projects/Asteroids/src/asteroid_vs_diligent.hlsl b/Projects/Asteroids/src/asteroid_vs_diligent.hlsl new file mode 100644 index 0000000..fa29aba --- /dev/null +++ b/Projects/Asteroids/src/asteroid_vs_diligent.hlsl @@ -0,0 +1,62 @@ +#include "shader_common.h" + +struct AsteroidData +{ + float4x4 World; + float4 SurfaceColor; + + float DeepColorR; + float DeepColorG; + float DeepColorB; + uint TextureIndex; +}; + +#ifdef BINDLESS + +cbuffer DrawConstantBuffer +{ + float4x4 ViewProjection; +} +StructuredBuffer<AsteroidData> g_Data; + +#else + +cbuffer DrawConstantBuffer +{ + float4x4 ViewProjection; + AsteroidData g_Data; +}; + +#endif + +float linstep(float min, float max, float s) +{ + return saturate((s - min) / (max - min)); +} + + +void asteroid_vs_diligent(in float3 in_pos : ATTRIB0, + in float3 in_normal : ATTRIB1, +#ifdef BINDLESS + in uint AsteroidId : ATTRIB2, // SV_InstanceId is not affected by BaseInstance +#endif + out float4 position : SV_Position, + out VSOut vs_output) +{ +#ifdef BINDLESS + AsteroidData Data = g_Data[AsteroidId]; +#else + AsteroidData Data = g_Data; +#endif + + float3 positionWorld = mul(Data.World, float4(in_pos, 1.0f)).xyz; + position = mul(ViewProjection, float4(positionWorld, 1.0f)); + + vs_output.positionModel = in_pos; + vs_output.normalWorld = mul(Data.World, float4(in_normal, 0.0f)).xyz; // No non-uniform scaling + + float depth = linstep(0.5f, 0.7f, length(in_pos.xyz)); + vs_output.albedo = lerp( float3(Data.DeepColorR, Data.DeepColorG, Data.DeepColorB), Data.SurfaceColor.xyz, depth); + + vs_output.textureId = Data.TextureIndex; +} 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); diff --git a/Projects/Asteroids/src/shader_common.h b/Projects/Asteroids/src/shader_common.h index ced6a70..f83f12b 100644 --- a/Projects/Asteroids/src/shader_common.h +++ b/Projects/Asteroids/src/shader_common.h @@ -9,17 +9,4 @@ struct VSOut uint textureId : TEXTURE_ID; }; -struct AsteroidData -{ - float4x4 World; - float4x4 ViewProjection; - float4 SurfaceColor; - float4 DeepColor; - - uint TextureIndex; - uint Padding0; - uint Padding1; - uint Padding2; -}; - #endif |
