git.s-ol.nu ~forks/DiligentFX / 8d0f1fe
GLTF PBR Renderer: moved SRB managing out of the renderer assiduous 10 months ago
2 changed file(s) with 78 addition(s) and 135 deletion(s). Raw diff Collapse all Expand all
207207 {}
208208 };
209209
210 struct ModelResourceBindings
211 {
212 std::vector<RefCntAutoPtr<IShaderResourceBinding>> MaterialSRB;
213 };
214
210215 /// Renders the given GLTF model.
211216
212217 /// \param [in] pCtx - Device context to record rendering commands to.
213218 /// \param [in] GLTFModel - GLTF model to render.
214219 /// \param [in] RenderParams - Render parameters.
220 /// \param [in] ResourceBindings - Model shader resource bindings.
215221 /// \param [in] RenderNodeCallback - Optional render call back function that should be called
216222 /// for every GLTF node instead of rendering it.
217223 /// \param [in] SRBTypeId - Optional application-defined SRB type that was given to
219225 void Render(IDeviceContext* pCtx,
220226 GLTF::Model& GLTFModel,
221227 const RenderInfo& RenderParams,
222 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback = nullptr,
223 size_t SRBTypeId = 0);
224
225 /// Initializes resource bindings for a given GLTF model
226 void InitializeResourceBindings(GLTF::Model& GLTFModel,
227 IBuffer* pCameraAttribs,
228 IBuffer* pLightAttribs);
229
230 /// Releases resource bindings for a given GLTF model and SRB type
231 void ReleaseResourceBindings(GLTF::Model& GLTFModel, size_t SRBTypeId = 0);
228 const ModelResourceBindings& ResourceBindings,
229 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback = nullptr);
230
231 /// Creates resource bindings for a given GLTF model
232 ModelResourceBindings CreateResourceBindings(GLTF::Model& GLTFModel,
233 IBuffer* pCameraAttribs,
234 IBuffer* pLightAttribs);
232235
233236 /// Precompute cubemaps used by IBL.
234237 void PrecomputeCubemaps(IRenderDevice* pDevice,
250253 /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB.
251254 /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB.
252255 /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the
253 /// default PSO.
254 /// \param [in] TypeId - Optional application-defined type to associate created SRB object with.
255 /// This type can be used when retreiving the SRB with GetMaterialSRB or
256 /// rendering the model with Render.
257 /// An application may use this type to differentiate e.g. shadow-pass SRBs
258 /// from color-pass SRBs.
259 /// \return Created shader resource binding.
260 IShaderResourceBinding* CreateMaterialSRB(GLTF::Model& Model,
261 GLTF::Material& Material,
262 IBuffer* pCameraAttribs,
263 IBuffer* pLightAttribs,
264 IPipelineState* pPSO = nullptr,
265 size_t TypeId = 0);
266
267 /// Finds a shader resource binding for the given material.
268
269 /// \param [in] Material - GLTF material to find SRB for.
270 /// \param [in] TypeId - Optional application-defined type ID that was given to CreateMaterialSRB.
271 /// \return Shader resource binding.
272 IShaderResourceBinding* GetMaterialSRB(const GLTF::Material* material, size_t TypeId = 0)
273 {
274 auto it = m_SRBCache.find(SRBCacheKey{material, TypeId});
275 return it != m_SRBCache.end() ? it->second.RawPtr() : nullptr;
276 }
256 /// default PSO. Can be null
257 /// \param [out] ppMaterialSRB - Pointer to memory location where the pointer to the SRB object
258 /// will be written.
259 void CreateMaterialSRB(GLTF::Model& Model,
260 GLTF::Material& Material,
261 IBuffer* pCameraAttribs,
262 IBuffer* pLightAttribs,
263 IPipelineState* pPSO,
264 IShaderResourceBinding** ppMaterialSRB);
277265
278266 void Begin(IDeviceContext* pCtx);
279267
334322 RefCntAutoPtr<ITextureView> m_pBlackTexSRV;
335323 RefCntAutoPtr<ITextureView> m_pDefaultNormalMapSRV;
336324
337 struct SRBCacheKey
338 {
339 const GLTF::Material* pMaterial = nullptr;
340 size_t TypeId = 0;
341
342 SRBCacheKey() = default;
343
344 SRBCacheKey(const GLTF::Material* _pMaterial,
345 size_t _TypeId) :
346 pMaterial{_pMaterial},
347 TypeId{_TypeId}
348 {}
349
350
351 bool operator==(const SRBCacheKey& Key) const
352 {
353 return pMaterial == Key.pMaterial && TypeId == Key.TypeId;
354 }
355
356 struct Hasher
357 {
358 size_t operator()(const SRBCacheKey& Key) const
359 {
360 return ComputeHash(Key.pMaterial, Key.TypeId);
361 }
362 };
363 };
364
365 std::mutex m_SRBCacheMtx;
366 std::unordered_map<SRBCacheKey, RefCntAutoPtr<IShaderResourceBinding>, SRBCacheKey::Hasher> m_SRBCache;
367325
368326 static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA32_FLOAT;
369327 static constexpr TEXTURE_FORMAT PrefilteredEnvMapFmt = TEX_FORMAT_RGBA16_FLOAT;
390348 IDeviceContext* const pCtx;
391349 GLTF::Model& GLTFModel;
392350 const RenderInfo& RenderParams;
351 const ModelResourceBindings& ResourceBindings;
393352 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback;
394 const size_t SRBTypeId;
395353
396354 const Uint32 FirstIndexLocation;
397355 const Uint32 BaseVertex;
389389 }
390390 }
391391
392 IShaderResourceBinding* GLTF_PBR_Renderer::CreateMaterialSRB(GLTF::Model& Model,
393 GLTF::Material& Material,
394 IBuffer* pCameraAttribs,
395 IBuffer* pLightAttribs,
396 IPipelineState* pPSO,
397 size_t TypeId)
392 void GLTF_PBR_Renderer::CreateMaterialSRB(GLTF::Model& Model,
393 GLTF::Material& Material,
394 IBuffer* pCameraAttribs,
395 IBuffer* pLightAttribs,
396 IPipelineState* pPSO,
397 IShaderResourceBinding** ppMaterialSRB)
398398 {
399399 if (pPSO == nullptr)
400400 pPSO = GetPSO(PSOKey{});
401401
402 RefCntAutoPtr<IShaderResourceBinding> pSRB;
403 pPSO->CreateShaderResourceBinding(&pSRB, true);
402 pPSO->CreateShaderResourceBinding(ppMaterialSRB, true);
403 auto* pSRB = *ppMaterialSRB;
404 if (pSRB == nullptr)
405 {
406 LOG_ERROR_MESSAGE("Failed to create material SRB");
407 return;
408 }
404409
405410 if (auto* pCameraAttribsVSVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbCameraAttribs"))
406411 pCameraAttribsVSVar->Set(pCameraAttribs);
454459 if (m_Settings.UseEmissive)
455460 {
456461 SetTexture(GLTF::Material::TEXTURE_ID_EMISSIVE, m_pBlackTexSRV, "g_EmissiveMap");
457 }
458
459
460 {
461 SRBCacheKey SRBKey{&Material, TypeId};
462
463 std::lock_guard<std::mutex> Lock{m_SRBCacheMtx};
464
465 auto it = m_SRBCache.find(SRBKey);
466 if (it != m_SRBCache.end())
467 {
468 it->second = std::move(pSRB);
469 return it->second;
470 }
471 else
472 {
473 auto new_it = m_SRBCache.emplace(SRBKey, std::move(pSRB));
474 VERIFY_EXPR(new_it.second);
475 return new_it.first->second;
476 }
477462 }
478463 }
479464
726711 }
727712
728713
729 void GLTF_PBR_Renderer::InitializeResourceBindings(GLTF::Model& GLTFModel,
730 IBuffer* pCameraAttribs,
731 IBuffer* pLightAttribs)
714 GLTF_PBR_Renderer::ModelResourceBindings GLTF_PBR_Renderer::CreateResourceBindings(
715 GLTF::Model& GLTFModel,
716 IBuffer* pCameraAttribs,
717 IBuffer* pLightAttribs)
732718 {
733 for (auto& mat : GLTFModel.Materials)
734 {
735 CreateMaterialSRB(GLTFModel, mat, pCameraAttribs, pLightAttribs);
736 }
719 ModelResourceBindings ResourceBindings;
720 ResourceBindings.MaterialSRB.resize(GLTFModel.Materials.size());
721 for (size_t mat = 0; mat < GLTFModel.Materials.size(); ++mat)
722 {
723 CreateMaterialSRB(GLTFModel, GLTFModel.Materials[mat], pCameraAttribs, pLightAttribs, nullptr, &ResourceBindings.MaterialSRB[mat]);
724 }
725 return ResourceBindings;
737726 }
738
739 void GLTF_PBR_Renderer::ReleaseResourceBindings(GLTF::Model& GLTFModel, size_t SRBTypeId)
740 {
741 std::lock_guard<std::mutex> Lock{m_SRBCacheMtx};
742 for (auto& mat : GLTFModel.Materials)
743 {
744 m_SRBCache.erase(SRBCacheKey{&mat, SRBTypeId});
745 }
746 }
747
748727
749728 void GLTF_PBR_Renderer::GLTFNodeRenderer::Render(const GLTF::Node& Node,
750729 GLTF::Material::ALPHA_MODE AlphaMode)
751730 {
752 if (Node._Mesh)
731 if (Node.Mesh)
753732 {
754733 // Render mesh primitives
755 for (const auto& primitive : Node._Mesh->Primitives)
756 {
757 if (primitive->material.AlphaMode != AlphaMode)
734 for (const auto& primitive : Node.Mesh->Primitives)
735 {
736 const auto& material = GLTFModel.Materials[primitive.MaterialId];
737 if (material.AlphaMode != AlphaMode)
758738 continue;
759739
760 const auto& material = primitive->material;
761740 if (RenderNodeCallback == nullptr)
762741 {
763742 auto* pPSO = Renderer.GetPSO(PSOKey{AlphaMode, material.DoubleSided});
764743 VERIFY_EXPR(pPSO != nullptr);
765744 pCtx->SetPipelineState(pPSO);
766745
767 auto* pSRB = Renderer.GetMaterialSRB(&material, SRBTypeId);
746 VERIFY(primitive.MaterialId < ResourceBindings.MaterialSRB.size(),
747 "Material index is out of bounds. This mostl likely indicates that shader resources were initialized for a different model.");
748
749 IShaderResourceBinding* const pSRB = ResourceBindings.MaterialSRB[primitive.MaterialId].RawPtr<IShaderResourceBinding>();
768750 if (pSRB == nullptr)
769751 {
770 LOG_ERROR_MESSAGE("Unable to find SRB for GLTF material. Please call GLTF_PBR_Renderer::InitializeResourceBindings()");
752 LOG_ERROR_MESSAGE("Unable to find SRB for GLTF material. Please call GLTF_PBR_Renderer::CreateResourceBindings()");
771753 continue;
772754 }
773755 pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
774756
775 size_t JointCount = Node._Mesh->Transforms.jointMatrices.size();
757 size_t JointCount = Node.Mesh->Transforms.jointMatrices.size();
776758 if (JointCount > Renderer.m_Settings.MaxJointCount)
777759 {
778760 LOG_WARNING_MESSAGE("The number of joints in the mesh (", JointCount, ") exceeds the maximum number (", Renderer.m_Settings.MaxJointCount,
782764
783765 {
784766 MapHelper<GLTFNodeShaderTransforms> pTransforms{pCtx, Renderer.m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD};
785 pTransforms->NodeMatrix = Node._Mesh->Transforms.matrix * RenderParams.ModelTransform;
767 pTransforms->NodeMatrix = Node.Mesh->Transforms.matrix * RenderParams.ModelTransform;
786768 pTransforms->JointCount = static_cast<int>(JointCount);
787769 }
788770
789 if (JointCount != 0 && pLastAnimatedMesh != Node._Mesh.get())
771 if (JointCount != 0 && pLastAnimatedMesh != Node.Mesh.get())
790772 {
791773 MapHelper<float4x4> pJoints{pCtx, Renderer.m_JointsBuffer, MAP_WRITE, MAP_FLAG_DISCARD};
792 memcpy(pJoints, Node._Mesh->Transforms.jointMatrices.data(), JointCount * sizeof(float4x4));
793 pLastAnimatedMesh = Node._Mesh.get();
774 memcpy(pJoints, Node.Mesh->Transforms.jointMatrices.data(), JointCount * sizeof(float4x4));
775 pLastAnimatedMesh = Node.Mesh.get();
794776 }
795777
796778 {
820802 ShaderParams.PrefilteredCubeMipLevels = Renderer.m_Settings.UseIBL ? static_cast<float>(Renderer.m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
821803 }
822804
823 if (primitive->hasIndices)
805 if (primitive.HasIndices())
824806 {
825 DrawIndexedAttribs drawAttrs{primitive->IndexCount, VT_UINT32, DRAW_FLAG_VERIFY_ALL};
826 drawAttrs.FirstIndexLocation = FirstIndexLocation + primitive->FirstIndex;
807 DrawIndexedAttribs drawAttrs{primitive.IndexCount, VT_UINT32, DRAW_FLAG_VERIFY_ALL};
808 drawAttrs.FirstIndexLocation = FirstIndexLocation + primitive.FirstIndex;
827809 drawAttrs.BaseVertex = BaseVertex;
828810 pCtx->DrawIndexed(drawAttrs);
829811 }
830812 else
831813 {
832 DrawAttribs drawAttrs{primitive->VertexCount, DRAW_FLAG_VERIFY_ALL};
814 DrawAttribs drawAttrs{primitive.VertexCount, DRAW_FLAG_VERIFY_ALL};
833815 drawAttrs.StartVertexLocation = BaseVertex;
834816 pCtx->Draw(drawAttrs);
835817 }
838820 {
839821 GLTFNodeRenderInfo NodeRI;
840822 NodeRI.pMaterial = &material;
841 NodeRI.pTransformData = &Node._Mesh->Transforms;
842 NodeRI.IndexType = primitive->hasIndices ? VT_UINT32 : VT_UNDEFINED;
823 NodeRI.pTransformData = &Node.Mesh->Transforms;
824 NodeRI.IndexType = primitive.HasIndices() ? VT_UINT32 : VT_UNDEFINED;
843825 NodeRI.BaseVertex = BaseVertex;
844826
845 if (primitive->hasIndices)
827 if (primitive.HasIndices())
846828 {
847 NodeRI.IndexCount = primitive->IndexCount;
848 NodeRI.FirstIndex = FirstIndexLocation + primitive->FirstIndex;
829 NodeRI.IndexCount = primitive.IndexCount;
830 NodeRI.FirstIndex = FirstIndexLocation + primitive.FirstIndex;
849831 }
850832 else
851833 {
852 NodeRI.VertexCount = primitive->VertexCount;
834 NodeRI.VertexCount = primitive.VertexCount;
853835 }
854836
855837 RenderNodeCallback(NodeRI);
872854 void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx,
873855 GLTF::Model& GLTFModel,
874856 const RenderInfo& RenderParams,
875 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback,
876 size_t SRBTypeId)
857 const ModelResourceBindings& ResourceBindings,
858 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback)
877859 {
860 DEV_CHECK_ERR(ResourceBindings.MaterialSRB.size() == GLTFModel.Materials.size(),
861 "The number of material shader resource bindings is not consistent with the number of materials");
862
878863 m_RenderParams = RenderParams;
879864
880865 if (RenderNodeCallback == nullptr)
903888 pCtx,
904889 GLTFModel,
905890 RenderParams,
891 ResourceBindings,
906892 RenderNodeCallback,
907 SRBTypeId,
908893 GLTFModel.GetFirstIndexLocation(),
909894 GLTFModel.GetBaseVertex() //
910895 };