/* * Copyright 2019-2021 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * In no event and under no legal theory, whether in tort (including negligence), * contract, or otherwise, unless required by applicable law (such as deliberate * and grossly negligent acts) or agreed to in writing, shall any Contributor be * liable for any damages, including any direct, indirect, special, incidental, * or consequential damages of any character arising as a result of this License or * out of the use or inability to use the software (including but not limited to damages * for loss of goodwill, work stoppage, computer failure or malfunction, or any and * all other commercial damages or losses), even if such Contributor has been advised * of the possibility of such damages. */ #pragma once /// \file /// Implementation of the Diligent::RenderDeviceBase template class and related structures #include "RenderDevice.h" #include "DeviceObjectBase.hpp" #include "Defines.h" #include "ResourceMappingImpl.hpp" #include "StateObjectsRegistry.hpp" #include "HashUtils.hpp" #include "ObjectBase.hpp" #include "DeviceContext.h" #include "SwapChain.h" #include "GraphicsAccessories.hpp" #include "FixedBlockMemoryAllocator.hpp" #include "EngineMemory.h" #include "STDAllocator.hpp" namespace std { /// Hash function specialization for Diligent::SamplerDesc structure. template <> struct hash { size_t operator()(const Diligent::SamplerDesc& SamDesc) const { // Sampler name is ignored in comparison operator // and should not be hashed return Diligent::ComputeHash( // SamDesc.Name, static_cast(SamDesc.MinFilter), static_cast(SamDesc.MagFilter), static_cast(SamDesc.MipFilter), static_cast(SamDesc.AddressU), static_cast(SamDesc.AddressV), static_cast(SamDesc.AddressW), SamDesc.MipLODBias, SamDesc.MaxAnisotropy, static_cast(SamDesc.ComparisonFunc), SamDesc.BorderColor[0], SamDesc.BorderColor[1], SamDesc.BorderColor[2], SamDesc.BorderColor[3], SamDesc.MinLOD, SamDesc.MaxLOD); } }; /// Hash function specialization for Diligent::StencilOpDesc structure. template <> struct hash { size_t operator()(const Diligent::StencilOpDesc& StOpDesc) const { return Diligent::ComputeHash(static_cast(StOpDesc.StencilFailOp), static_cast(StOpDesc.StencilDepthFailOp), static_cast(StOpDesc.StencilPassOp), static_cast(StOpDesc.StencilFunc)); } }; /// Hash function specialization for Diligent::DepthStencilStateDesc structure. template <> struct hash { size_t operator()(const Diligent::DepthStencilStateDesc& DepthStencilDesc) const { return Diligent::ComputeHash(DepthStencilDesc.DepthEnable, DepthStencilDesc.DepthWriteEnable, static_cast(DepthStencilDesc.DepthFunc), DepthStencilDesc.StencilEnable, DepthStencilDesc.StencilReadMask, DepthStencilDesc.StencilWriteMask, DepthStencilDesc.FrontFace, DepthStencilDesc.BackFace); } }; /// Hash function specialization for Diligent::RasterizerStateDesc structure. template <> struct hash { size_t operator()(const Diligent::RasterizerStateDesc& RasterizerDesc) const { return Diligent::ComputeHash(static_cast(RasterizerDesc.FillMode), static_cast(RasterizerDesc.CullMode), RasterizerDesc.FrontCounterClockwise, RasterizerDesc.DepthBias, RasterizerDesc.DepthBiasClamp, RasterizerDesc.SlopeScaledDepthBias, RasterizerDesc.DepthClipEnable, RasterizerDesc.ScissorEnable, RasterizerDesc.AntialiasedLineEnable); } }; /// Hash function specialization for Diligent::BlendStateDesc structure. template <> struct hash { size_t operator()(const Diligent::BlendStateDesc& BSDesc) const { std::size_t Seed = 0; for (size_t i = 0; i < Diligent::MAX_RENDER_TARGETS; ++i) { const auto& rt = BSDesc.RenderTargets[i]; Diligent::HashCombine(Seed, rt.BlendEnable, static_cast(rt.SrcBlend), static_cast(rt.DestBlend), static_cast(rt.BlendOp), static_cast(rt.SrcBlendAlpha), static_cast(rt.DestBlendAlpha), static_cast(rt.BlendOpAlpha), rt.RenderTargetWriteMask); } Diligent::HashCombine(Seed, BSDesc.AlphaToCoverageEnable, BSDesc.IndependentBlendEnable); return Seed; } }; /// Hash function specialization for Diligent::TextureViewDesc structure. template <> struct hash { size_t operator()(const Diligent::TextureViewDesc& TexViewDesc) const { std::size_t Seed = 0; Diligent::HashCombine(Seed, static_cast(TexViewDesc.ViewType), static_cast(TexViewDesc.TextureDim), static_cast(TexViewDesc.Format), TexViewDesc.MostDetailedMip, TexViewDesc.NumMipLevels, TexViewDesc.FirstArraySlice, TexViewDesc.NumArraySlices, static_cast(TexViewDesc.AccessFlags), static_cast(TexViewDesc.Flags)); return Seed; } }; } // namespace std namespace Diligent { /// Base implementation of a render device /// \tparam EngineImplTraits - Engine implementation type traits. /// /// \warning Render device must *NOT* hold strong references to any object it creates /// to avoid cyclic dependencies. Device context, swap chain and all object /// the device creates keep strong reference to the device. /// Device only holds weak reference to the immediate context. template class RenderDeviceBase : public ObjectBase { public: using BaseInterface = typename EngineImplTraits::RenderDeviceInterface; using TObjectBase = ObjectBase; using RenderDeviceImplType = typename EngineImplTraits::RenderDeviceImplType; using PipelineStateImplType = typename EngineImplTraits::PipelineStateImplType; using ShaderResourceBindingImplType = typename EngineImplTraits::ShaderResourceBindingImplType; using BufferImplType = typename EngineImplTraits::BufferImplType; using BufferViewImplType = typename EngineImplTraits::BufferViewImplType; using TextureImplType = typename EngineImplTraits::TextureImplType; using TextureViewImplType = typename EngineImplTraits::TextureViewImplType; using ShaderImplType = typename EngineImplTraits::ShaderImplType; using SamplerImplType = typename EngineImplTraits::SamplerImplType; using FenceImplType = typename EngineImplTraits::FenceImplType; using QueryImplType = typename EngineImplTraits::QueryImplType; using RenderPassImplType = typename EngineImplTraits::RenderPassImplType; using FramebufferImplType = typename EngineImplTraits::FramebufferImplType; using BottomLevelASImplType = typename EngineImplTraits::BottomLevelASImplType; using TopLevelASImplType = typename EngineImplTraits::TopLevelASImplType; using ShaderBindingTableImplType = typename EngineImplTraits::ShaderBindingTableImplType; using PipelineResourceSignatureImplType = typename EngineImplTraits::PipelineResourceSignatureImplType; /// \param pRefCounters - Reference counters object that controls the lifetime of this render device /// \param RawMemAllocator - Allocator that will be used to allocate memory for all device objects (including render device itself) /// \param pEngineFactory - Engine factory that was used to create this device /// \param NumDeferredContexts - The number of deferred device contexts /// /// \remarks Render device uses fixed block allocators (see FixedBlockMemoryAllocator) to allocate memory for /// device objects. The object sizes provided to constructor are used to initialize the allocators. RenderDeviceBase(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator, IEngineFactory* pEngineFactory, Uint32 NumDeferredContexts) : // clang-format off TObjectBase {pRefCounters}, m_pEngineFactory {pEngineFactory}, m_SamplersRegistry {RawMemAllocator, "sampler"}, m_TextureFormatsInfo (TEX_FORMAT_NUM_FORMATS, TextureFormatInfoExt(), STD_ALLOCATOR_RAW_MEM(TextureFormatInfoExt, RawMemAllocator, "Allocator for vector")), m_TexFmtInfoInitFlags (TEX_FORMAT_NUM_FORMATS, false, STD_ALLOCATOR_RAW_MEM(bool, RawMemAllocator, "Allocator for vector")), m_wpDeferredContexts (NumDeferredContexts, RefCntWeakPtr(), STD_ALLOCATOR_RAW_MEM(RefCntWeakPtr, RawMemAllocator, "Allocator for vector< RefCntWeakPtr >")), m_RawMemAllocator {RawMemAllocator}, m_TexObjAllocator {RawMemAllocator, sizeof(TextureImplType), 64}, m_TexViewObjAllocator {RawMemAllocator, sizeof(TextureViewImplType), 64}, m_BufObjAllocator {RawMemAllocator, sizeof(BufferImplType), 128}, m_BuffViewObjAllocator {RawMemAllocator, sizeof(BufferViewImplType), 128}, m_ShaderObjAllocator {RawMemAllocator, sizeof(ShaderImplType), 32}, m_SamplerObjAllocator {RawMemAllocator, sizeof(SamplerImplType), 32}, m_PSOAllocator {RawMemAllocator, sizeof(PipelineStateImplType), 128}, m_SRBAllocator {RawMemAllocator, sizeof(ShaderResourceBindingImplType), 1024}, m_ResMappingAllocator {RawMemAllocator, sizeof(ResourceMappingImpl), 16}, m_FenceAllocator {RawMemAllocator, sizeof(FenceImplType), 16}, m_QueryAllocator {RawMemAllocator, sizeof(QueryImplType), 16}, m_RenderPassAllocator {RawMemAllocator, sizeof(RenderPassImplType), 16}, m_FramebufferAllocator {RawMemAllocator, sizeof(FramebufferImplType), 16}, m_BLASAllocator {RawMemAllocator, sizeof(BottomLevelASImplType), 16}, m_TLASAllocator {RawMemAllocator, sizeof(TopLevelASImplType), 16}, m_SBTAllocator {RawMemAllocator, sizeof(ShaderBindingTableImplType), 16}, m_PipeResSignAllocator {RawMemAllocator, sizeof(PipelineResourceSignatureImplType), 128}, m_DeviceProperties {} // clang-format on { // Initialize texture format info for (Uint32 Fmt = TEX_FORMAT_UNKNOWN; Fmt < TEX_FORMAT_NUM_FORMATS; ++Fmt) static_cast(m_TextureFormatsInfo[Fmt]) = GetTextureFormatAttribs(static_cast(Fmt)); // https://msdn.microsoft.com/en-us/library/windows/desktop/ff471325(v=vs.85).aspx TEXTURE_FORMAT FilterableFormats[] = { TEX_FORMAT_RGBA32_FLOAT, // OpenGL ES3.1 does not require this format to be filterable TEX_FORMAT_RGBA16_FLOAT, TEX_FORMAT_RGBA16_UNORM, TEX_FORMAT_RGBA16_SNORM, TEX_FORMAT_RG32_FLOAT, // OpenGL ES3.1 does not require this format to be filterable TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, //TEX_FORMAT_R10G10B10A2_UNORM, TEX_FORMAT_R11G11B10_FLOAT, TEX_FORMAT_RGBA8_UNORM, TEX_FORMAT_RGBA8_UNORM_SRGB, TEX_FORMAT_RGBA8_SNORM, TEX_FORMAT_RG16_FLOAT, TEX_FORMAT_RG16_UNORM, TEX_FORMAT_RG16_SNORM, TEX_FORMAT_R32_FLOAT, // OpenGL ES3.1 does not require this format to be filterable TEX_FORMAT_R24_UNORM_X8_TYPELESS, TEX_FORMAT_RG8_UNORM, TEX_FORMAT_RG8_SNORM, TEX_FORMAT_R16_FLOAT, TEX_FORMAT_R16_UNORM, TEX_FORMAT_R16_SNORM, TEX_FORMAT_R8_UNORM, TEX_FORMAT_R8_SNORM, TEX_FORMAT_A8_UNORM, TEX_FORMAT_RGB9E5_SHAREDEXP, TEX_FORMAT_RG8_B8G8_UNORM, TEX_FORMAT_G8R8_G8B8_UNORM, TEX_FORMAT_BC1_UNORM, TEX_FORMAT_BC1_UNORM_SRGB, TEX_FORMAT_BC2_UNORM, TEX_FORMAT_BC2_UNORM_SRGB, TEX_FORMAT_BC3_UNORM, TEX_FORMAT_BC3_UNORM_SRGB, TEX_FORMAT_BC4_UNORM, TEX_FORMAT_BC4_SNORM, TEX_FORMAT_BC5_UNORM, TEX_FORMAT_BC5_SNORM, TEX_FORMAT_B5G6R5_UNORM}; for (Uint32 fmt = 0; fmt < _countof(FilterableFormats); ++fmt) m_TextureFormatsInfo[FilterableFormats[fmt]].Filterable = true; } ~RenderDeviceBase() { } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_RenderDevice, ObjectBase) // It is important to have final implementation of Release() method to avoid // virtual calls inline virtual ReferenceCounterValueType DILIGENT_CALL_TYPE Release() override final { return TObjectBase::Release(); } /// Implementation of IRenderDevice::CreateResourceMapping(). virtual void DILIGENT_CALL_TYPE CreateResourceMapping(const ResourceMappingDesc& MappingDesc, IResourceMapping** ppMapping) override final { DEV_CHECK_ERR(ppMapping != nullptr, "Null pointer provided"); if (ppMapping == nullptr) return; DEV_CHECK_ERR(*ppMapping == nullptr, "Overwriting reference to existing object may cause memory leaks"); auto* pResourceMapping{NEW_RC_OBJ(m_ResMappingAllocator, "ResourceMappingImpl instance", ResourceMappingImpl)(GetRawAllocator())}; pResourceMapping->QueryInterface(IID_ResourceMapping, reinterpret_cast(ppMapping)); if (MappingDesc.pEntries) { for (auto* pEntry = MappingDesc.pEntries; pEntry->Name && pEntry->pObject; ++pEntry) { (*ppMapping)->AddResourceArray(pEntry->Name, pEntry->ArrayIndex, &pEntry->pObject, 1, true); } } } /// Implementation of IRenderDevice::GetDeviceCaps(). virtual const DeviceCaps& DILIGENT_CALL_TYPE GetDeviceCaps() const override final { return m_DeviceCaps; } /// Implementation of IRenderDevice::GetDeviceProperties(). virtual const DeviceProperties& DILIGENT_CALL_TYPE GetDeviceProperties() const override final { return m_DeviceProperties; } /// Implementation of IRenderDevice::GetTextureFormatInfo(). virtual const TextureFormatInfo& DILIGENT_CALL_TYPE GetTextureFormatInfo(TEXTURE_FORMAT TexFormat) override final { VERIFY(TexFormat >= TEX_FORMAT_UNKNOWN && TexFormat < TEX_FORMAT_NUM_FORMATS, "Texture format out of range"); const auto& TexFmtInfo = m_TextureFormatsInfo[TexFormat]; VERIFY(TexFmtInfo.Format == TexFormat, "Sanity check failed"); return TexFmtInfo; } /// Implementation of IRenderDevice::GetTextureFormatInfoExt(). virtual const TextureFormatInfoExt& DILIGENT_CALL_TYPE GetTextureFormatInfoExt(TEXTURE_FORMAT TexFormat) override final { VERIFY(TexFormat >= TEX_FORMAT_UNKNOWN && TexFormat < TEX_FORMAT_NUM_FORMATS, "Texture format out of range"); const auto& TexFmtInfo = m_TextureFormatsInfo[TexFormat]; VERIFY(TexFmtInfo.Format == TexFormat, "Sanity check failed"); if (!m_TexFmtInfoInitFlags[TexFormat]) { if (TexFmtInfo.Supported) TestTextureFormat(TexFormat); m_TexFmtInfoInitFlags[TexFormat] = true; } return TexFmtInfo; } virtual IEngineFactory* DILIGENT_CALL_TYPE GetEngineFactory() const override final { return m_pEngineFactory.RawPtr(); } StateObjectsRegistry& GetSamplerRegistry() { return m_SamplersRegistry; } /// Set weak reference to the immediate context void SetImmediateContext(IDeviceContext* pImmediateContext) { VERIFY(m_wpImmediateContext.Lock() == nullptr, "Immediate context has already been set"); m_wpImmediateContext = pImmediateContext; } /// Set weak reference to the deferred context void SetDeferredContext(size_t Ctx, IDeviceContext* pDeferredCtx) { VERIFY(m_wpDeferredContexts[Ctx].Lock() == nullptr, "Deferred context has already been set"); m_wpDeferredContexts[Ctx] = pDeferredCtx; } /// Returns number of deferred contexts size_t GetNumDeferredContexts() const { return m_wpDeferredContexts.size(); } RefCntAutoPtr GetImmediateContext() { return m_wpImmediateContext.Lock(); } RefCntAutoPtr GetDeferredContext(size_t Ctx) { return m_wpDeferredContexts[Ctx].Lock(); } FixedBlockMemoryAllocator& GetTexViewObjAllocator() { return m_TexViewObjAllocator; } FixedBlockMemoryAllocator& GetBuffViewObjAllocator() { return m_BuffViewObjAllocator; } FixedBlockMemoryAllocator& GetSRBAllocator() { return m_SRBAllocator; } protected: virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) = 0; /// Helper template function to facilitate device object creation /// \tparam ObjectType - The type of the object being created (IBuffer, ITexture, etc.). /// \tparam ObjectDescType - The type of the object description structure (BufferDesc, TextureDesc, etc.). /// \tparam ObjectConstructorType - The type of the function that constructs the object. /// /// \param ObjectTypeName - String name of the object type ("buffer", "texture", etc.). /// \param Desc - Object description. /// \param ppObject - Memory address where the pointer to the created object will be stored. /// \param ConstructObject - Function that constructs the object. template void CreateDeviceObject(const Char* ObjectTypeName, const ObjectDescType& Desc, ObjectType** ppObject, ObjectConstructorType ConstructObject) { DEV_CHECK_ERR(ppObject != nullptr, "Null pointer provided"); if (!ppObject) return; DEV_CHECK_ERR(*ppObject == nullptr, "Overwriting reference to existing object may cause memory leaks"); // Do not release *ppObject here! // Should this happen, RefCntAutoPtr<> will take care of this! //if( *ppObject ) //{ // (*ppObject)->Release(); // *ppObject = nullptr; //} *ppObject = nullptr; try { ConstructObject(); } catch (...) { VERIFY(*ppObject == nullptr, "Object was created despite error"); if (*ppObject) { (*ppObject)->Release(); *ppObject = nullptr; } const auto ObjectDescString = GetObjectDescString(Desc); if (!ObjectDescString.empty()) { LOG_ERROR("Failed to create ", ObjectTypeName, " object '", (Desc.Name ? Desc.Name : ""), "'\n", ObjectDescString); } else { LOG_ERROR("Failed to create ", ObjectTypeName, " object '", (Desc.Name ? Desc.Name : ""), "'"); } } } template void CreatePipelineStateImpl(IPipelineState** ppPipelineState, const PSOCreateInfoType& PSOCreateInfo, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, [&]() // { auto* pPipelineStateImpl{NEW_RC_OBJ(m_PSOAllocator, "Pipeline State instance", PipelineStateImplType)(static_cast(this), PSOCreateInfo, ExtraArgs...)}; pPipelineStateImpl->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); }); } template void CreateBufferImpl(IBuffer** ppBuffer, const BufferDesc& BuffDesc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Buffer", BuffDesc, ppBuffer, [&]() // { auto* pBufferImpl{NEW_RC_OBJ(m_BufObjAllocator, "Buffer instance", BufferImplType)(m_BuffViewObjAllocator, static_cast(this), BuffDesc, ExtraArgs...)}; pBufferImpl->QueryInterface(IID_Buffer, reinterpret_cast(ppBuffer)); pBufferImpl->CreateDefaultViews(); }); } template void CreateTextureImpl(ITexture** ppTexture, const TextureDesc& TexDesc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Texture", TexDesc, ppTexture, [&]() // { auto* pTextureImpl{NEW_RC_OBJ(m_TexObjAllocator, "Texture instance", TextureImplType)(m_TexViewObjAllocator, static_cast(this), TexDesc, ExtraArgs...)}; pTextureImpl->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureImpl->CreateDefaultViews(); }); } template void CreateShaderImpl(IShader** ppShader, const ShaderCreateInfo& ShaderCI, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Shader", ShaderCI.Desc, ppShader, [&]() // { auto* pShaderImpl{NEW_RC_OBJ(m_ShaderObjAllocator, "Shader instance", ShaderImplType)(static_cast(this), ShaderCI, ExtraArgs...)}; pShaderImpl->QueryInterface(IID_Shader, reinterpret_cast(ppShader)); }); } template void CreateSamplerImpl(ISampler** ppSampler, const SamplerDesc& SamplerDesc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Sampler", SamplerDesc, ppSampler, [&]() // { m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast(ppSampler)); if (*ppSampler == nullptr) { auto* pSamplerImpl{NEW_RC_OBJ(m_SamplerObjAllocator, "Sampler instance", SamplerImplType)(static_cast(this), SamplerDesc, ExtraArgs...)}; pSamplerImpl->QueryInterface(IID_Sampler, reinterpret_cast(ppSampler)); m_SamplersRegistry.Add(SamplerDesc, *ppSampler); } }); } void CreateFenceImpl(IFence** ppFence, const FenceDesc& Desc) { CreateDeviceObject("Fence", Desc, ppFence, [&]() // { auto* pFenceImpl{NEW_RC_OBJ(m_FenceAllocator, "Fence instance", FenceImplType)(static_cast(this), Desc)}; pFenceImpl->QueryInterface(IID_Fence, reinterpret_cast(ppFence)); }); } void CreateQueryImpl(IQuery** ppQuery, const QueryDesc& Desc) { CreateDeviceObject("Query", Desc, ppQuery, [&]() // { auto* pQueryImpl{NEW_RC_OBJ(m_QueryAllocator, "Query instance", QueryImplType)(static_cast(this), Desc)}; pQueryImpl->QueryInterface(IID_Query, reinterpret_cast(ppQuery)); }); } template void CreateRenderPassImpl(IRenderPass** ppRenderPass, const RenderPassDesc& Desc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("RenderPass", Desc, ppRenderPass, [&]() // { auto* pRenderPassImpl{NEW_RC_OBJ(m_RenderPassAllocator, "Render instance", RenderPassImplType)(static_cast(this), Desc, ExtraArgs...)}; pRenderPassImpl->QueryInterface(IID_RenderPass, reinterpret_cast(ppRenderPass)); }); } template void CreateFramebufferImpl(IFramebuffer** ppFramebuffer, const FramebufferDesc& Desc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("Framebuffer", Desc, ppFramebuffer, [&]() // { auto* pFramebufferImpl{NEW_RC_OBJ(m_FramebufferAllocator, "Framebuffer instance", FramebufferImplType)(static_cast(this), Desc, ExtraArgs...)}; pFramebufferImpl->QueryInterface(IID_Framebuffer, reinterpret_cast(ppFramebuffer)); }); } template void CreateBLASImpl(IBottomLevelAS** ppBLAS, const BottomLevelASDesc& Desc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("BottomLevelAS", Desc, ppBLAS, [&]() // { auto* pBottomLevelASImpl(NEW_RC_OBJ(m_BLASAllocator, "BottomLevelAS instance", BottomLevelASImplType)(static_cast(this), Desc, ExtraArgs...)); pBottomLevelASImpl->QueryInterface(IID_BottomLevelAS, reinterpret_cast(ppBLAS)); }); } template void CreateTLASImpl(ITopLevelAS** ppTLAS, const TopLevelASDesc& Desc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("TopLevelAS", Desc, ppTLAS, [&]() // { auto* pTopLevelASImpl(NEW_RC_OBJ(m_TLASAllocator, "TopLevelAS instance", TopLevelASImplType)(static_cast(this), Desc, ExtraArgs...)); pTopLevelASImpl->QueryInterface(IID_TopLevelAS, reinterpret_cast(ppTLAS)); }); } void CreateSBTImpl(IShaderBindingTable** ppSBT, const ShaderBindingTableDesc& Desc) { CreateDeviceObject("ShaderBindingTable", Desc, ppSBT, [&]() // { auto* pSBTImpl(NEW_RC_OBJ(m_SBTAllocator, "ShaderBindingTable instance", ShaderBindingTableImplType)(static_cast(this), Desc)); pSBTImpl->QueryInterface(IID_ShaderBindingTable, reinterpret_cast(ppSBT)); }); } template void CreatePipelineResourceSignatureImpl(IPipelineResourceSignature** ppSignature, const PipelineResourceSignatureDesc& Desc, const ExtraArgsType&... ExtraArgs) { CreateDeviceObject("PipelineResourceSignature", Desc, ppSignature, [&]() // { auto* pPRSImpl(NEW_RC_OBJ(m_PipeResSignAllocator, "PipelineResourceSignature instance", PipelineResourceSignatureImplType)(static_cast(this), Desc, ExtraArgs...)); pPRSImpl->QueryInterface(IID_PipelineResourceSignature, reinterpret_cast(ppSignature)); }); } protected: RefCntAutoPtr m_pEngineFactory; DeviceCaps m_DeviceCaps; DeviceProperties m_DeviceProperties; // All state object registries hold raw pointers. // This is safe because every object unregisters itself // when it is deleted. StateObjectsRegistry m_SamplersRegistry; ///< Sampler state registry std::vector> m_TextureFormatsInfo; std::vector> m_TexFmtInfoInitFlags; /// Weak reference to the immediate context. Immediate context holds strong reference /// to the device, so we must use weak reference to avoid circular dependencies. RefCntWeakPtr m_wpImmediateContext; /// Weak references to deferred contexts. std::vector, STDAllocatorRawMem>> m_wpDeferredContexts; IMemoryAllocator& m_RawMemAllocator; ///< Raw memory allocator FixedBlockMemoryAllocator m_TexObjAllocator; ///< Allocator for texture objects FixedBlockMemoryAllocator m_TexViewObjAllocator; ///< Allocator for texture view objects FixedBlockMemoryAllocator m_BufObjAllocator; ///< Allocator for buffer objects FixedBlockMemoryAllocator m_BuffViewObjAllocator; ///< Allocator for buffer view objects FixedBlockMemoryAllocator m_ShaderObjAllocator; ///< Allocator for shader objects FixedBlockMemoryAllocator m_SamplerObjAllocator; ///< Allocator for sampler objects FixedBlockMemoryAllocator m_PSOAllocator; ///< Allocator for pipeline state objects FixedBlockMemoryAllocator m_SRBAllocator; ///< Allocator for shader resource binding objects FixedBlockMemoryAllocator m_ResMappingAllocator; ///< Allocator for resource mapping objects FixedBlockMemoryAllocator m_FenceAllocator; ///< Allocator for fence objects FixedBlockMemoryAllocator m_QueryAllocator; ///< Allocator for query objects FixedBlockMemoryAllocator m_RenderPassAllocator; ///< Allocator for render pass objects FixedBlockMemoryAllocator m_FramebufferAllocator; ///< Allocator for framebuffer objects FixedBlockMemoryAllocator m_BLASAllocator; ///< Allocator for bottom-level acceleration structure objects FixedBlockMemoryAllocator m_TLASAllocator; ///< Allocator for top-level acceleration structure objects FixedBlockMemoryAllocator m_SBTAllocator; ///< Allocator for shader binding table objects FixedBlockMemoryAllocator m_PipeResSignAllocator; ///< Allocator for pipeline resource signature objects }; } // namespace Diligent