From 38ad2d5cb659074ad9b4bde16bcbf71481719b94 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 26 Jan 2020 13:44:37 -0800 Subject: Renamed .h -> .hpp in GraphicsEngine, GraphicsEngineD3DBase, GraphicsEningeD3D11, and GraphicsEningeD3D12 projects --- Graphics/GLSLTools/src/SPIRVShaderResources.cpp | 2 +- Graphics/GraphicsEngine/CMakeLists.txt | 38 +- Graphics/GraphicsEngine/include/BufferBase.h | 282 ---- Graphics/GraphicsEngine/include/BufferBase.hpp | 282 ++++ Graphics/GraphicsEngine/include/BufferViewBase.h | 108 -- Graphics/GraphicsEngine/include/BufferViewBase.hpp | 108 ++ Graphics/GraphicsEngine/include/CommandListBase.h | 72 - .../GraphicsEngine/include/CommandListBase.hpp | 72 + .../GraphicsEngine/include/DeviceContextBase.h | 1518 -------------------- .../GraphicsEngine/include/DeviceContextBase.hpp | 1518 ++++++++++++++++++++ Graphics/GraphicsEngine/include/DeviceObjectBase.h | 178 --- .../GraphicsEngine/include/DeviceObjectBase.hpp | 178 +++ .../GraphicsEngine/include/EngineFactoryBase.h | 155 -- .../GraphicsEngine/include/EngineFactoryBase.hpp | 155 ++ Graphics/GraphicsEngine/include/FenceBase.h | 71 - Graphics/GraphicsEngine/include/FenceBase.hpp | 71 + .../GraphicsEngine/include/PipelineStateBase.h | 390 ----- .../GraphicsEngine/include/PipelineStateBase.hpp | 390 +++++ Graphics/GraphicsEngine/include/QueryBase.h | 243 ---- Graphics/GraphicsEngine/include/QueryBase.hpp | 243 ++++ Graphics/GraphicsEngine/include/RenderDeviceBase.h | 502 ------- .../GraphicsEngine/include/RenderDeviceBase.hpp | 502 +++++++ .../GraphicsEngine/include/ResourceMappingImpl.h | 136 -- .../GraphicsEngine/include/ResourceMappingImpl.hpp | 136 ++ Graphics/GraphicsEngine/include/SamplerBase.h | 74 - Graphics/GraphicsEngine/include/SamplerBase.hpp | 74 + Graphics/GraphicsEngine/include/ShaderBase.h | 122 -- Graphics/GraphicsEngine/include/ShaderBase.hpp | 122 ++ .../include/ShaderResourceBindingBase.h | 90 -- .../include/ShaderResourceBindingBase.hpp | 90 ++ .../include/ShaderResourceVariableBase.h | 379 ----- .../include/ShaderResourceVariableBase.hpp | 379 +++++ .../GraphicsEngine/include/StateObjectsRegistry.h | 213 --- .../include/StateObjectsRegistry.hpp | 213 +++ Graphics/GraphicsEngine/include/SwapChainBase.h | 118 -- Graphics/GraphicsEngine/include/SwapChainBase.hpp | 118 ++ Graphics/GraphicsEngine/include/TextureBase.h | 515 ------- Graphics/GraphicsEngine/include/TextureBase.hpp | 515 +++++++ Graphics/GraphicsEngine/include/TextureViewBase.h | 135 -- .../GraphicsEngine/include/TextureViewBase.hpp | 135 ++ Graphics/GraphicsEngine/include/pch.h | 4 +- Graphics/GraphicsEngine/src/ResourceMapping.cpp | 4 +- Graphics/GraphicsEngineD3D11/CMakeLists.txt | 42 +- .../GraphicsEngineD3D11/include/BufferD3D11Impl.h | 97 -- .../include/BufferD3D11Impl.hpp | 97 ++ .../include/BufferViewD3D11Impl.h | 68 - .../include/BufferViewD3D11Impl.hpp | 68 + .../include/CommandListD3D11Impl.h | 59 - .../include/CommandListD3D11Impl.hpp | 59 + .../include/DeviceContextD3D11Impl.h | 438 ------ .../include/DeviceContextD3D11Impl.hpp | 438 ++++++ .../include/DisjointQueryPool.h | 102 -- .../include/DisjointQueryPool.hpp | 102 ++ .../GraphicsEngineD3D11/include/FenceD3D11Impl.h | 89 -- .../GraphicsEngineD3D11/include/FenceD3D11Impl.hpp | 89 ++ .../include/PipelineStateD3D11Impl.h | 158 -- .../include/PipelineStateD3D11Impl.hpp | 158 ++ .../GraphicsEngineD3D11/include/QueryD3D11Impl.h | 85 -- .../GraphicsEngineD3D11/include/QueryD3D11Impl.hpp | 85 ++ .../include/RenderDeviceD3D11Impl.h | 108 -- .../include/RenderDeviceD3D11Impl.hpp | 108 ++ .../GraphicsEngineD3D11/include/SamplerD3D11Impl.h | 64 - .../include/SamplerD3D11Impl.hpp | 64 + .../GraphicsEngineD3D11/include/ShaderD3D11Impl.h | 99 -- .../include/ShaderD3D11Impl.hpp | 99 ++ .../include/ShaderResourceBindingD3D11Impl.h | 108 -- .../include/ShaderResourceBindingD3D11Impl.hpp | 108 ++ .../include/ShaderResourceCacheD3D11.h | 334 ----- .../include/ShaderResourceCacheD3D11.hpp | 334 +++++ .../include/ShaderResourceLayoutD3D11.h | 415 ------ .../include/ShaderResourceLayoutD3D11.hpp | 415 ++++++ .../include/ShaderResourcesD3D11.h | 142 -- .../include/ShaderResourcesD3D11.hpp | 142 ++ .../include/SwapChainD3D11Impl.h | 80 -- .../include/SwapChainD3D11Impl.hpp | 80 ++ .../GraphicsEngineD3D11/include/Texture1D_D3D11.h | 64 - .../include/Texture1D_D3D11.hpp | 64 + .../GraphicsEngineD3D11/include/Texture2D_D3D11.h | 64 - .../include/Texture2D_D3D11.hpp | 64 + .../GraphicsEngineD3D11/include/Texture3D_D3D11.h | 64 - .../include/Texture3D_D3D11.hpp | 64 + .../GraphicsEngineD3D11/include/TextureBaseD3D11.h | 98 -- .../include/TextureBaseD3D11.hpp | 98 ++ .../include/TextureViewD3D11Impl.h | 69 - .../include/TextureViewD3D11Impl.hpp | 69 + Graphics/GraphicsEngineD3D11/include/pch.h | 4 +- .../GraphicsEngineD3D11/src/BufferD3D11Impl.cpp | 8 +- .../src/BufferViewD3D11Impl.cpp | 2 +- .../src/CommandListD3D11Impl.cpp | 2 +- .../src/D3D11TypeConversions.cpp | 4 +- .../src/DeviceContextD3D11Impl.cpp | 28 +- .../GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp | 8 +- .../GraphicsEngineD3D11/src/FenceD3D11Impl.cpp | 2 +- .../src/PipelineStateD3D11Impl.cpp | 8 +- .../GraphicsEngineD3D11/src/QueryD3D11Impl.cpp | 4 +- .../src/RenderDeviceD3D11Impl.cpp | 26 +- .../GraphicsEngineD3D11/src/SamplerD3D11Impl.cpp | 4 +- .../GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp | 4 +- .../src/ShaderResourceBindingD3D11Impl.cpp | 8 +- .../src/ShaderResourceCacheD3D11.cpp | 10 +- .../src/ShaderResourceLayoutD3D11.cpp | 16 +- .../src/ShaderResourcesD3D11.cpp | 8 +- .../GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp | 6 +- .../GraphicsEngineD3D11/src/Texture1D_D3D11.cpp | 4 +- .../GraphicsEngineD3D11/src/Texture2D_D3D11.cpp | 4 +- .../GraphicsEngineD3D11/src/Texture3D_D3D11.cpp | 4 +- .../GraphicsEngineD3D11/src/TextureBaseD3D11.cpp | 8 +- .../src/TextureViewD3D11Impl.cpp | 4 +- Graphics/GraphicsEngineD3D12/CMakeLists.txt | 56 +- .../GraphicsEngineD3D12/include/BufferD3D12Impl.h | 123 -- .../include/BufferD3D12Impl.hpp | 123 ++ .../include/BufferViewD3D12Impl.h | 67 - .../include/BufferViewD3D12Impl.hpp | 67 + .../GraphicsEngineD3D12/include/CommandContext.h | 435 ------ .../GraphicsEngineD3D12/include/CommandContext.hpp | 435 ++++++ .../include/CommandListD3D12Impl.h | 88 -- .../include/CommandListD3D12Impl.hpp | 88 ++ .../include/CommandListManager.h | 81 -- .../include/CommandListManager.hpp | 81 ++ .../include/CommandQueueD3D12Impl.h | 88 -- .../include/CommandQueueD3D12Impl.hpp | 88 ++ .../GraphicsEngineD3D12/include/D3D12DynamicHeap.h | 208 --- .../include/D3D12DynamicHeap.hpp | 208 +++ Graphics/GraphicsEngineD3D12/include/D3D12Loader.h | 57 - .../GraphicsEngineD3D12/include/D3D12Loader.hpp | 57 + .../include/D3D12ResourceBase.h | 49 - .../include/D3D12ResourceBase.hpp | 49 + .../GraphicsEngineD3D12/include/DescriptorHeap.h | 569 -------- .../GraphicsEngineD3D12/include/DescriptorHeap.hpp | 569 ++++++++ .../include/DeviceContextD3D12Impl.h | 404 ------ .../include/DeviceContextD3D12Impl.hpp | 404 ++++++ .../GraphicsEngineD3D12/include/FenceD3D12Impl.h | 72 - .../GraphicsEngineD3D12/include/FenceD3D12Impl.hpp | 72 + .../GraphicsEngineD3D12/include/GenerateMips.h | 66 - .../GraphicsEngineD3D12/include/GenerateMips.hpp | 66 + .../include/PipelineStateD3D12Impl.h | 135 -- .../include/PipelineStateD3D12Impl.hpp | 135 ++ .../GraphicsEngineD3D12/include/QueryD3D12Impl.h | 79 - .../GraphicsEngineD3D12/include/QueryD3D12Impl.hpp | 79 + .../include/QueryManagerD3D12.h | 90 -- .../include/QueryManagerD3D12.hpp | 90 ++ .../include/RenderDeviceD3D12Impl.h | 163 --- .../include/RenderDeviceD3D12Impl.hpp | 163 +++ .../GraphicsEngineD3D12/include/RootSignature.h | 591 -------- .../GraphicsEngineD3D12/include/RootSignature.hpp | 591 ++++++++ .../GraphicsEngineD3D12/include/SamplerD3D12Impl.h | 66 - .../include/SamplerD3D12Impl.hpp | 66 + .../GraphicsEngineD3D12/include/ShaderD3D12Impl.h | 87 -- .../include/ShaderD3D12Impl.hpp | 87 ++ .../include/ShaderResourceBindingD3D12Impl.h | 88 -- .../include/ShaderResourceBindingD3D12Impl.hpp | 88 ++ .../include/ShaderResourceCacheD3D12.h | 354 ----- .../include/ShaderResourceCacheD3D12.hpp | 354 +++++ .../include/ShaderResourceLayoutD3D12.h | 360 ----- .../include/ShaderResourceLayoutD3D12.hpp | 360 +++++ .../include/ShaderResourcesD3D12.h | 105 -- .../include/ShaderResourcesD3D12.hpp | 105 ++ .../include/ShaderVariableD3D12.h | 222 --- .../include/ShaderVariableD3D12.hpp | 222 +++ .../include/SwapChainD3D12Impl.h | 87 -- .../include/SwapChainD3D12Impl.hpp | 87 ++ .../GraphicsEngineD3D12/include/TextureD3D12Impl.h | 105 -- .../include/TextureD3D12Impl.hpp | 105 ++ .../include/TextureViewD3D12Impl.h | 90 -- .../include/TextureViewD3D12Impl.hpp | 90 ++ Graphics/GraphicsEngineD3D12/include/pch.h | 6 +- .../GraphicsEngineD3D12/src/BufferD3D12Impl.cpp | 8 +- .../src/BufferViewD3D12Impl.cpp | 2 +- .../GraphicsEngineD3D12/src/CommandContext.cpp | 8 +- .../GraphicsEngineD3D12/src/CommandListManager.cpp | 4 +- .../src/CommandQueueD3D12Impl.cpp | 2 +- .../GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp | 4 +- Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp | 2 +- .../src/D3D12TypeConversions.cpp | 4 +- .../GraphicsEngineD3D12/src/DescriptorHeap.cpp | 4 +- .../src/DeviceContextD3D12Impl.cpp | 18 +- .../GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp | 10 +- .../GraphicsEngineD3D12/src/FenceD3D12Impl.cpp | 4 +- Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp | 10 +- .../src/PipelineStateD3D12Impl.cpp | 12 +- .../GraphicsEngineD3D12/src/QueryD3D12Impl.cpp | 6 +- .../GraphicsEngineD3D12/src/QueryManagerD3D12.cpp | 4 +- .../src/RenderDeviceD3D12Impl.cpp | 20 +- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 12 +- .../GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp | 4 +- .../GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp | 4 +- .../src/ShaderResourceBindingD3D12Impl.cpp | 8 +- .../src/ShaderResourceCacheD3D12.cpp | 4 +- .../src/ShaderResourceLayoutD3D12.cpp | 20 +- .../src/ShaderResourcesD3D12.cpp | 6 +- .../src/ShaderVariableD3D12.cpp | 4 +- .../GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp | 8 +- .../GraphicsEngineD3D12/src/TextureD3D12Impl.cpp | 8 +- .../src/TextureViewD3D12Impl.cpp | 4 +- Graphics/GraphicsEngineD3DBase/CMakeLists.txt | 20 +- Graphics/GraphicsEngineD3DBase/include/D3DErrors.h | 114 -- .../GraphicsEngineD3DBase/include/D3DErrors.hpp | 114 ++ .../include/D3DShaderResourceLoader.h | 306 ---- .../include/D3DShaderResourceLoader.hpp | 306 ++++ .../include/D3DTypeConversionImpl.h | 589 -------- .../include/D3DTypeConversionImpl.hpp | 589 ++++++++ .../include/D3DViewDescConversionImpl.h | 344 ----- .../include/D3DViewDescConversionImpl.hpp | 344 +++++ .../include/EngineFactoryD3DBase.h | 229 --- .../include/EngineFactoryD3DBase.hpp | 229 +++ .../include/RenderDeviceD3DBase.h | 182 --- .../include/RenderDeviceD3DBase.hpp | 182 +++ .../GraphicsEngineD3DBase/include/ShaderD3DBase.h | 50 - .../include/ShaderD3DBase.hpp | 50 + .../include/ShaderResources.h | 587 -------- .../include/ShaderResources.hpp | 587 ++++++++ .../include/ShaderVariableD3DBase.h | 89 -- .../include/ShaderVariableD3DBase.hpp | 89 ++ .../include/SwapChainD3DBase.h | 248 ---- .../include/SwapChainD3DBase.hpp | 248 ++++ .../GraphicsEngineD3DBase/src/ShaderD3DBase.cpp | 4 +- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 4 +- .../include/DeviceContextNextGenBase.h | 2 +- .../GraphicsEngineOpenGL/include/BufferGLImpl.h | 2 +- .../include/BufferViewGLImpl.h | 2 +- .../include/DeviceContextGLImpl.h | 2 +- .../GraphicsEngineOpenGL/include/FenceGLImpl.h | 2 +- .../include/GLPipelineResourceLayout.h | 2 +- .../include/GLProgramResources.h | 2 +- .../include/PipelineStateGLImpl.h | 2 +- .../GraphicsEngineOpenGL/include/QueryGLImpl.h | 2 +- .../include/RenderDeviceGLImpl.h | 2 +- .../GraphicsEngineOpenGL/include/SamplerGLImpl.h | 2 +- .../GraphicsEngineOpenGL/include/ShaderGLImpl.h | 2 +- .../include/ShaderResourceBindingGLImpl.h | 4 +- .../GraphicsEngineOpenGL/include/SwapChainGLBase.h | 2 +- .../GraphicsEngineOpenGL/include/TextureBaseGL.h | 2 +- .../include/TextureViewGLImpl.h | 2 +- Graphics/GraphicsEngineOpenGL/include/VAOCache.h | 2 +- .../src/EngineFactoryOpenGL.cpp | 2 +- .../src/GLPipelineResourceLayout.cpp | 2 +- .../src/GLProgramResources.cpp | 4 +- .../include/BufferViewVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/BufferVkImpl.h | 2 +- .../include/CommandListVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/FenceVkImpl.h | 2 +- .../include/ManagedVulkanObject.h | 2 +- .../GraphicsEngineVulkan/include/PipelineLayout.h | 2 +- .../include/PipelineStateVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/QueryVkImpl.h | 2 +- .../include/RenderDeviceVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/SamplerVkImpl.h | 2 +- .../include/ShaderResourceBindingVkImpl.h | 4 +- .../include/ShaderResourceLayoutVk.h | 2 +- .../include/ShaderVariableVk.h | 2 +- .../GraphicsEngineVulkan/include/ShaderVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/SwapChainVkImpl.h | 2 +- .../include/TextureViewVkImpl.h | 2 +- .../GraphicsEngineVulkan/include/TextureVkImpl.h | 2 +- Graphics/GraphicsEngineVulkan/include/pch.h | 2 +- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 2 +- .../src/ShaderResourceLayoutVk.cpp | 2 +- .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 2 +- .../src/HLSL2GLSLConverterImpl.cpp | 2 +- 259 files changed, 16098 insertions(+), 16098 deletions(-) delete mode 100644 Graphics/GraphicsEngine/include/BufferBase.h create mode 100644 Graphics/GraphicsEngine/include/BufferBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/BufferViewBase.h create mode 100644 Graphics/GraphicsEngine/include/BufferViewBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/CommandListBase.h create mode 100644 Graphics/GraphicsEngine/include/CommandListBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/DeviceContextBase.h create mode 100644 Graphics/GraphicsEngine/include/DeviceContextBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/DeviceObjectBase.h create mode 100644 Graphics/GraphicsEngine/include/DeviceObjectBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/EngineFactoryBase.h create mode 100644 Graphics/GraphicsEngine/include/EngineFactoryBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/FenceBase.h create mode 100644 Graphics/GraphicsEngine/include/FenceBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/PipelineStateBase.h create mode 100644 Graphics/GraphicsEngine/include/PipelineStateBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/QueryBase.h create mode 100644 Graphics/GraphicsEngine/include/QueryBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/RenderDeviceBase.h create mode 100644 Graphics/GraphicsEngine/include/RenderDeviceBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/ResourceMappingImpl.h create mode 100644 Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp delete mode 100644 Graphics/GraphicsEngine/include/SamplerBase.h create mode 100644 Graphics/GraphicsEngine/include/SamplerBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/ShaderBase.h create mode 100644 Graphics/GraphicsEngine/include/ShaderBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/ShaderResourceBindingBase.h create mode 100644 Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h create mode 100644 Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/StateObjectsRegistry.h create mode 100644 Graphics/GraphicsEngine/include/StateObjectsRegistry.hpp delete mode 100644 Graphics/GraphicsEngine/include/SwapChainBase.h create mode 100644 Graphics/GraphicsEngine/include/SwapChainBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/TextureBase.h create mode 100644 Graphics/GraphicsEngine/include/TextureBase.hpp delete mode 100644 Graphics/GraphicsEngine/include/TextureViewBase.h create mode 100644 Graphics/GraphicsEngine/include/TextureViewBase.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/CommandListD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/CommandListD3D11Impl.hpp delete mode 100755 Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.h create mode 100644 Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp delete mode 100755 Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp delete mode 100755 Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h create mode 100644 Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.h create mode 100644 Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/CommandContext.h create mode 100644 Graphics/GraphicsEngineD3D12/include/CommandContext.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/CommandListManager.h create mode 100644 Graphics/GraphicsEngineD3D12/include/CommandListManager.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h create mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12Loader.h create mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12Loader.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h create mode 100644 Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h create mode 100644 Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/GenerateMips.h create mode 100644 Graphics/GraphicsEngineD3D12/include/GenerateMips.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/RootSignature.h create mode 100644 Graphics/GraphicsEngineD3D12/include/RootSignature.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h create mode 100644 Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DErrors.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DErrors.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderResources.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp delete mode 100644 Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.h create mode 100644 Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp (limited to 'Graphics') diff --git a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp index b51c2a00..4d9fc6d5 100644 --- a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp +++ b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp @@ -29,7 +29,7 @@ #include "SPIRVShaderResources.hpp" #include "spirv_parser.hpp" #include "spirv_cross.hpp" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "GraphicsAccessories.hpp" #include "StringTools.h" #include "Align.h" diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index f28c3db1..037af6fa 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -3,29 +3,29 @@ cmake_minimum_required (VERSION 3.6) project(Diligent-GraphicsEngine CXX) set(INCLUDE - include/BufferBase.h - include/BufferViewBase.h - include/CommandListBase.h + include/BufferBase.hpp + include/BufferViewBase.hpp + include/CommandListBase.hpp include/DefaultShaderSourceStreamFactory.h include/Defines.h - include/DeviceContextBase.h - include/DeviceObjectBase.h - include/EngineFactoryBase.h + include/DeviceContextBase.hpp + include/DeviceObjectBase.hpp + include/EngineFactoryBase.hpp include/EngineMemory.h - include/FenceBase.h + include/FenceBase.hpp include/pch.h - include/PipelineStateBase.h - include/QueryBase.h - include/RenderDeviceBase.h - include/ResourceMappingImpl.h - include/SamplerBase.h - include/ShaderBase.h - include/ShaderResourceBindingBase.h - include/ShaderResourceVariableBase.h - include/StateObjectsRegistry.h - include/SwapChainBase.h - include/TextureBase.h - include/TextureViewBase.h + include/PipelineStateBase.hpp + include/QueryBase.hpp + include/RenderDeviceBase.hpp + include/ResourceMappingImpl.hpp + include/SamplerBase.hpp + include/ShaderBase.hpp + include/ShaderResourceBindingBase.hpp + include/ShaderResourceVariableBase.hpp + include/StateObjectsRegistry.hpp + include/SwapChainBase.hpp + include/TextureBase.hpp + include/TextureViewBase.hpp ) set(INTERFACE diff --git a/Graphics/GraphicsEngine/include/BufferBase.h b/Graphics/GraphicsEngine/include/BufferBase.h deleted file mode 100644 index 388625b1..00000000 --- a/Graphics/GraphicsEngine/include/BufferBase.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2019-2020 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::BufferBase template class - -#include "Buffer.h" -#include "GraphicsTypes.h" -#include "DeviceObjectBase.h" -#include "GraphicsAccessories.hpp" -#include "STDAllocator.h" -#include - -namespace Diligent -{ - -/// Template class implementing base functionality for a buffer object - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IBufferD3D11, Diligent::IBufferD3D12, -/// Diligent::IBufferGL or Diligent::IBufferVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -/// \tparam BufferViewImplType - type of the buffer view implementation -/// (Diligent::BufferViewD3D11Impl, Diligent::BufferViewD3D12Impl, -/// Diligent::BufferViewGLImpl or Diligent::BufferViewVkImpl) -/// \tparam TBuffViewObjAllocator - type of the allocator that is used to allocate memory for the buffer view object instances -template -class BufferBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this buffer. - /// \param BuffViewObjAllocator - allocator that is used to allocate memory for the buffer view instances. - /// This parameter is only used for debug purposes. - /// \param pDevice - pointer to the device. - /// \param BuffDesc - buffer description. - /// \param bIsDeviceInternal - flag indicating if the buffer is an internal device object and - /// must not keep a strong reference to the device. - BufferBase(IReferenceCounters* pRefCounters, - TBuffViewObjAllocator& BuffViewObjAllocator, - RenderDeviceImplType* pDevice, - const BufferDesc& BuffDesc, - bool bIsDeviceInternal) : - TDeviceObjectBase{pRefCounters, pDevice, BuffDesc, bIsDeviceInternal}, -#ifdef _DEBUG - m_dbgBuffViewAllocator{BuffViewObjAllocator}, -#endif - m_pDefaultUAV{nullptr, STDDeleter(BuffViewObjAllocator)}, - m_pDefaultSRV{nullptr, STDDeleter(BuffViewObjAllocator)} - { -#define VERIFY_BUFFER(Expr, ...) \ - do \ - { \ - if (!(Expr)) \ - { \ - LOG_ERROR_AND_THROW("Buffer '", this->m_Desc.Name ? this->m_Desc.Name : "", "': ", ##__VA_ARGS__); \ - } \ - } while (false) - - Uint32 AllowedBindFlags = - BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_UNIFORM_BUFFER | - BIND_SHADER_RESOURCE | BIND_STREAM_OUTPUT | BIND_UNORDERED_ACCESS | - BIND_INDIRECT_DRAW_ARGS; - const Char* strAllowedBindFlags = - "BIND_VERTEX_BUFFER (1), BIND_INDEX_BUFFER (2), BIND_UNIFORM_BUFFER (4), " - "BIND_SHADER_RESOURCE (8), BIND_STREAM_OUTPUT (16), BIND_UNORDERED_ACCESS (128), " - "BIND_INDIRECT_DRAW_ARGS (256)"; - - VERIFY_BUFFER((BuffDesc.BindFlags & ~AllowedBindFlags) == 0, "Incorrect bind flags specified (", BuffDesc.BindFlags & ~AllowedBindFlags, "). Only the following flags are allowed:\n", strAllowedBindFlags); - - if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || - (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) - { - VERIFY_BUFFER(this->m_Desc.Mode > BUFFER_MODE_UNDEFINED && this->m_Desc.Mode < BUFFER_MODE_NUM_MODES, GetBufferModeString(this->m_Desc.Mode), " is not a valid mode for a buffer created with BIND_SHADER_RESOURCE or BIND_UNORDERED_ACCESS flags"); - if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) - { - VERIFY_BUFFER(this->m_Desc.ElementByteStride != 0, "Element stride must not be zero for structured and formatted buffers"); - } - else if (this->m_Desc.Mode == BUFFER_MODE_RAW) - { - } - } - -#undef VERIFY_BUFFER - - Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); - DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); - this->m_Desc.CommandQueueMask &= DeviceQueuesMask; - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Buffer, TDeviceObjectBase) - - /// Implementation of IBuffer::CreateView(); calls CreateViewInternal() virtual function - /// that creates buffer view for the specific engine implementation. - virtual void CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override; - - /// Implementation of IBuffer::GetDefaultView(). - virtual IBufferView* GetDefaultView(BUFFER_VIEW_TYPE ViewType) override; - - /// Creates default buffer views. - - /// - /// - Creates default shader resource view addressing the entire buffer if Diligent::BIND_SHADER_RESOURCE flag is set - /// - Creates default unordered access view addressing the entire buffer if Diligent::BIND_UNORDERED_ACCESS flag is set - /// - /// The function calls CreateViewInternal(). - void CreateDefaultViews(); - - virtual void SetState(RESOURCE_STATE State) override final - { - this->m_State = State; - } - - virtual RESOURCE_STATE GetState() const override final - { - return this->m_State; - } - - bool IsInKnownState() const - { - return this->m_State != RESOURCE_STATE_UNKNOWN; - } - - bool CheckState(RESOURCE_STATE State) const - { - VERIFY((State & (State - 1)) == 0, "Single state is expected"); - VERIFY(IsInKnownState(), "Buffer state is unknown"); - return (this->m_State & State) == State; - } - -protected: - /// Pure virtual function that creates buffer view for the specific engine implementation. - virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) = 0; - - /// Corrects buffer view description and validates view parameters. - void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc); - -#ifdef _DEBUG - TBuffViewObjAllocator& m_dbgBuffViewAllocator; -#endif - - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; - - /// Default UAV addressing the entire buffer - std::unique_ptr> m_pDefaultUAV; - - /// Default SRV addressing the entire buffer - std::unique_ptr> m_pDefaultSRV; -}; - - - - -template -void BufferBase::CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) -{ - DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); - if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); - else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); - else - UNEXPECTED("Unexpected buffer view type"); - - CreateViewInternal(ViewDesc, ppView, false); -} - - -template -void BufferBase::CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc) -{ - if (ViewDesc.ByteWidth == 0) - { - DEV_CHECK_ERR(this->m_Desc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", this->m_Desc.uiSizeInBytes, ")"); - ViewDesc.ByteWidth = this->m_Desc.uiSizeInBytes - ViewDesc.ByteOffset; - } - if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > this->m_Desc.uiSizeInBytes) - LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", this->m_Desc.uiSizeInBytes, ")."); - if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || - (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) - { - if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) - { - VERIFY(this->m_Desc.ElementByteStride != 0, "Element byte stride is zero"); - if ((ViewDesc.ByteOffset % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - if ((ViewDesc.ByteWidth % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - } - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) - LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED || (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) - { - if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) - LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); - if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) - ViewDesc.Format.IsNormalized = false; - auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; - if (this->m_Desc.Mode == BUFFER_MODE_RAW && this->m_Desc.ElementByteStride == 0) - LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); - if (ViewElementStride != this->m_Desc.ElementByteStride) - LOG_ERROR_AND_THROW("Buffer element byte stride (", this->m_Desc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); - } - - if (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) - { - if ((ViewDesc.ByteOffset % 16) != 0) - LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); - } - } -} - -template -IBufferView* BufferBase::GetDefaultView(BUFFER_VIEW_TYPE ViewType) -{ - switch (ViewType) - { - case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); - case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); - default: UNEXPECTED("Unknown view type"); return nullptr; - } -} - -template -void BufferBase::CreateDefaultViews() -{ - // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so - // cannot create views. - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; - IBufferView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; - IBufferView* pSRV = nullptr; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp new file mode 100644 index 00000000..a40978f7 --- /dev/null +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -0,0 +1,282 @@ +/* + * Copyright 2019-2020 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::BufferBase template class + +#include "Buffer.h" +#include "GraphicsTypes.h" +#include "DeviceObjectBase.hpp" +#include "GraphicsAccessories.hpp" +#include "STDAllocator.h" +#include + +namespace Diligent +{ + +/// Template class implementing base functionality for a buffer object + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IBufferD3D11, Diligent::IBufferD3D12, +/// Diligent::IBufferGL or Diligent::IBufferVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +/// \tparam BufferViewImplType - type of the buffer view implementation +/// (Diligent::BufferViewD3D11Impl, Diligent::BufferViewD3D12Impl, +/// Diligent::BufferViewGLImpl or Diligent::BufferViewVkImpl) +/// \tparam TBuffViewObjAllocator - type of the allocator that is used to allocate memory for the buffer view object instances +template +class BufferBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this buffer. + /// \param BuffViewObjAllocator - allocator that is used to allocate memory for the buffer view instances. + /// This parameter is only used for debug purposes. + /// \param pDevice - pointer to the device. + /// \param BuffDesc - buffer description. + /// \param bIsDeviceInternal - flag indicating if the buffer is an internal device object and + /// must not keep a strong reference to the device. + BufferBase(IReferenceCounters* pRefCounters, + TBuffViewObjAllocator& BuffViewObjAllocator, + RenderDeviceImplType* pDevice, + const BufferDesc& BuffDesc, + bool bIsDeviceInternal) : + TDeviceObjectBase{pRefCounters, pDevice, BuffDesc, bIsDeviceInternal}, +#ifdef _DEBUG + m_dbgBuffViewAllocator{BuffViewObjAllocator}, +#endif + m_pDefaultUAV{nullptr, STDDeleter(BuffViewObjAllocator)}, + m_pDefaultSRV{nullptr, STDDeleter(BuffViewObjAllocator)} + { +#define VERIFY_BUFFER(Expr, ...) \ + do \ + { \ + if (!(Expr)) \ + { \ + LOG_ERROR_AND_THROW("Buffer '", this->m_Desc.Name ? this->m_Desc.Name : "", "': ", ##__VA_ARGS__); \ + } \ + } while (false) + + Uint32 AllowedBindFlags = + BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_UNIFORM_BUFFER | + BIND_SHADER_RESOURCE | BIND_STREAM_OUTPUT | BIND_UNORDERED_ACCESS | + BIND_INDIRECT_DRAW_ARGS; + const Char* strAllowedBindFlags = + "BIND_VERTEX_BUFFER (1), BIND_INDEX_BUFFER (2), BIND_UNIFORM_BUFFER (4), " + "BIND_SHADER_RESOURCE (8), BIND_STREAM_OUTPUT (16), BIND_UNORDERED_ACCESS (128), " + "BIND_INDIRECT_DRAW_ARGS (256)"; + + VERIFY_BUFFER((BuffDesc.BindFlags & ~AllowedBindFlags) == 0, "Incorrect bind flags specified (", BuffDesc.BindFlags & ~AllowedBindFlags, "). Only the following flags are allowed:\n", strAllowedBindFlags); + + if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || + (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) + { + VERIFY_BUFFER(this->m_Desc.Mode > BUFFER_MODE_UNDEFINED && this->m_Desc.Mode < BUFFER_MODE_NUM_MODES, GetBufferModeString(this->m_Desc.Mode), " is not a valid mode for a buffer created with BIND_SHADER_RESOURCE or BIND_UNORDERED_ACCESS flags"); + if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) + { + VERIFY_BUFFER(this->m_Desc.ElementByteStride != 0, "Element stride must not be zero for structured and formatted buffers"); + } + else if (this->m_Desc.Mode == BUFFER_MODE_RAW) + { + } + } + +#undef VERIFY_BUFFER + + Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); + DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); + this->m_Desc.CommandQueueMask &= DeviceQueuesMask; + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Buffer, TDeviceObjectBase) + + /// Implementation of IBuffer::CreateView(); calls CreateViewInternal() virtual function + /// that creates buffer view for the specific engine implementation. + virtual void CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override; + + /// Implementation of IBuffer::GetDefaultView(). + virtual IBufferView* GetDefaultView(BUFFER_VIEW_TYPE ViewType) override; + + /// Creates default buffer views. + + /// + /// - Creates default shader resource view addressing the entire buffer if Diligent::BIND_SHADER_RESOURCE flag is set + /// - Creates default unordered access view addressing the entire buffer if Diligent::BIND_UNORDERED_ACCESS flag is set + /// + /// The function calls CreateViewInternal(). + void CreateDefaultViews(); + + virtual void SetState(RESOURCE_STATE State) override final + { + this->m_State = State; + } + + virtual RESOURCE_STATE GetState() const override final + { + return this->m_State; + } + + bool IsInKnownState() const + { + return this->m_State != RESOURCE_STATE_UNKNOWN; + } + + bool CheckState(RESOURCE_STATE State) const + { + VERIFY((State & (State - 1)) == 0, "Single state is expected"); + VERIFY(IsInKnownState(), "Buffer state is unknown"); + return (this->m_State & State) == State; + } + +protected: + /// Pure virtual function that creates buffer view for the specific engine implementation. + virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) = 0; + + /// Corrects buffer view description and validates view parameters. + void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc); + +#ifdef _DEBUG + TBuffViewObjAllocator& m_dbgBuffViewAllocator; +#endif + + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + + /// Default UAV addressing the entire buffer + std::unique_ptr> m_pDefaultUAV; + + /// Default SRV addressing the entire buffer + std::unique_ptr> m_pDefaultSRV; +}; + + + + +template +void BufferBase::CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) +{ + DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); + if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); + else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); + else + UNEXPECTED("Unexpected buffer view type"); + + CreateViewInternal(ViewDesc, ppView, false); +} + + +template +void BufferBase::CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc) +{ + if (ViewDesc.ByteWidth == 0) + { + DEV_CHECK_ERR(this->m_Desc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", this->m_Desc.uiSizeInBytes, ")"); + ViewDesc.ByteWidth = this->m_Desc.uiSizeInBytes - ViewDesc.ByteOffset; + } + if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > this->m_Desc.uiSizeInBytes) + LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", this->m_Desc.uiSizeInBytes, ")."); + if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || + (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) + { + if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) + { + VERIFY(this->m_Desc.ElementByteStride != 0, "Element byte stride is zero"); + if ((ViewDesc.ByteOffset % this->m_Desc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); + if ((ViewDesc.ByteWidth % this->m_Desc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); + } + + if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) + LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); + + if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED || (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) + { + if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) + LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); + if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) + ViewDesc.Format.IsNormalized = false; + auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; + if (this->m_Desc.Mode == BUFFER_MODE_RAW && this->m_Desc.ElementByteStride == 0) + LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); + if (ViewElementStride != this->m_Desc.ElementByteStride) + LOG_ERROR_AND_THROW("Buffer element byte stride (", this->m_Desc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); + } + + if (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) + { + if ((ViewDesc.ByteOffset % 16) != 0) + LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); + } + } +} + +template +IBufferView* BufferBase::GetDefaultView(BUFFER_VIEW_TYPE ViewType) +{ + switch (ViewType) + { + case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); + case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); + default: UNEXPECTED("Unknown view type"); return nullptr; + } +} + +template +void BufferBase::CreateDefaultViews() +{ + // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so + // cannot create views. + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; + IBufferView* pUAV = nullptr; + CreateViewInternal(ViewDesc, &pUAV, true); + m_pDefaultUAV.reset(static_cast(pUAV)); + VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; + IBufferView* pSRV = nullptr; + CreateViewInternal(ViewDesc, &pSRV, true); + m_pDefaultSRV.reset(static_cast(pSRV)); + VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/BufferViewBase.h b/Graphics/GraphicsEngine/include/BufferViewBase.h deleted file mode 100644 index 59e9a14a..00000000 --- a/Graphics/GraphicsEngine/include/BufferViewBase.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2019-2020 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::BufferViewBase template class - -#include "BufferView.h" -#include "DeviceObjectBase.h" -#include "GraphicsTypes.h" -#include "RefCntAutoPtr.h" - -namespace Diligent -{ - -class IRenderDevice; -class IBuffer; - -/// Template class implementing base functionality for a buffer view object - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IBufferViewD3D11, Diligent::IBufferViewD3D12, -/// Diligent::IBufferViewGL or Diligent::IBufferViewVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class BufferViewBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this buffer view. - /// \param pDevice - pointer to the render device. - /// \param ViewDesc - buffer view description. - /// \param pBuffer - pointer to the buffer that the view is to be created for. - /// \param bIsDefaultView - flag indicating if the view is default view, and is thus - /// part of the buffer object. In this case the view will attach - /// to the buffer's reference counters. - BufferViewBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const BufferViewDesc& ViewDesc, - IBuffer* pBuffer, - bool bIsDefaultView) : - // Default views are created as part of the buffer, so we cannot not keep strong - // reference to the buffer to avoid cyclic links. Instead, we will attach to the - // reference counters of the buffer. - TDeviceObjectBase(pRefCounters, pDevice, ViewDesc), - m_pBuffer{pBuffer}, - // For non-default view, we will keep strong reference to buffer - m_spBuffer{bIsDefaultView ? nullptr : pBuffer} - {} - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BufferView, TDeviceObjectBase) - - /// Implementation of IBufferView::GetBuffer() - virtual IBuffer* GetBuffer() override final - { - return m_pBuffer; - } - - template - BufferType* GetBuffer() - { - return ValidatedCast(m_pBuffer); - } - - template - BufferType* GetBuffer() const - { - return ValidatedCast(m_pBuffer); - } - -protected: - /// Pointer to the buffer - IBuffer* const m_pBuffer; - - /// Strong reference to the buffer. Used for non-default views - /// to keep the buffer alive - RefCntAutoPtr m_spBuffer; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/BufferViewBase.hpp b/Graphics/GraphicsEngine/include/BufferViewBase.hpp new file mode 100644 index 00000000..37e80756 --- /dev/null +++ b/Graphics/GraphicsEngine/include/BufferViewBase.hpp @@ -0,0 +1,108 @@ +/* + * Copyright 2019-2020 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::BufferViewBase template class + +#include "BufferView.h" +#include "DeviceObjectBase.hpp" +#include "GraphicsTypes.h" +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + +class IRenderDevice; +class IBuffer; + +/// Template class implementing base functionality for a buffer view object + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IBufferViewD3D11, Diligent::IBufferViewD3D12, +/// Diligent::IBufferViewGL or Diligent::IBufferViewVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class BufferViewBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this buffer view. + /// \param pDevice - pointer to the render device. + /// \param ViewDesc - buffer view description. + /// \param pBuffer - pointer to the buffer that the view is to be created for. + /// \param bIsDefaultView - flag indicating if the view is default view, and is thus + /// part of the buffer object. In this case the view will attach + /// to the buffer's reference counters. + BufferViewBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const BufferViewDesc& ViewDesc, + IBuffer* pBuffer, + bool bIsDefaultView) : + // Default views are created as part of the buffer, so we cannot not keep strong + // reference to the buffer to avoid cyclic links. Instead, we will attach to the + // reference counters of the buffer. + TDeviceObjectBase(pRefCounters, pDevice, ViewDesc), + m_pBuffer{pBuffer}, + // For non-default view, we will keep strong reference to buffer + m_spBuffer{bIsDefaultView ? nullptr : pBuffer} + {} + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BufferView, TDeviceObjectBase) + + /// Implementation of IBufferView::GetBuffer() + virtual IBuffer* GetBuffer() override final + { + return m_pBuffer; + } + + template + BufferType* GetBuffer() + { + return ValidatedCast(m_pBuffer); + } + + template + BufferType* GetBuffer() const + { + return ValidatedCast(m_pBuffer); + } + +protected: + /// Pointer to the buffer + IBuffer* const m_pBuffer; + + /// Strong reference to the buffer. Used for non-default views + /// to keep the buffer alive + RefCntAutoPtr m_spBuffer; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/CommandListBase.h b/Graphics/GraphicsEngine/include/CommandListBase.h deleted file mode 100644 index 2fda804b..00000000 --- a/Graphics/GraphicsEngine/include/CommandListBase.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019-2020 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::CommandListBase template class - -#include "CommandList.h" -#include "DeviceObjectBase.h" -#include "RenderDeviceBase.h" - -namespace Diligent -{ - -struct CommandListDesc : public DeviceObjectAttribs -{ -}; - -/// Template class implementing base functionality for a command list object. - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ICommandListD3D11, Diligent::ICommandListD3D12 or Diligent::ICommandListVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class CommandListBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this command list. - /// \param pDevice - pointer to the device. - /// \param bIsDeviceInternal - flag indicating if the CommandList is an internal device object and - /// must not keep a strong reference to the device. - CommandListBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, CommandListDesc(), bIsDeviceInternal} - {} - - ~CommandListBase() - { - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_CommandList, TDeviceObjectBase) -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/CommandListBase.hpp b/Graphics/GraphicsEngine/include/CommandListBase.hpp new file mode 100644 index 00000000..051eb737 --- /dev/null +++ b/Graphics/GraphicsEngine/include/CommandListBase.hpp @@ -0,0 +1,72 @@ +/* + * Copyright 2019-2020 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::CommandListBase template class + +#include "CommandList.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" + +namespace Diligent +{ + +struct CommandListDesc : public DeviceObjectAttribs +{ +}; + +/// Template class implementing base functionality for a command list object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ICommandListD3D11, Diligent::ICommandListD3D12 or Diligent::ICommandListVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class CommandListBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this command list. + /// \param pDevice - pointer to the device. + /// \param bIsDeviceInternal - flag indicating if the CommandList is an internal device object and + /// must not keep a strong reference to the device. + CommandListBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, CommandListDesc(), bIsDeviceInternal} + {} + + ~CommandListBase() + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_CommandList, TDeviceObjectBase) +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.h b/Graphics/GraphicsEngine/include/DeviceContextBase.h deleted file mode 100644 index c6ed1793..00000000 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.h +++ /dev/null @@ -1,1518 +0,0 @@ -/* - * Copyright 2019-2020 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::DeviceContextBase template class and related structures - -#include - -#include "DeviceContext.h" -#include "DeviceObjectBase.h" -#include "ResourceMapping.h" -#include "Sampler.h" -#include "ObjectBase.h" -#include "DebugUtilities.h" -#include "ValidatedCast.h" -#include "GraphicsAccessories.hpp" -#include "TextureBase.h" - -namespace Diligent -{ - -/// Describes input vertex stream -template -struct VertexStreamInfo -{ - VertexStreamInfo() {} - - /// Strong reference to the buffer object - RefCntAutoPtr pBuffer; - Uint32 Offset = 0; ///< Offset in bytes -}; - -/// Base implementation of the device context. - -/// \tparam BaseInterface - base interface that this class will inheret. -/// \tparam ImplementationTraits - implementation traits that define specific implementation details -/// (texture implemenation type, buffer implementation type, etc.) -/// \remarks Device context keeps strong references to all objects currently bound to -/// the pipeline: buffers, states, samplers, shaders, etc. -/// The context also keeps strong references to the device and -/// the swap chain. -template -class DeviceContextBase : public ObjectBase -{ -public: - using TObjectBase = ObjectBase; - using DeviceImplType = typename ImplementationTraits::DeviceType; - using BufferImplType = typename ImplementationTraits::BufferType; - using TextureImplType = typename ImplementationTraits::TextureType; - using PipelineStateImplType = typename ImplementationTraits::PipelineStateType; - using TextureViewImplType = typename TextureImplType::ViewImplType; - using QueryImplType = typename ImplementationTraits::QueryType; - - /// \param pRefCounters - reference counters object that controls the lifetime of this device context. - /// \param pRenderDevice - render device. - /// \param bIsDeferred - flag indicating if this instance is a deferred context - DeviceContextBase(IReferenceCounters* pRefCounters, DeviceImplType* pRenderDevice, bool bIsDeferred) : - // clang-format off - TObjectBase {pRefCounters }, - m_pDevice {pRenderDevice}, - m_bIsDeferred{bIsDeferred } - // clang-format on - { - } - - ~DeviceContextBase() - { - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceContext, TObjectBase) - - /// Base implementation of IDeviceContext::SetVertexBuffers(); validates parameters and - /// caches references to the buffers. - inline virtual void SetVertexBuffers(Uint32 StartSlot, - Uint32 NumBuffersSet, - IBuffer** ppBuffers, - Uint32* pOffsets, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - SET_VERTEX_BUFFERS_FLAGS Flags) override = 0; - - inline virtual void InvalidateState() override = 0; - - /// Base implementation of IDeviceContext::CommitShaderResources(); validates parameters. - inline bool CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - int); - - /// Base implementation of IDeviceContext::SetIndexBuffer(); caches the strong reference to the index buffer - inline virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; - - /// Caches the viewports - inline void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight); - - /// Caches the scissor rects - inline void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight); - - /// Caches the render target and depth stencil views. Returns true if any view is different - /// from the cached value and false otherwise. - inline bool SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil); - - /// Base implementation of IDeviceContext::UpdateBuffer(); validates input parameters. - virtual void UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; - - /// Base implementation of IDeviceContext::CopyBuffer(); validates input parameters. - virtual void CopyBuffer(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - IBuffer* pDstBuffer, - Uint32 DstOffset, - Uint32 Size, - RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override = 0; - - /// Base implementation of IDeviceContext::MapBuffer(); validates input parameters. - virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override = 0; - - /// Base implementation of IDeviceContext::UnmapBuffer() - virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override = 0; - - /// Base implementaiton of IDeviceContext::UpdateData(); validates input parameters - virtual void UpdateTexture(ITexture* pTexture, - Uint32 MipLevel, - Uint32 Slice, - const Box& DstBox, - const TextureSubResData& SubresData, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) override = 0; - - /// Base implementaiton of IDeviceContext::CopyTexture(); validates input parameters - virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override = 0; - - /// Base implementaiton of IDeviceContext::MapTextureSubresource() - virtual void MapTextureSubresource(ITexture* pTexture, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - MAP_FLAGS MapFlags, - const Box* pMapRegion, - MappedTextureSubresource& MappedData) override = 0; - - /// Base implementaiton of IDeviceContext::UnmapTextureSubresource() - virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override = 0; - - virtual void GenerateMips(ITextureView* pTexView) override = 0; - - virtual void ResolveTextureSubresource(ITexture* pSrcTexture, - ITexture* pDstTexture, - const ResolveTextureSubresourceAttribs& ResolveAttribs) override = 0; - - /// Returns currently bound pipeline state and blend factors - inline void GetPipelineState(IPipelineState** ppPSO, float* BlendFactors, Uint32& StencilRef); - - /// Returns currently bound render targets - inline void GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV); - - /// Returns currently set viewports - inline void GetViewports(Uint32& NumViewports, Viewport* pViewports); - - /// Returns the render device - IRenderDevice* GetDevice() { return m_pDevice; } - - virtual void ResetRenderTargets(); - - bool IsDeferred() const { return m_bIsDeferred; } - - /// Checks if a texture is bound as a render target or depth-stencil buffer and - /// resets render targets if it is. - bool UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage); - -protected: - inline bool SetBlendFactors(const float* BlendFactors, int Dummy); - - inline bool SetStencilRef(Uint32 StencilRef, int Dummy); - - inline void SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/); - - /// Clears all cached resources - inline void ClearStateCache(); - - /// Checks if the texture is currently bound as a render target. - bool CheckIfBoundAsRenderTarget(TextureImplType* pTexture); - - /// Checks if the texture is currently bound as depth-stencil buffer. - bool CheckIfBoundAsDepthStencil(TextureImplType* pTexture); - - bool ClearDepthStencil(ITextureView* pView); - - bool ClearRenderTarget(ITextureView* pView); - - bool BeginQuery(IQuery* pQuery, int); - - bool EndQuery(IQuery* pQuery, int); - -#ifdef DEVELOPMENT - // clang-format off - bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const; - bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const; - bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - - bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const; - bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - - void DvpVerifyRenderTargets()const; - void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const; - bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const; - bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const; -#else - bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;} - bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;} - bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} - bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} - - bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;} - bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} - - void DvpVerifyRenderTargets()const {} - void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {} - bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} - bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} - // clang-format on -#endif - - /// Strong reference to the device. - RefCntAutoPtr m_pDevice; - - /// Vertex streams. Every stream holds strong reference to the buffer - VertexStreamInfo m_VertexStreams[MAX_BUFFER_SLOTS]; - - /// Number of bound vertex streams - Uint32 m_NumVertexStreams = 0; - - /// Strong reference to the bound pipeline state object. - /// Use final PSO implementation type to avoid virtual calls to AddRef()/Release(). - /// We need to keep strong reference as we examine previous pipeline state in - /// SetPipelineState() - RefCntAutoPtr m_pPipelineState; - - /// Strong reference to the bound index buffer. - /// Use final buffer implementation type to avoid virtual calls to AddRef()/Release() - RefCntAutoPtr m_pIndexBuffer; - - /// Offset from the beginning of the index buffer to the start of the index data, in bytes. - Uint32 m_IndexDataStartOffset = 0; - - /// Current stencil reference value - Uint32 m_StencilRef = 0; - - /// Curent blend factors - Float32 m_BlendFactors[4] = {-1, -1, -1, -1}; - - /// Current viewports - Viewport m_Viewports[MAX_VIEWPORTS]; - /// Number of current viewports - Uint32 m_NumViewports = 0; - - /// Current scissor rects - Rect m_ScissorRects[MAX_VIEWPORTS]; - /// Number of current scissor rects - Uint32 m_NumScissorRects = 0; - - /// Vector of strong references to the bound render targets. - /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() - RefCntAutoPtr m_pBoundRenderTargets[MAX_RENDER_TARGETS]; - /// Number of bound render targets - Uint32 m_NumBoundRenderTargets = 0; - /// Width of the currently bound framebuffer - Uint32 m_FramebufferWidth = 0; - /// Height of the currently bound framebuffer - Uint32 m_FramebufferHeight = 0; - /// Number of array slices in the currently bound framebuffer - Uint32 m_FramebufferSlices = 0; - - /// Strong references to the bound depth stencil view. - /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() - RefCntAutoPtr m_pBoundDepthStencil; - - const bool m_bIsDeferred = false; - -#ifdef _DEBUG - // std::unordered_map is unbelievably slow. Keeping track of mapped buffers - // in release builds is not feasible - struct DbgMappedBufferInfo - { - MAP_TYPE MapType; - }; - std::unordered_map m_DbgMappedBuffers; -#endif -}; - - -template -inline void DeviceContextBase:: - SetVertexBuffers(Uint32 StartSlot, - Uint32 NumBuffersSet, - IBuffer** ppBuffers, - Uint32* pOffsets, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - SET_VERTEX_BUFFERS_FLAGS Flags) -{ -#ifdef DEVELOPMENT - if (StartSlot >= MAX_BUFFER_SLOTS) - { - LOG_ERROR_MESSAGE("Start vertex buffer slot ", StartSlot, " is out of allowed range [0, ", MAX_BUFFER_SLOTS - 1, "]."); - return; - } - - if (StartSlot + NumBuffersSet > MAX_BUFFER_SLOTS) - { - LOG_ERROR_MESSAGE("The range of vertex buffer slots being set [", StartSlot, ", ", StartSlot + NumBuffersSet - 1, "] is out of allowed range [0, ", MAX_BUFFER_SLOTS - 1, "]."); - NumBuffersSet = MAX_BUFFER_SLOTS - StartSlot; - } -#endif - - if (Flags & SET_VERTEX_BUFFERS_FLAG_RESET) - { - // Reset only these buffer slots that are not being set. - // It is very important to not reset buffers that stay unchanged - // as AddRef()/Release() are not free - for (Uint32 s = 0; s < StartSlot; ++s) - m_VertexStreams[s] = VertexStreamInfo{}; - for (Uint32 s = StartSlot + NumBuffersSet; s < m_NumVertexStreams; ++s) - m_VertexStreams[s] = VertexStreamInfo{}; - m_NumVertexStreams = 0; - } - m_NumVertexStreams = std::max(m_NumVertexStreams, StartSlot + NumBuffersSet); - - for (Uint32 Buff = 0; Buff < NumBuffersSet; ++Buff) - { - auto& CurrStream = m_VertexStreams[StartSlot + Buff]; - CurrStream.pBuffer = ppBuffers ? ValidatedCast(ppBuffers[Buff]) : nullptr; - CurrStream.Offset = pOffsets ? pOffsets[Buff] : 0; -#ifdef DEVELOPMENT - if (CurrStream.pBuffer) - { - const auto& BuffDesc = CurrStream.pBuffer->GetDesc(); - if (!(BuffDesc.BindFlags & BIND_VERTEX_BUFFER)) - { - LOG_ERROR_MESSAGE("Buffer '", BuffDesc.Name ? BuffDesc.Name : "", "' being bound as vertex buffer to slot ", Buff, " was not created with BIND_VERTEX_BUFFER flag"); - } - } -#endif - } - // Remove null buffers from the end of the array - while (m_NumVertexStreams > 0 && !m_VertexStreams[m_NumVertexStreams - 1].pBuffer) - m_VertexStreams[m_NumVertexStreams--] = VertexStreamInfo{}; -} - -template -inline void DeviceContextBase:: - SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/) -{ - m_pPipelineState = pPipelineState; -} - -template -inline bool DeviceContextBase:: - CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int) -{ -#ifdef DEVELOPMENT - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("No pipeline state is bound to the pipeline"); - return false; - } - - if (pShaderResourceBinding) - { - if (m_pPipelineState->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState())) - { - LOG_ERROR_MESSAGE("Shader resource binding object is not compatible with the currently bound pipeline state '", m_pPipelineState->GetDesc().Name, '\''); - return false; - } - } -#endif - return true; -} - -template -inline void DeviceContextBase::InvalidateState() -{ - DeviceContextBase::ClearStateCache(); -} - -template -inline void DeviceContextBase:: - SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) -{ - m_pIndexBuffer = ValidatedCast(pIndexBuffer); - m_IndexDataStartOffset = ByteOffset; -#ifdef DEVELOPMENT - if (m_pIndexBuffer) - { - const auto& BuffDesc = m_pIndexBuffer->GetDesc(); - if (!(BuffDesc.BindFlags & BIND_INDEX_BUFFER)) - { - LOG_ERROR_MESSAGE("Buffer '", BuffDesc.Name ? BuffDesc.Name : "", "' being bound as index buffer was not created with BIND_INDEX_BUFFER flag"); - } - } -#endif -} - - -template -inline void DeviceContextBase::GetPipelineState(IPipelineState** ppPSO, float* BlendFactors, Uint32& StencilRef) -{ - VERIFY(ppPSO != nullptr, "Null pointer provided null"); - VERIFY(*ppPSO == nullptr, "Memory address contains a pointer to a non-null blend state"); - if (m_pPipelineState) - { - m_pPipelineState->QueryInterface(IID_PipelineState, reinterpret_cast(ppPSO)); - } - else - { - *ppPSO = nullptr; - } - - for (Uint32 f = 0; f < 4; ++f) - BlendFactors[f] = m_BlendFactors[f]; - StencilRef = m_StencilRef; -}; - -template -inline bool DeviceContextBase::SetBlendFactors(const float* BlendFactors, int) -{ - bool FactorsDiffer = false; - for (Uint32 f = 0; f < 4; ++f) - { - if (m_BlendFactors[f] != BlendFactors[f]) - FactorsDiffer = true; - m_BlendFactors[f] = BlendFactors[f]; - } - return FactorsDiffer; -} - -template -inline bool DeviceContextBase::SetStencilRef(Uint32 StencilRef, int) -{ - if (m_StencilRef != StencilRef) - { - m_StencilRef = StencilRef; - return true; - } - return false; -} - -template -inline void DeviceContextBase:: - SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight) -{ - if (RTWidth == 0 || RTHeight == 0) - { - RTWidth = m_FramebufferWidth; - RTHeight = m_FramebufferHeight; - } - - VERIFY(NumViewports < MAX_VIEWPORTS, "Number of viewports (", NumViewports, ") exceeds the limit (", MAX_VIEWPORTS, ")"); - m_NumViewports = std::min(MAX_VIEWPORTS, NumViewports); - - Viewport DefaultVP(0, 0, static_cast(RTWidth), static_cast(RTHeight)); - // If no viewports are specified, use default viewport - if (m_NumViewports == 1 && pViewports == nullptr) - { - pViewports = &DefaultVP; - } - - for (Uint32 vp = 0; vp < m_NumViewports; ++vp) - { - m_Viewports[vp] = pViewports[vp]; - VERIFY(m_Viewports[vp].Width >= 0, "Incorrect viewport width (", m_Viewports[vp].Width, ")"); - VERIFY(m_Viewports[vp].Height >= 0, "Incorrect viewport height (", m_Viewports[vp].Height, ")"); - VERIFY(m_Viewports[vp].MaxDepth >= m_Viewports[vp].MinDepth, "Incorrect viewport depth range [", m_Viewports[vp].MinDepth, ", ", m_Viewports[vp].MaxDepth, "]"); - } -} - -template -inline void DeviceContextBase::GetViewports(Uint32& NumViewports, Viewport* pViewports) -{ - NumViewports = m_NumViewports; - if (pViewports) - { - for (Uint32 vp = 0; vp < m_NumViewports; ++vp) - pViewports[vp] = m_Viewports[vp]; - } -} - -template -inline void DeviceContextBase:: - SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight) -{ - if (RTWidth == 0 || RTHeight == 0) - { - RTWidth = m_FramebufferWidth; - RTHeight = m_FramebufferHeight; - } - - VERIFY(NumRects < MAX_VIEWPORTS, "Number of scissor rects (", NumRects, ") exceeds the limit (", MAX_VIEWPORTS, ")"); - m_NumScissorRects = std::min(MAX_VIEWPORTS, NumRects); - - for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr) - { - m_ScissorRects[sr] = pRects[sr]; - VERIFY(m_ScissorRects[sr].left <= m_ScissorRects[sr].right, "Incorrect horizontal bounds for a scissor rect [", m_ScissorRects[sr].left, ", ", m_ScissorRects[sr].right, ")"); - VERIFY(m_ScissorRects[sr].top <= m_ScissorRects[sr].bottom, "Incorrect vertical bounds for a scissor rect [", m_ScissorRects[sr].top, ", ", m_ScissorRects[sr].bottom, ")"); - } -} - -template -inline bool DeviceContextBase:: - SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil) -{ - if (NumRenderTargets == 0 && pDepthStencil == nullptr) - { - ResetRenderTargets(); - return false; - } - - bool bBindRenderTargets = false; - m_FramebufferWidth = 0; - m_FramebufferHeight = 0; - m_FramebufferSlices = 0; - - if (NumRenderTargets != m_NumBoundRenderTargets) - { - bBindRenderTargets = true; - for (Uint32 rt = NumRenderTargets; rt < m_NumBoundRenderTargets; ++rt) - m_pBoundRenderTargets[rt].Release(); - - m_NumBoundRenderTargets = NumRenderTargets; - } - - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) - { - auto* pRTView = ppRenderTargets[rt]; - if (pRTView) - { - const auto& RTVDesc = pRTView->GetDesc(); -#ifdef DEVELOPMENT - if (RTVDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET) - LOG_ERROR("Texture view object named '", RTVDesc.Name ? RTVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(RTVDesc.ViewType), "). Render target view is expected"); -#endif - // Use this RTV to set the render target size - if (m_FramebufferWidth == 0) - { - auto* pTex = pRTView->GetTexture(); - const auto& TexDesc = pTex->GetDesc(); - m_FramebufferWidth = std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U); - m_FramebufferHeight = std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U); - m_FramebufferSlices = RTVDesc.NumArraySlices; - } - else - { -#ifdef DEVELOPMENT - const auto& TexDesc = pRTView->GetTexture()->GetDesc(); - if (m_FramebufferWidth != std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Render target width (", std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); - if (m_FramebufferHeight != std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Render target height (", std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); - if (m_FramebufferSlices != RTVDesc.NumArraySlices) - LOG_ERROR("Number of slices (", RTVDesc.NumArraySlices, ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); -#endif - } - } - - // Here both views are certainly live objects, since we store - // strong references to all bound render targets. So we - // can safely compare pointers. - if (m_pBoundRenderTargets[rt] != pRTView) - { - m_pBoundRenderTargets[rt] = ValidatedCast(pRTView); - bBindRenderTargets = true; - } - } - - if (pDepthStencil != nullptr) - { - const auto& DSVDesc = pDepthStencil->GetDesc(); -#ifdef DEVELOPMENT - if (DSVDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL) - LOG_ERROR("Texture view object named '", DSVDesc.Name ? DSVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(DSVDesc.ViewType), "). Depth stencil view is expected"); -#endif - - // Use depth stencil size to set render target size - if (m_FramebufferWidth == 0) - { - auto* pTex = pDepthStencil->GetTexture(); - const auto& TexDesc = pTex->GetDesc(); - m_FramebufferWidth = std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U); - m_FramebufferHeight = std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U); - m_FramebufferSlices = DSVDesc.NumArraySlices; - } - else - { -#ifdef DEVELOPMENT - const auto& TexDesc = pDepthStencil->GetTexture()->GetDesc(); - if (m_FramebufferWidth != std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Depth-stencil target width (", std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); - if (m_FramebufferHeight != std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Depth-stencil target height (", std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); - if (m_FramebufferSlices != DSVDesc.NumArraySlices) - LOG_ERROR("Number of slices (", DSVDesc.NumArraySlices, ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); -#endif - } - } - - if (m_pBoundDepthStencil != pDepthStencil) - { - m_pBoundDepthStencil = ValidatedCast(pDepthStencil); - bBindRenderTargets = true; - } - - - VERIFY_EXPR(m_FramebufferWidth > 0 && m_FramebufferHeight > 0 && m_FramebufferSlices > 0); - - return bBindRenderTargets; -} - -template -inline void DeviceContextBase:: - GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV) -{ - NumRenderTargets = m_NumBoundRenderTargets; - - if (ppRTVs) - { - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) - { - VERIFY(ppRTVs[rt] == nullptr, "Non-null pointer found in RTV array element #", rt); - auto pBoundRTV = m_pBoundRenderTargets[rt]; - if (pBoundRTV) - pBoundRTV->QueryInterface(IID_TextureView, reinterpret_cast(ppRTVs + rt)); - else - ppRTVs[rt] = nullptr; - } - for (Uint32 rt = NumRenderTargets; rt < MAX_RENDER_TARGETS; ++rt) - { - VERIFY(ppRTVs[rt] == nullptr, "Non-null pointer found in RTV array element #", rt); - ppRTVs[rt] = nullptr; - } - } - - if (ppDSV) - { - VERIFY(*ppDSV == nullptr, "Non-null DSV pointer found"); - if (m_pBoundDepthStencil) - m_pBoundDepthStencil->QueryInterface(IID_TextureView, reinterpret_cast(ppDSV)); - else - *ppDSV = nullptr; - } -} - -template -inline void DeviceContextBase::ClearStateCache() -{ - for (Uint32 stream = 0; stream < m_NumVertexStreams; ++stream) - m_VertexStreams[stream] = VertexStreamInfo{}; -#ifdef _DEBUG - for (Uint32 stream = m_NumVertexStreams; stream < _countof(m_VertexStreams); ++stream) - { - VERIFY(m_VertexStreams[stream].pBuffer == nullptr, "Unexpected non-null buffer"); - VERIFY(m_VertexStreams[stream].Offset == 0, "Unexpected non-zero offset"); - } -#endif - m_NumVertexStreams = 0; - - m_pPipelineState.Release(); - - m_pIndexBuffer.Release(); - m_IndexDataStartOffset = 0; - - m_StencilRef = 0; - - for (int i = 0; i < 4; ++i) - m_BlendFactors[i] = -1; - - for (Uint32 vp = 0; vp < m_NumViewports; ++vp) - m_Viewports[vp] = Viewport(); - m_NumViewports = 0; - - for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr) - m_ScissorRects[sr] = Rect(); - m_NumScissorRects = 0; - - ResetRenderTargets(); -} - -template -bool DeviceContextBase::CheckIfBoundAsRenderTarget(TextureImplType* pTexture) -{ - if (pTexture == nullptr) - return false; - - for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) - { - if (m_pBoundRenderTargets[rt] && m_pBoundRenderTargets[rt]->GetTexture() == pTexture) - { - return true; - } - } - - return false; -} - -template -bool DeviceContextBase::CheckIfBoundAsDepthStencil(TextureImplType* pTexture) -{ - if (pTexture == nullptr) - return false; - - return m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture() == pTexture; -} - -template -bool DeviceContextBase::UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage) -{ - if (pTexture == nullptr) - return false; - - const auto& TexDesc = pTexture->GetDesc(); - - bool bResetRenderTargets = false; - if (TexDesc.BindFlags & BIND_RENDER_TARGET) - { - if (CheckIfBoundAsRenderTarget(pTexture)) - { - if (bShowMessage) - { - LOG_INFO_MESSAGE("Texture '", TexDesc.Name, - "' is currently bound as render target and will be unset along with all " - "other render targets and depth-stencil buffer. " - "Call SetRenderTargets() to reset the render targets.\n" - "To silence this message, explicitly unbind the texture with " - "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); - } - - bResetRenderTargets = true; - } - } - - if (TexDesc.BindFlags & BIND_DEPTH_STENCIL) - { - if (CheckIfBoundAsDepthStencil(pTexture)) - { - if (bShowMessage) - { - LOG_INFO_MESSAGE("Texture '", TexDesc.Name, - "' is currently bound as depth buffer and will be unset along with " - "all render targets. Call SetRenderTargets() to reset the render targets.\n" - "To silence this message, explicitly unbind the texture with " - "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); - } - - bResetRenderTargets = true; - } - } - - if (bResetRenderTargets) - { - ResetRenderTargets(); - } - - return bResetRenderTargets; -} - -template -void DeviceContextBase::ResetRenderTargets() -{ - for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) - m_pBoundRenderTargets[rt].Release(); -#ifdef _DEBUG - for (Uint32 rt = m_NumBoundRenderTargets; rt < _countof(m_pBoundRenderTargets); ++rt) - { - VERIFY(m_pBoundRenderTargets[rt] == nullptr, "Non-null render target found"); - } -#endif - m_NumBoundRenderTargets = 0; - m_FramebufferWidth = 0; - m_FramebufferHeight = 0; - m_FramebufferSlices = 0; - - m_pBoundDepthStencil.Release(); -} - - -template -inline bool DeviceContextBase::ClearDepthStencil(ITextureView* pView) -{ - if (pView == nullptr) - { - LOG_ERROR_MESSAGE("Depth-stencil view to clear must not be null"); - return false; - } - -#ifdef DEVELOPMENT - { - const auto& ViewDesc = pView->GetDesc(); - if (ViewDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL) - { - LOG_ERROR_MESSAGE("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of the texture view '", ViewDesc.Name, - "' is invalid: ClearDepthStencil command expects depth-stencil view (TEXTURE_VIEW_DEPTH_STENCIL)."); - return false; - } - - if (pView != m_pBoundDepthStencil) - { - if (m_pDevice->GetDeviceCaps().IsGLDevice()) - { - LOG_ERROR_MESSAGE("Depth-stencil view '", ViewDesc.Name, - "' is not bound to the device context. ClearDepthStencil command requires " - "depth-stencil view be bound to the device contex in OpenGL backend"); - return false; - } - else - { - LOG_WARNING_MESSAGE("Depth-stencil view '", ViewDesc.Name, - "' is not bound to the device context. " - "ClearDepthStencil command is more efficient when depth-stencil " - "view is bound to the context. In OpenGL backend this is a requirement."); - } - } - } -#endif - - return true; -} - -template -inline bool DeviceContextBase::ClearRenderTarget(ITextureView* pView) -{ - if (pView == nullptr) - { - LOG_ERROR_MESSAGE("Render target view to clear must not be null"); - return false; - } - -#ifdef DEVELOPMENT - { - const auto& ViewDesc = pView->GetDesc(); - if (ViewDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET) - { - LOG_ERROR_MESSAGE("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, - "' is invalid: ClearRenderTarget command expects render target view (TEXTURE_VIEW_RENDER_TARGET)."); - return false; - } - - bool RTFound = false; - for (Uint32 i = 0; i < m_NumBoundRenderTargets && !RTFound; ++i) - { - RTFound = m_pBoundRenderTargets[i] == pView; - } - if (!RTFound) - { - if (m_pDevice->GetDeviceCaps().IsGLDevice()) - { - LOG_ERROR_MESSAGE("Render target view '", ViewDesc.Name, - "' is not bound to the device context. ClearRenderTarget command " - "requires render target view be bound to the device contex in OpenGL backend"); - return false; - } - else - { - LOG_WARNING_MESSAGE("Render target view '", ViewDesc.Name, - "' is not bound to the device context. ClearRenderTarget command is more efficient " - "if render target view is bound to the device context. In OpenGL backend this is a requirement."); - } - } - } -#endif - - return true; -} - -template -inline bool DeviceContextBase::BeginQuery(IQuery* pQuery, int) -{ - if (pQuery == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: pQuery must not be null"); - return false; - } - - if (m_bIsDeferred) - { - LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: Deferred contexts do not support queries"); - return false; - } - - if (pQuery->GetDesc().Type == QUERY_TYPE_TIMESTAMP) - { - LOG_ERROR_MESSAGE("BeginQuery() is disabled for timestamp queries. Call EndQuery() to set the timestamp."); - return false; - } - - if (!ValidatedCast(pQuery)->OnBeginQuery(this)) - return false; - - return true; -} - -template -inline bool DeviceContextBase::EndQuery(IQuery* pQuery, int) -{ - if (pQuery == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: pQuery must not be null"); - return false; - } - - if (m_bIsDeferred) - { - LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: Deferred contexts do not support queries"); - return false; - } - - if (!ValidatedCast(pQuery)->OnEndQuery(this)) - return false; - - return true; -} - -template -inline void DeviceContextBase:: - UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) -{ - VERIFY(pBuffer != nullptr, "Buffer must not be null"); -#ifdef DEVELOPMENT - const auto& BuffDesc = ValidatedCast(pBuffer)->GetDesc(); - DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DEFAULT, "Unable to update buffer '", BuffDesc.Name, "': only USAGE_DEFAULT buffers can be updated with UpdateData()"); - DEV_CHECK_ERR(Offset < BuffDesc.uiSizeInBytes, "Unable to update buffer '", BuffDesc.Name, "': offset (", Offset, ") exceeds the buffer size (", BuffDesc.uiSizeInBytes, ")"); - DEV_CHECK_ERR(Size + Offset <= BuffDesc.uiSizeInBytes, "Unable to update buffer '", BuffDesc.Name, "': Update region [", Offset, ",", Size + Offset, ") is out of buffer bounds [0,", BuffDesc.uiSizeInBytes, ")"); -#endif -} - -template -inline void DeviceContextBase:: - CopyBuffer(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - IBuffer* pDstBuffer, - Uint32 DstOffset, - Uint32 Size, - RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) -{ - VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null"); - VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null"); -#ifdef DEVELOPMENT - const auto& SrcBufferDesc = ValidatedCast(pSrcBuffer)->GetDesc(); - const auto& DstBufferDesc = ValidatedCast(pDstBuffer)->GetDesc(); - DEV_CHECK_ERR(DstOffset + Size <= DstBufferDesc.uiSizeInBytes, "Failed to copy buffer '", SrcBufferDesc.Name, "' to '", DstBufferDesc.Name, "': Destination range [", DstOffset, ",", DstOffset + Size, ") is out of buffer bounds [0,", DstBufferDesc.uiSizeInBytes, ")"); - DEV_CHECK_ERR(SrcOffset + Size <= SrcBufferDesc.uiSizeInBytes, "Failed to copy buffer '", SrcBufferDesc.Name, "' to '", DstBufferDesc.Name, "': Source range [", SrcOffset, ",", SrcOffset + Size, ") is out of buffer bounds [0,", SrcBufferDesc.uiSizeInBytes, ")"); -#endif -} - -template -inline void DeviceContextBase:: - MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) -{ - VERIFY(pBuffer, "pBuffer must not be null"); - - const auto& BuffDesc = pBuffer->GetDesc(); - -#ifdef _DEBUG - VERIFY(m_DbgMappedBuffers.find(pBuffer) == m_DbgMappedBuffers.end(), "Buffer '", BuffDesc.Name, "' has already been mapped"); - m_DbgMappedBuffers[pBuffer] = DbgMappedBufferInfo{MapType}; -#endif - - pMappedData = nullptr; - switch (MapType) - { - case MAP_READ: - DEV_CHECK_ERR(BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING can be read from"); - DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_READ), "Buffer being mapped for reading was not created with CPU_ACCESS_READ flag"); - DEV_CHECK_ERR((MapFlags & MAP_FLAG_DISCARD) == 0, "MAP_FLAG_DISCARD is not valid when mapping buffer for reading"); - break; - - case MAP_WRITE: - DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DYNAMIC || BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING or USAGE_DYNAMIC can be mapped for writing"); - DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Buffer being mapped for writing was not created with CPU_ACCESS_WRITE flag"); - break; - - case MAP_READ_WRITE: - DEV_CHECK_ERR(BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING can be mapped for reading and writing"); - DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Buffer being mapped for reading & writing was not created with CPU_ACCESS_WRITE flag"); - DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_READ), "Buffer being mapped for reading & writing was not created with CPU_ACCESS_READ flag"); - DEV_CHECK_ERR((MapFlags & MAP_FLAG_DISCARD) == 0, "MAP_FLAG_DISCARD is not valid when mapping buffer for reading and writing"); - break; - - default: UNEXPECTED("Unknown map type"); - } - - if (BuffDesc.Usage == USAGE_DYNAMIC) - { - DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE)) != 0 && MapType == MAP_WRITE, "Dynamic buffers can only be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_NO_OVERWRITE flag"); - DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE)) != (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE), "When mapping dynamic buffer, only one of MAP_FLAG_DISCARD or MAP_FLAG_NO_OVERWRITE flags must be specified"); - } - - if ((MapFlags & MAP_FLAG_DISCARD) != 0) - { - DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DYNAMIC || BuffDesc.Usage == USAGE_STAGING, "Only dynamic and staging buffers can be mapped with discard flag"); - DEV_CHECK_ERR(MapType == MAP_WRITE, "MAP_FLAG_DISCARD is only valid when mapping buffer for writing"); - } -} - -template -inline void DeviceContextBase:: - UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) -{ - VERIFY(pBuffer, "pBuffer must not be null"); -#ifdef _DEBUG - auto MappedBufferIt = m_DbgMappedBuffers.find(pBuffer); - VERIFY(MappedBufferIt != m_DbgMappedBuffers.end(), "Buffer '", pBuffer->GetDesc().Name, "' has not been mapped."); - VERIFY(MappedBufferIt->second.MapType == MapType, "MapType (", MapType, ") does not match the map type that was used to map the buffer ", MappedBufferIt->second.MapType); - m_DbgMappedBuffers.erase(MappedBufferIt); -#endif -} - - -template -inline void DeviceContextBase:: - UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) -{ - VERIFY(pTexture != nullptr, "pTexture must not be null"); - ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData); -} - -template -inline void DeviceContextBase:: - CopyTexture(const CopyTextureAttribs& CopyAttribs) -{ - VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null"); - VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null"); - ValidateCopyTextureParams(CopyAttribs); -} - -template -inline void DeviceContextBase:: - MapTextureSubresource(ITexture* pTexture, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - MAP_FLAGS MapFlags, - const Box* pMapRegion, - MappedTextureSubresource& MappedData) -{ - VERIFY(pTexture, "pTexture must not be null"); - ValidateMapTextureParams(pTexture->GetDesc(), MipLevel, ArraySlice, MapType, MapFlags, pMapRegion); -} - -template -inline void DeviceContextBase:: - UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) -{ - VERIFY(pTexture, "pTexture must not be null"); - DEV_CHECK_ERR(MipLevel < pTexture->GetDesc().MipLevels, "Mip level is out of range"); - DEV_CHECK_ERR(ArraySlice < pTexture->GetDesc().ArraySize, "Array slice is out of range"); -} - -template -inline void DeviceContextBase:: - GenerateMips(ITextureView* pTexView) -{ - VERIFY(pTexView != nullptr, "pTexView must not be null"); -#ifdef DEVELOPMENT - const auto& ViewDesc = pTexView->GetDesc(); - DEV_CHECK_ERR(ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Shader resource view '", ViewDesc.Name, - "' can't be used to generate mipmaps because its type is ", GetTexViewTypeLiteralName(ViewDesc.ViewType), ". Required view type: TEXTURE_VIEW_SHADER_RESOURCE."); - DEV_CHECK_ERR((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0, "Shader resource view '", ViewDesc.Name, - "' was not created with TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag and can't be used to generate mipmaps."); -#endif -} - - -template -void DeviceContextBase:: - ResolveTextureSubresource(ITexture* pSrcTexture, - ITexture* pDstTexture, - const ResolveTextureSubresourceAttribs& ResolveAttribs) -{ -#ifdef DEVELOPMENT - VERIFY_EXPR(pSrcTexture != nullptr && pDstTexture != nullptr); - const auto& SrcTexDesc = pSrcTexture->GetDesc(); - const auto& DstTexDesc = pDstTexture->GetDesc(); - DEV_CHECK_ERR(SrcTexDesc.SampleCount > 1, - "Source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled"); - DEV_CHECK_ERR(DstTexDesc.SampleCount == 1, - "Destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled"); - auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel); - auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel); - DEV_CHECK_ERR(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight, - "The size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight, - ") of the source subresource of a resolve operation (texture '", - SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice, - ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight, - ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ", - ResolveAttribs.DstSlice, ")"); - - const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format); - const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); - const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format); - if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format, - "Source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name, - ") texture formats of a resolve operation must match exaclty or be compatible typeless formats"); - DEV_CHECK_ERR(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation"); - } - if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN, - "Format of a resolve operation must not be unknown when both src and dst texture formats are typeless"); - } - if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless, - "Format of a resolve operation must not be typeless when one of the texture formats is typeless"); - } -#endif -} - -#ifdef DEVELOPMENT -template -inline bool DeviceContextBase:: - DvpVerifyDrawArguments(const DrawAttribs& Attribs) const -{ - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; - - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (m_pPipelineState->GetDesc().IsComputePipeline) - { - LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); - return false; - } - - if (Attribs.NumVertices == 0) - { - LOG_WARNING_MESSAGE("Draw command arguments are invalid: number of vertices to draw is zero."); - } - - return true; -} - -template -inline bool DeviceContextBase:: - DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const -{ - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; - - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (m_pPipelineState->GetDesc().IsComputePipeline) - { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); - return false; - } - - if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) - { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: IndexType (", - GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); - return false; - } - - if (!m_pIndexBuffer) - { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound."); - return false; - } - - if (Attribs.NumIndices == 0) - { - LOG_WARNING_MESSAGE("DrawIndexed command arguments are invalid: number of indices to draw is zero."); - } - - return true; -} - -template -inline bool DeviceContextBase:: - DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const -{ - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; - - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (m_pPipelineState->GetDesc().IsComputePipeline) - { - - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); - return false; - } - - if (pAttribsBuffer != nullptr) - { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer is null."); - return false; - } - - return true; -} - -template -inline bool DeviceContextBase:: - DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const -{ - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; - - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (m_pPipelineState->GetDesc().IsComputePipeline) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); - return false; - } - - if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: IndexType (", - GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); - return false; - } - - if (!m_pIndexBuffer) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound."); - return false; - } - - if (pAttribsBuffer != nullptr) - { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer is null."); - return false; - } - - return true; -} - -template -inline void DeviceContextBase:: - DvpVerifyRenderTargets() const -{ - if (!m_pPipelineState) - { - LOG_ERROR("No pipeline state is bound"); - return; - } - - TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN}; - TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN; - - for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) - { - if (auto* pRT = m_pBoundRenderTargets[rt].RawPtr()) - BoundRTVFormats[rt] = pRT->GetDesc().Format; - else - BoundRTVFormats[rt] = TEX_FORMAT_UNKNOWN; - } - - BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; - - const auto& PSODesc = m_pPipelineState->GetDesc(); - const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; - if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) - { - LOG_WARNING_MESSAGE("Number of currently bound render targets (", m_NumBoundRenderTargets, - ") does not match the number of outputs specified by the PSO '", PSODesc.Name, - "' (", Uint32{GraphicsPipeline.NumRenderTargets}, ")."); - } - - if (BoundDSVFormat != GraphicsPipeline.DSVFormat) - { - LOG_WARNING_MESSAGE("Currently bound depth-stencil buffer format (", GetTextureFormatAttribs(BoundDSVFormat).Name, - ") does not match the DSV format specified by the PSO '", PSODesc.Name, - "' (", GetTextureFormatAttribs(GraphicsPipeline.DSVFormat).Name, ")."); - } - - for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) - { - auto BoundFmt = BoundRTVFormats[rt]; - auto PSOFmt = GraphicsPipeline.RTVFormats[rt]; - if (BoundFmt != PSOFmt) - { - LOG_WARNING_MESSAGE("Render target bound to slot ", rt, " (", GetTextureFormatAttribs(BoundFmt).Name, - ") does not match the RTV format specified by the PSO '", PSODesc.Name, - "' (", GetTextureFormatAttribs(PSOFmt).Name, ")."); - } - } -} - - - -template -inline bool DeviceContextBase:: - DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const -{ - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("DispatchCompute command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (!m_pPipelineState->GetDesc().IsComputePipeline) - { - LOG_ERROR_MESSAGE("DispatchCompute command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, - "' is a graphics pipeline."); - return false; - } - - if (Attribs.ThreadGroupCountX == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero."); - - if (Attribs.ThreadGroupCountY == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountY is zero."); - - if (Attribs.ThreadGroupCountZ == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountZ is zero."); - - return true; -} - -template -inline bool DeviceContextBase:: - DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const -{ - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (!m_pPipelineState->GetDesc().IsComputePipeline) - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is a graphics pipeline."); - return false; - } - - if (pAttribsBuffer != nullptr) - { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer is null."); - return false; - } - - return true; -} - - -template -void DeviceContextBase:: - DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const -{ - DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null"); - DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); - RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; - if (Barrier.pTexture) - { - const auto& TexDesc = Barrier.pTexture->GetDesc(); - - DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, - "The state of texture '", TexDesc.Name, - "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'"); - - DEV_CHECK_ERR(Barrier.FirstMipLevel < TexDesc.MipLevels, "First mip level (", Barrier.FirstMipLevel, - ") specified by the barrier is out of range. Texture '", - TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); - DEV_CHECK_ERR(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels, - "Mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1, - " specified by the barrier is out of range. Texture '", - TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); - - DEV_CHECK_ERR(Barrier.FirstArraySlice < TexDesc.ArraySize, "First array slice (", Barrier.FirstArraySlice, - ") specified by the barrier is out of range. Array size of texture '", - TexDesc.Name, "' is ", TexDesc.ArraySize); - DEV_CHECK_ERR(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize, - "Array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1, - " specified by the barrier is out of range. Array size of texture '", - TexDesc.Name, "' is ", TexDesc.ArraySize); - - auto DevType = m_pDevice->GetDeviceCaps().DevType; - if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN) - { - DEV_CHECK_ERR(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels), - "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); - DEV_CHECK_ERR(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize), - "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); - } - } - else - { - const auto& BuffDesc = Barrier.pBuffer->GetDesc(); - DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); - } - - if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) - { - DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE"); - } - - if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN) - { - DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier"); - } -} - -template -bool DeviceContextBase:: - DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const -{ - if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState)) - { - LOG_ERROR_MESSAGE(OperationName, " requires texture '", Texture.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), - " state. Actual texture state: ", GetResourceStateString(Texture.GetState()), - ". Use appropriate state transiton flags or explicitly transition the texture using IDeviceContext::TransitionResourceStates() method."); - return false; - } - - return true; -} - -template -bool DeviceContextBase:: - DvpVerifyBufferState(const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const -{ - if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState)) - { - LOG_ERROR_MESSAGE(OperationName, " requires buffer '", Buffer.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), - " state. Actual buffer state: ", GetResourceStateString(Buffer.GetState()), - ". Use appropriate state transiton flags or explicitly transition the buffer using IDeviceContext::TransitionResourceStates() method."); - return false; - } - - return true; -} - -#endif // DEVELOPMENT - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp new file mode 100644 index 00000000..87604f84 --- /dev/null +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -0,0 +1,1518 @@ +/* + * Copyright 2019-2020 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::DeviceContextBase template class and related structures + +#include + +#include "DeviceContext.h" +#include "DeviceObjectBase.hpp" +#include "ResourceMapping.h" +#include "Sampler.h" +#include "ObjectBase.h" +#include "DebugUtilities.h" +#include "ValidatedCast.h" +#include "GraphicsAccessories.hpp" +#include "TextureBase.hpp" + +namespace Diligent +{ + +/// Describes input vertex stream +template +struct VertexStreamInfo +{ + VertexStreamInfo() {} + + /// Strong reference to the buffer object + RefCntAutoPtr pBuffer; + Uint32 Offset = 0; ///< Offset in bytes +}; + +/// Base implementation of the device context. + +/// \tparam BaseInterface - base interface that this class will inheret. +/// \tparam ImplementationTraits - implementation traits that define specific implementation details +/// (texture implemenation type, buffer implementation type, etc.) +/// \remarks Device context keeps strong references to all objects currently bound to +/// the pipeline: buffers, states, samplers, shaders, etc. +/// The context also keeps strong references to the device and +/// the swap chain. +template +class DeviceContextBase : public ObjectBase +{ +public: + using TObjectBase = ObjectBase; + using DeviceImplType = typename ImplementationTraits::DeviceType; + using BufferImplType = typename ImplementationTraits::BufferType; + using TextureImplType = typename ImplementationTraits::TextureType; + using PipelineStateImplType = typename ImplementationTraits::PipelineStateType; + using TextureViewImplType = typename TextureImplType::ViewImplType; + using QueryImplType = typename ImplementationTraits::QueryType; + + /// \param pRefCounters - reference counters object that controls the lifetime of this device context. + /// \param pRenderDevice - render device. + /// \param bIsDeferred - flag indicating if this instance is a deferred context + DeviceContextBase(IReferenceCounters* pRefCounters, DeviceImplType* pRenderDevice, bool bIsDeferred) : + // clang-format off + TObjectBase {pRefCounters }, + m_pDevice {pRenderDevice}, + m_bIsDeferred{bIsDeferred } + // clang-format on + { + } + + ~DeviceContextBase() + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceContext, TObjectBase) + + /// Base implementation of IDeviceContext::SetVertexBuffers(); validates parameters and + /// caches references to the buffers. + inline virtual void SetVertexBuffers(Uint32 StartSlot, + Uint32 NumBuffersSet, + IBuffer** ppBuffers, + Uint32* pOffsets, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + SET_VERTEX_BUFFERS_FLAGS Flags) override = 0; + + inline virtual void InvalidateState() override = 0; + + /// Base implementation of IDeviceContext::CommitShaderResources(); validates parameters. + inline bool CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + int); + + /// Base implementation of IDeviceContext::SetIndexBuffer(); caches the strong reference to the index buffer + inline virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; + + /// Caches the viewports + inline void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight); + + /// Caches the scissor rects + inline void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight); + + /// Caches the render target and depth stencil views. Returns true if any view is different + /// from the cached value and false otherwise. + inline bool SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil); + + /// Base implementation of IDeviceContext::UpdateBuffer(); validates input parameters. + virtual void UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; + + /// Base implementation of IDeviceContext::CopyBuffer(); validates input parameters. + virtual void CopyBuffer(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + IBuffer* pDstBuffer, + Uint32 DstOffset, + Uint32 Size, + RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override = 0; + + /// Base implementation of IDeviceContext::MapBuffer(); validates input parameters. + virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override = 0; + + /// Base implementation of IDeviceContext::UnmapBuffer() + virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override = 0; + + /// Base implementaiton of IDeviceContext::UpdateData(); validates input parameters + virtual void UpdateTexture(ITexture* pTexture, + Uint32 MipLevel, + Uint32 Slice, + const Box& DstBox, + const TextureSubResData& SubresData, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) override = 0; + + /// Base implementaiton of IDeviceContext::CopyTexture(); validates input parameters + virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override = 0; + + /// Base implementaiton of IDeviceContext::MapTextureSubresource() + virtual void MapTextureSubresource(ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) override = 0; + + /// Base implementaiton of IDeviceContext::UnmapTextureSubresource() + virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override = 0; + + virtual void GenerateMips(ITextureView* pTexView) override = 0; + + virtual void ResolveTextureSubresource(ITexture* pSrcTexture, + ITexture* pDstTexture, + const ResolveTextureSubresourceAttribs& ResolveAttribs) override = 0; + + /// Returns currently bound pipeline state and blend factors + inline void GetPipelineState(IPipelineState** ppPSO, float* BlendFactors, Uint32& StencilRef); + + /// Returns currently bound render targets + inline void GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV); + + /// Returns currently set viewports + inline void GetViewports(Uint32& NumViewports, Viewport* pViewports); + + /// Returns the render device + IRenderDevice* GetDevice() { return m_pDevice; } + + virtual void ResetRenderTargets(); + + bool IsDeferred() const { return m_bIsDeferred; } + + /// Checks if a texture is bound as a render target or depth-stencil buffer and + /// resets render targets if it is. + bool UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage); + +protected: + inline bool SetBlendFactors(const float* BlendFactors, int Dummy); + + inline bool SetStencilRef(Uint32 StencilRef, int Dummy); + + inline void SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/); + + /// Clears all cached resources + inline void ClearStateCache(); + + /// Checks if the texture is currently bound as a render target. + bool CheckIfBoundAsRenderTarget(TextureImplType* pTexture); + + /// Checks if the texture is currently bound as depth-stencil buffer. + bool CheckIfBoundAsDepthStencil(TextureImplType* pTexture); + + bool ClearDepthStencil(ITextureView* pView); + + bool ClearRenderTarget(ITextureView* pView); + + bool BeginQuery(IQuery* pQuery, int); + + bool EndQuery(IQuery* pQuery, int); + +#ifdef DEVELOPMENT + // clang-format off + bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const; + bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const; + bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; + bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; + + bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const; + bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; + + void DvpVerifyRenderTargets()const; + void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const; + bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const; +#else + bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;} + bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;} + bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} + bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} + + bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;} + bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} + + void DvpVerifyRenderTargets()const {} + void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {} + bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + // clang-format on +#endif + + /// Strong reference to the device. + RefCntAutoPtr m_pDevice; + + /// Vertex streams. Every stream holds strong reference to the buffer + VertexStreamInfo m_VertexStreams[MAX_BUFFER_SLOTS]; + + /// Number of bound vertex streams + Uint32 m_NumVertexStreams = 0; + + /// Strong reference to the bound pipeline state object. + /// Use final PSO implementation type to avoid virtual calls to AddRef()/Release(). + /// We need to keep strong reference as we examine previous pipeline state in + /// SetPipelineState() + RefCntAutoPtr m_pPipelineState; + + /// Strong reference to the bound index buffer. + /// Use final buffer implementation type to avoid virtual calls to AddRef()/Release() + RefCntAutoPtr m_pIndexBuffer; + + /// Offset from the beginning of the index buffer to the start of the index data, in bytes. + Uint32 m_IndexDataStartOffset = 0; + + /// Current stencil reference value + Uint32 m_StencilRef = 0; + + /// Curent blend factors + Float32 m_BlendFactors[4] = {-1, -1, -1, -1}; + + /// Current viewports + Viewport m_Viewports[MAX_VIEWPORTS]; + /// Number of current viewports + Uint32 m_NumViewports = 0; + + /// Current scissor rects + Rect m_ScissorRects[MAX_VIEWPORTS]; + /// Number of current scissor rects + Uint32 m_NumScissorRects = 0; + + /// Vector of strong references to the bound render targets. + /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() + RefCntAutoPtr m_pBoundRenderTargets[MAX_RENDER_TARGETS]; + /// Number of bound render targets + Uint32 m_NumBoundRenderTargets = 0; + /// Width of the currently bound framebuffer + Uint32 m_FramebufferWidth = 0; + /// Height of the currently bound framebuffer + Uint32 m_FramebufferHeight = 0; + /// Number of array slices in the currently bound framebuffer + Uint32 m_FramebufferSlices = 0; + + /// Strong references to the bound depth stencil view. + /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() + RefCntAutoPtr m_pBoundDepthStencil; + + const bool m_bIsDeferred = false; + +#ifdef _DEBUG + // std::unordered_map is unbelievably slow. Keeping track of mapped buffers + // in release builds is not feasible + struct DbgMappedBufferInfo + { + MAP_TYPE MapType; + }; + std::unordered_map m_DbgMappedBuffers; +#endif +}; + + +template +inline void DeviceContextBase:: + SetVertexBuffers(Uint32 StartSlot, + Uint32 NumBuffersSet, + IBuffer** ppBuffers, + Uint32* pOffsets, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + SET_VERTEX_BUFFERS_FLAGS Flags) +{ +#ifdef DEVELOPMENT + if (StartSlot >= MAX_BUFFER_SLOTS) + { + LOG_ERROR_MESSAGE("Start vertex buffer slot ", StartSlot, " is out of allowed range [0, ", MAX_BUFFER_SLOTS - 1, "]."); + return; + } + + if (StartSlot + NumBuffersSet > MAX_BUFFER_SLOTS) + { + LOG_ERROR_MESSAGE("The range of vertex buffer slots being set [", StartSlot, ", ", StartSlot + NumBuffersSet - 1, "] is out of allowed range [0, ", MAX_BUFFER_SLOTS - 1, "]."); + NumBuffersSet = MAX_BUFFER_SLOTS - StartSlot; + } +#endif + + if (Flags & SET_VERTEX_BUFFERS_FLAG_RESET) + { + // Reset only these buffer slots that are not being set. + // It is very important to not reset buffers that stay unchanged + // as AddRef()/Release() are not free + for (Uint32 s = 0; s < StartSlot; ++s) + m_VertexStreams[s] = VertexStreamInfo{}; + for (Uint32 s = StartSlot + NumBuffersSet; s < m_NumVertexStreams; ++s) + m_VertexStreams[s] = VertexStreamInfo{}; + m_NumVertexStreams = 0; + } + m_NumVertexStreams = std::max(m_NumVertexStreams, StartSlot + NumBuffersSet); + + for (Uint32 Buff = 0; Buff < NumBuffersSet; ++Buff) + { + auto& CurrStream = m_VertexStreams[StartSlot + Buff]; + CurrStream.pBuffer = ppBuffers ? ValidatedCast(ppBuffers[Buff]) : nullptr; + CurrStream.Offset = pOffsets ? pOffsets[Buff] : 0; +#ifdef DEVELOPMENT + if (CurrStream.pBuffer) + { + const auto& BuffDesc = CurrStream.pBuffer->GetDesc(); + if (!(BuffDesc.BindFlags & BIND_VERTEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", BuffDesc.Name ? BuffDesc.Name : "", "' being bound as vertex buffer to slot ", Buff, " was not created with BIND_VERTEX_BUFFER flag"); + } + } +#endif + } + // Remove null buffers from the end of the array + while (m_NumVertexStreams > 0 && !m_VertexStreams[m_NumVertexStreams - 1].pBuffer) + m_VertexStreams[m_NumVertexStreams--] = VertexStreamInfo{}; +} + +template +inline void DeviceContextBase:: + SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/) +{ + m_pPipelineState = pPipelineState; +} + +template +inline bool DeviceContextBase:: + CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int) +{ +#ifdef DEVELOPMENT + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("No pipeline state is bound to the pipeline"); + return false; + } + + if (pShaderResourceBinding) + { + if (m_pPipelineState->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState())) + { + LOG_ERROR_MESSAGE("Shader resource binding object is not compatible with the currently bound pipeline state '", m_pPipelineState->GetDesc().Name, '\''); + return false; + } + } +#endif + return true; +} + +template +inline void DeviceContextBase::InvalidateState() +{ + DeviceContextBase::ClearStateCache(); +} + +template +inline void DeviceContextBase:: + SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +{ + m_pIndexBuffer = ValidatedCast(pIndexBuffer); + m_IndexDataStartOffset = ByteOffset; +#ifdef DEVELOPMENT + if (m_pIndexBuffer) + { + const auto& BuffDesc = m_pIndexBuffer->GetDesc(); + if (!(BuffDesc.BindFlags & BIND_INDEX_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", BuffDesc.Name ? BuffDesc.Name : "", "' being bound as index buffer was not created with BIND_INDEX_BUFFER flag"); + } + } +#endif +} + + +template +inline void DeviceContextBase::GetPipelineState(IPipelineState** ppPSO, float* BlendFactors, Uint32& StencilRef) +{ + VERIFY(ppPSO != nullptr, "Null pointer provided null"); + VERIFY(*ppPSO == nullptr, "Memory address contains a pointer to a non-null blend state"); + if (m_pPipelineState) + { + m_pPipelineState->QueryInterface(IID_PipelineState, reinterpret_cast(ppPSO)); + } + else + { + *ppPSO = nullptr; + } + + for (Uint32 f = 0; f < 4; ++f) + BlendFactors[f] = m_BlendFactors[f]; + StencilRef = m_StencilRef; +}; + +template +inline bool DeviceContextBase::SetBlendFactors(const float* BlendFactors, int) +{ + bool FactorsDiffer = false; + for (Uint32 f = 0; f < 4; ++f) + { + if (m_BlendFactors[f] != BlendFactors[f]) + FactorsDiffer = true; + m_BlendFactors[f] = BlendFactors[f]; + } + return FactorsDiffer; +} + +template +inline bool DeviceContextBase::SetStencilRef(Uint32 StencilRef, int) +{ + if (m_StencilRef != StencilRef) + { + m_StencilRef = StencilRef; + return true; + } + return false; +} + +template +inline void DeviceContextBase:: + SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight) +{ + if (RTWidth == 0 || RTHeight == 0) + { + RTWidth = m_FramebufferWidth; + RTHeight = m_FramebufferHeight; + } + + VERIFY(NumViewports < MAX_VIEWPORTS, "Number of viewports (", NumViewports, ") exceeds the limit (", MAX_VIEWPORTS, ")"); + m_NumViewports = std::min(MAX_VIEWPORTS, NumViewports); + + Viewport DefaultVP(0, 0, static_cast(RTWidth), static_cast(RTHeight)); + // If no viewports are specified, use default viewport + if (m_NumViewports == 1 && pViewports == nullptr) + { + pViewports = &DefaultVP; + } + + for (Uint32 vp = 0; vp < m_NumViewports; ++vp) + { + m_Viewports[vp] = pViewports[vp]; + VERIFY(m_Viewports[vp].Width >= 0, "Incorrect viewport width (", m_Viewports[vp].Width, ")"); + VERIFY(m_Viewports[vp].Height >= 0, "Incorrect viewport height (", m_Viewports[vp].Height, ")"); + VERIFY(m_Viewports[vp].MaxDepth >= m_Viewports[vp].MinDepth, "Incorrect viewport depth range [", m_Viewports[vp].MinDepth, ", ", m_Viewports[vp].MaxDepth, "]"); + } +} + +template +inline void DeviceContextBase::GetViewports(Uint32& NumViewports, Viewport* pViewports) +{ + NumViewports = m_NumViewports; + if (pViewports) + { + for (Uint32 vp = 0; vp < m_NumViewports; ++vp) + pViewports[vp] = m_Viewports[vp]; + } +} + +template +inline void DeviceContextBase:: + SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight) +{ + if (RTWidth == 0 || RTHeight == 0) + { + RTWidth = m_FramebufferWidth; + RTHeight = m_FramebufferHeight; + } + + VERIFY(NumRects < MAX_VIEWPORTS, "Number of scissor rects (", NumRects, ") exceeds the limit (", MAX_VIEWPORTS, ")"); + m_NumScissorRects = std::min(MAX_VIEWPORTS, NumRects); + + for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr) + { + m_ScissorRects[sr] = pRects[sr]; + VERIFY(m_ScissorRects[sr].left <= m_ScissorRects[sr].right, "Incorrect horizontal bounds for a scissor rect [", m_ScissorRects[sr].left, ", ", m_ScissorRects[sr].right, ")"); + VERIFY(m_ScissorRects[sr].top <= m_ScissorRects[sr].bottom, "Incorrect vertical bounds for a scissor rect [", m_ScissorRects[sr].top, ", ", m_ScissorRects[sr].bottom, ")"); + } +} + +template +inline bool DeviceContextBase:: + SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil) +{ + if (NumRenderTargets == 0 && pDepthStencil == nullptr) + { + ResetRenderTargets(); + return false; + } + + bool bBindRenderTargets = false; + m_FramebufferWidth = 0; + m_FramebufferHeight = 0; + m_FramebufferSlices = 0; + + if (NumRenderTargets != m_NumBoundRenderTargets) + { + bBindRenderTargets = true; + for (Uint32 rt = NumRenderTargets; rt < m_NumBoundRenderTargets; ++rt) + m_pBoundRenderTargets[rt].Release(); + + m_NumBoundRenderTargets = NumRenderTargets; + } + + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) + { + auto* pRTView = ppRenderTargets[rt]; + if (pRTView) + { + const auto& RTVDesc = pRTView->GetDesc(); +#ifdef DEVELOPMENT + if (RTVDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET) + LOG_ERROR("Texture view object named '", RTVDesc.Name ? RTVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(RTVDesc.ViewType), "). Render target view is expected"); +#endif + // Use this RTV to set the render target size + if (m_FramebufferWidth == 0) + { + auto* pTex = pRTView->GetTexture(); + const auto& TexDesc = pTex->GetDesc(); + m_FramebufferWidth = std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U); + m_FramebufferHeight = std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U); + m_FramebufferSlices = RTVDesc.NumArraySlices; + } + else + { +#ifdef DEVELOPMENT + const auto& TexDesc = pRTView->GetTexture()->GetDesc(); + if (m_FramebufferWidth != std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U)) + LOG_ERROR("Render target width (", std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); + if (m_FramebufferHeight != std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U)) + LOG_ERROR("Render target height (", std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); + if (m_FramebufferSlices != RTVDesc.NumArraySlices) + LOG_ERROR("Number of slices (", RTVDesc.NumArraySlices, ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); +#endif + } + } + + // Here both views are certainly live objects, since we store + // strong references to all bound render targets. So we + // can safely compare pointers. + if (m_pBoundRenderTargets[rt] != pRTView) + { + m_pBoundRenderTargets[rt] = ValidatedCast(pRTView); + bBindRenderTargets = true; + } + } + + if (pDepthStencil != nullptr) + { + const auto& DSVDesc = pDepthStencil->GetDesc(); +#ifdef DEVELOPMENT + if (DSVDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL) + LOG_ERROR("Texture view object named '", DSVDesc.Name ? DSVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(DSVDesc.ViewType), "). Depth stencil view is expected"); +#endif + + // Use depth stencil size to set render target size + if (m_FramebufferWidth == 0) + { + auto* pTex = pDepthStencil->GetTexture(); + const auto& TexDesc = pTex->GetDesc(); + m_FramebufferWidth = std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U); + m_FramebufferHeight = std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U); + m_FramebufferSlices = DSVDesc.NumArraySlices; + } + else + { +#ifdef DEVELOPMENT + const auto& TexDesc = pDepthStencil->GetTexture()->GetDesc(); + if (m_FramebufferWidth != std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U)) + LOG_ERROR("Depth-stencil target width (", std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); + if (m_FramebufferHeight != std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U)) + LOG_ERROR("Depth-stencil target height (", std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); + if (m_FramebufferSlices != DSVDesc.NumArraySlices) + LOG_ERROR("Number of slices (", DSVDesc.NumArraySlices, ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); +#endif + } + } + + if (m_pBoundDepthStencil != pDepthStencil) + { + m_pBoundDepthStencil = ValidatedCast(pDepthStencil); + bBindRenderTargets = true; + } + + + VERIFY_EXPR(m_FramebufferWidth > 0 && m_FramebufferHeight > 0 && m_FramebufferSlices > 0); + + return bBindRenderTargets; +} + +template +inline void DeviceContextBase:: + GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV) +{ + NumRenderTargets = m_NumBoundRenderTargets; + + if (ppRTVs) + { + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) + { + VERIFY(ppRTVs[rt] == nullptr, "Non-null pointer found in RTV array element #", rt); + auto pBoundRTV = m_pBoundRenderTargets[rt]; + if (pBoundRTV) + pBoundRTV->QueryInterface(IID_TextureView, reinterpret_cast(ppRTVs + rt)); + else + ppRTVs[rt] = nullptr; + } + for (Uint32 rt = NumRenderTargets; rt < MAX_RENDER_TARGETS; ++rt) + { + VERIFY(ppRTVs[rt] == nullptr, "Non-null pointer found in RTV array element #", rt); + ppRTVs[rt] = nullptr; + } + } + + if (ppDSV) + { + VERIFY(*ppDSV == nullptr, "Non-null DSV pointer found"); + if (m_pBoundDepthStencil) + m_pBoundDepthStencil->QueryInterface(IID_TextureView, reinterpret_cast(ppDSV)); + else + *ppDSV = nullptr; + } +} + +template +inline void DeviceContextBase::ClearStateCache() +{ + for (Uint32 stream = 0; stream < m_NumVertexStreams; ++stream) + m_VertexStreams[stream] = VertexStreamInfo{}; +#ifdef _DEBUG + for (Uint32 stream = m_NumVertexStreams; stream < _countof(m_VertexStreams); ++stream) + { + VERIFY(m_VertexStreams[stream].pBuffer == nullptr, "Unexpected non-null buffer"); + VERIFY(m_VertexStreams[stream].Offset == 0, "Unexpected non-zero offset"); + } +#endif + m_NumVertexStreams = 0; + + m_pPipelineState.Release(); + + m_pIndexBuffer.Release(); + m_IndexDataStartOffset = 0; + + m_StencilRef = 0; + + for (int i = 0; i < 4; ++i) + m_BlendFactors[i] = -1; + + for (Uint32 vp = 0; vp < m_NumViewports; ++vp) + m_Viewports[vp] = Viewport(); + m_NumViewports = 0; + + for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr) + m_ScissorRects[sr] = Rect(); + m_NumScissorRects = 0; + + ResetRenderTargets(); +} + +template +bool DeviceContextBase::CheckIfBoundAsRenderTarget(TextureImplType* pTexture) +{ + if (pTexture == nullptr) + return false; + + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) + { + if (m_pBoundRenderTargets[rt] && m_pBoundRenderTargets[rt]->GetTexture() == pTexture) + { + return true; + } + } + + return false; +} + +template +bool DeviceContextBase::CheckIfBoundAsDepthStencil(TextureImplType* pTexture) +{ + if (pTexture == nullptr) + return false; + + return m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture() == pTexture; +} + +template +bool DeviceContextBase::UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage) +{ + if (pTexture == nullptr) + return false; + + const auto& TexDesc = pTexture->GetDesc(); + + bool bResetRenderTargets = false; + if (TexDesc.BindFlags & BIND_RENDER_TARGET) + { + if (CheckIfBoundAsRenderTarget(pTexture)) + { + if (bShowMessage) + { + LOG_INFO_MESSAGE("Texture '", TexDesc.Name, + "' is currently bound as render target and will be unset along with all " + "other render targets and depth-stencil buffer. " + "Call SetRenderTargets() to reset the render targets.\n" + "To silence this message, explicitly unbind the texture with " + "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); + } + + bResetRenderTargets = true; + } + } + + if (TexDesc.BindFlags & BIND_DEPTH_STENCIL) + { + if (CheckIfBoundAsDepthStencil(pTexture)) + { + if (bShowMessage) + { + LOG_INFO_MESSAGE("Texture '", TexDesc.Name, + "' is currently bound as depth buffer and will be unset along with " + "all render targets. Call SetRenderTargets() to reset the render targets.\n" + "To silence this message, explicitly unbind the texture with " + "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); + } + + bResetRenderTargets = true; + } + } + + if (bResetRenderTargets) + { + ResetRenderTargets(); + } + + return bResetRenderTargets; +} + +template +void DeviceContextBase::ResetRenderTargets() +{ + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) + m_pBoundRenderTargets[rt].Release(); +#ifdef _DEBUG + for (Uint32 rt = m_NumBoundRenderTargets; rt < _countof(m_pBoundRenderTargets); ++rt) + { + VERIFY(m_pBoundRenderTargets[rt] == nullptr, "Non-null render target found"); + } +#endif + m_NumBoundRenderTargets = 0; + m_FramebufferWidth = 0; + m_FramebufferHeight = 0; + m_FramebufferSlices = 0; + + m_pBoundDepthStencil.Release(); +} + + +template +inline bool DeviceContextBase::ClearDepthStencil(ITextureView* pView) +{ + if (pView == nullptr) + { + LOG_ERROR_MESSAGE("Depth-stencil view to clear must not be null"); + return false; + } + +#ifdef DEVELOPMENT + { + const auto& ViewDesc = pView->GetDesc(); + if (ViewDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL) + { + LOG_ERROR_MESSAGE("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of the texture view '", ViewDesc.Name, + "' is invalid: ClearDepthStencil command expects depth-stencil view (TEXTURE_VIEW_DEPTH_STENCIL)."); + return false; + } + + if (pView != m_pBoundDepthStencil) + { + if (m_pDevice->GetDeviceCaps().IsGLDevice()) + { + LOG_ERROR_MESSAGE("Depth-stencil view '", ViewDesc.Name, + "' is not bound to the device context. ClearDepthStencil command requires " + "depth-stencil view be bound to the device contex in OpenGL backend"); + return false; + } + else + { + LOG_WARNING_MESSAGE("Depth-stencil view '", ViewDesc.Name, + "' is not bound to the device context. " + "ClearDepthStencil command is more efficient when depth-stencil " + "view is bound to the context. In OpenGL backend this is a requirement."); + } + } + } +#endif + + return true; +} + +template +inline bool DeviceContextBase::ClearRenderTarget(ITextureView* pView) +{ + if (pView == nullptr) + { + LOG_ERROR_MESSAGE("Render target view to clear must not be null"); + return false; + } + +#ifdef DEVELOPMENT + { + const auto& ViewDesc = pView->GetDesc(); + if (ViewDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET) + { + LOG_ERROR_MESSAGE("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, + "' is invalid: ClearRenderTarget command expects render target view (TEXTURE_VIEW_RENDER_TARGET)."); + return false; + } + + bool RTFound = false; + for (Uint32 i = 0; i < m_NumBoundRenderTargets && !RTFound; ++i) + { + RTFound = m_pBoundRenderTargets[i] == pView; + } + if (!RTFound) + { + if (m_pDevice->GetDeviceCaps().IsGLDevice()) + { + LOG_ERROR_MESSAGE("Render target view '", ViewDesc.Name, + "' is not bound to the device context. ClearRenderTarget command " + "requires render target view be bound to the device contex in OpenGL backend"); + return false; + } + else + { + LOG_WARNING_MESSAGE("Render target view '", ViewDesc.Name, + "' is not bound to the device context. ClearRenderTarget command is more efficient " + "if render target view is bound to the device context. In OpenGL backend this is a requirement."); + } + } + } +#endif + + return true; +} + +template +inline bool DeviceContextBase::BeginQuery(IQuery* pQuery, int) +{ + if (pQuery == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: pQuery must not be null"); + return false; + } + + if (m_bIsDeferred) + { + LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: Deferred contexts do not support queries"); + return false; + } + + if (pQuery->GetDesc().Type == QUERY_TYPE_TIMESTAMP) + { + LOG_ERROR_MESSAGE("BeginQuery() is disabled for timestamp queries. Call EndQuery() to set the timestamp."); + return false; + } + + if (!ValidatedCast(pQuery)->OnBeginQuery(this)) + return false; + + return true; +} + +template +inline bool DeviceContextBase::EndQuery(IQuery* pQuery, int) +{ + if (pQuery == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: pQuery must not be null"); + return false; + } + + if (m_bIsDeferred) + { + LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: Deferred contexts do not support queries"); + return false; + } + + if (!ValidatedCast(pQuery)->OnEndQuery(this)) + return false; + + return true; +} + +template +inline void DeviceContextBase:: + UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +{ + VERIFY(pBuffer != nullptr, "Buffer must not be null"); +#ifdef DEVELOPMENT + const auto& BuffDesc = ValidatedCast(pBuffer)->GetDesc(); + DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DEFAULT, "Unable to update buffer '", BuffDesc.Name, "': only USAGE_DEFAULT buffers can be updated with UpdateData()"); + DEV_CHECK_ERR(Offset < BuffDesc.uiSizeInBytes, "Unable to update buffer '", BuffDesc.Name, "': offset (", Offset, ") exceeds the buffer size (", BuffDesc.uiSizeInBytes, ")"); + DEV_CHECK_ERR(Size + Offset <= BuffDesc.uiSizeInBytes, "Unable to update buffer '", BuffDesc.Name, "': Update region [", Offset, ",", Size + Offset, ") is out of buffer bounds [0,", BuffDesc.uiSizeInBytes, ")"); +#endif +} + +template +inline void DeviceContextBase:: + CopyBuffer(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + IBuffer* pDstBuffer, + Uint32 DstOffset, + Uint32 Size, + RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) +{ + VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null"); + VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null"); +#ifdef DEVELOPMENT + const auto& SrcBufferDesc = ValidatedCast(pSrcBuffer)->GetDesc(); + const auto& DstBufferDesc = ValidatedCast(pDstBuffer)->GetDesc(); + DEV_CHECK_ERR(DstOffset + Size <= DstBufferDesc.uiSizeInBytes, "Failed to copy buffer '", SrcBufferDesc.Name, "' to '", DstBufferDesc.Name, "': Destination range [", DstOffset, ",", DstOffset + Size, ") is out of buffer bounds [0,", DstBufferDesc.uiSizeInBytes, ")"); + DEV_CHECK_ERR(SrcOffset + Size <= SrcBufferDesc.uiSizeInBytes, "Failed to copy buffer '", SrcBufferDesc.Name, "' to '", DstBufferDesc.Name, "': Source range [", SrcOffset, ",", SrcOffset + Size, ") is out of buffer bounds [0,", SrcBufferDesc.uiSizeInBytes, ")"); +#endif +} + +template +inline void DeviceContextBase:: + MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) +{ + VERIFY(pBuffer, "pBuffer must not be null"); + + const auto& BuffDesc = pBuffer->GetDesc(); + +#ifdef _DEBUG + VERIFY(m_DbgMappedBuffers.find(pBuffer) == m_DbgMappedBuffers.end(), "Buffer '", BuffDesc.Name, "' has already been mapped"); + m_DbgMappedBuffers[pBuffer] = DbgMappedBufferInfo{MapType}; +#endif + + pMappedData = nullptr; + switch (MapType) + { + case MAP_READ: + DEV_CHECK_ERR(BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING can be read from"); + DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_READ), "Buffer being mapped for reading was not created with CPU_ACCESS_READ flag"); + DEV_CHECK_ERR((MapFlags & MAP_FLAG_DISCARD) == 0, "MAP_FLAG_DISCARD is not valid when mapping buffer for reading"); + break; + + case MAP_WRITE: + DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DYNAMIC || BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING or USAGE_DYNAMIC can be mapped for writing"); + DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Buffer being mapped for writing was not created with CPU_ACCESS_WRITE flag"); + break; + + case MAP_READ_WRITE: + DEV_CHECK_ERR(BuffDesc.Usage == USAGE_STAGING, "Only buffers with usage USAGE_STAGING can be mapped for reading and writing"); + DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Buffer being mapped for reading & writing was not created with CPU_ACCESS_WRITE flag"); + DEV_CHECK_ERR((BuffDesc.CPUAccessFlags & CPU_ACCESS_READ), "Buffer being mapped for reading & writing was not created with CPU_ACCESS_READ flag"); + DEV_CHECK_ERR((MapFlags & MAP_FLAG_DISCARD) == 0, "MAP_FLAG_DISCARD is not valid when mapping buffer for reading and writing"); + break; + + default: UNEXPECTED("Unknown map type"); + } + + if (BuffDesc.Usage == USAGE_DYNAMIC) + { + DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE)) != 0 && MapType == MAP_WRITE, "Dynamic buffers can only be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_NO_OVERWRITE flag"); + DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE)) != (MAP_FLAG_DISCARD | MAP_FLAG_NO_OVERWRITE), "When mapping dynamic buffer, only one of MAP_FLAG_DISCARD or MAP_FLAG_NO_OVERWRITE flags must be specified"); + } + + if ((MapFlags & MAP_FLAG_DISCARD) != 0) + { + DEV_CHECK_ERR(BuffDesc.Usage == USAGE_DYNAMIC || BuffDesc.Usage == USAGE_STAGING, "Only dynamic and staging buffers can be mapped with discard flag"); + DEV_CHECK_ERR(MapType == MAP_WRITE, "MAP_FLAG_DISCARD is only valid when mapping buffer for writing"); + } +} + +template +inline void DeviceContextBase:: + UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) +{ + VERIFY(pBuffer, "pBuffer must not be null"); +#ifdef _DEBUG + auto MappedBufferIt = m_DbgMappedBuffers.find(pBuffer); + VERIFY(MappedBufferIt != m_DbgMappedBuffers.end(), "Buffer '", pBuffer->GetDesc().Name, "' has not been mapped."); + VERIFY(MappedBufferIt->second.MapType == MapType, "MapType (", MapType, ") does not match the map type that was used to map the buffer ", MappedBufferIt->second.MapType); + m_DbgMappedBuffers.erase(MappedBufferIt); +#endif +} + + +template +inline void DeviceContextBase:: + UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) +{ + VERIFY(pTexture != nullptr, "pTexture must not be null"); + ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData); +} + +template +inline void DeviceContextBase:: + CopyTexture(const CopyTextureAttribs& CopyAttribs) +{ + VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null"); + VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null"); + ValidateCopyTextureParams(CopyAttribs); +} + +template +inline void DeviceContextBase:: + MapTextureSubresource(ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) +{ + VERIFY(pTexture, "pTexture must not be null"); + ValidateMapTextureParams(pTexture->GetDesc(), MipLevel, ArraySlice, MapType, MapFlags, pMapRegion); +} + +template +inline void DeviceContextBase:: + UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) +{ + VERIFY(pTexture, "pTexture must not be null"); + DEV_CHECK_ERR(MipLevel < pTexture->GetDesc().MipLevels, "Mip level is out of range"); + DEV_CHECK_ERR(ArraySlice < pTexture->GetDesc().ArraySize, "Array slice is out of range"); +} + +template +inline void DeviceContextBase:: + GenerateMips(ITextureView* pTexView) +{ + VERIFY(pTexView != nullptr, "pTexView must not be null"); +#ifdef DEVELOPMENT + const auto& ViewDesc = pTexView->GetDesc(); + DEV_CHECK_ERR(ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Shader resource view '", ViewDesc.Name, + "' can't be used to generate mipmaps because its type is ", GetTexViewTypeLiteralName(ViewDesc.ViewType), ". Required view type: TEXTURE_VIEW_SHADER_RESOURCE."); + DEV_CHECK_ERR((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0, "Shader resource view '", ViewDesc.Name, + "' was not created with TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag and can't be used to generate mipmaps."); +#endif +} + + +template +void DeviceContextBase:: + ResolveTextureSubresource(ITexture* pSrcTexture, + ITexture* pDstTexture, + const ResolveTextureSubresourceAttribs& ResolveAttribs) +{ +#ifdef DEVELOPMENT + VERIFY_EXPR(pSrcTexture != nullptr && pDstTexture != nullptr); + const auto& SrcTexDesc = pSrcTexture->GetDesc(); + const auto& DstTexDesc = pDstTexture->GetDesc(); + DEV_CHECK_ERR(SrcTexDesc.SampleCount > 1, + "Source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled"); + DEV_CHECK_ERR(DstTexDesc.SampleCount == 1, + "Destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled"); + auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel); + auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel); + DEV_CHECK_ERR(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight, + "The size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight, + ") of the source subresource of a resolve operation (texture '", + SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice, + ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight, + ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ", + ResolveAttribs.DstSlice, ")"); + + const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format); + const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); + const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format); + if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless) + { + DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format, + "Source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name, + ") texture formats of a resolve operation must match exaclty or be compatible typeless formats"); + DEV_CHECK_ERR(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation"); + } + if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless) + { + DEV_CHECK_ERR(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN, + "Format of a resolve operation must not be unknown when both src and dst texture formats are typeless"); + } + if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless) + { + DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless, + "Format of a resolve operation must not be typeless when one of the texture formats is typeless"); + } +#endif +} + +#ifdef DEVELOPMENT +template +inline bool DeviceContextBase:: + DvpVerifyDrawArguments(const DrawAttribs& Attribs) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (m_pPipelineState->GetDesc().IsComputePipeline) + { + LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); + return false; + } + + if (Attribs.NumVertices == 0) + { + LOG_WARNING_MESSAGE("Draw command arguments are invalid: number of vertices to draw is zero."); + } + + return true; +} + +template +inline bool DeviceContextBase:: + DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (m_pPipelineState->GetDesc().IsComputePipeline) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); + return false; + } + + if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: IndexType (", + GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + return false; + } + + if (!m_pIndexBuffer) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound."); + return false; + } + + if (Attribs.NumIndices == 0) + { + LOG_WARNING_MESSAGE("DrawIndexed command arguments are invalid: number of indices to draw is zero."); + } + + return true; +} + +template +inline bool DeviceContextBase:: + DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (m_pPipelineState->GetDesc().IsComputePipeline) + { + + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); + return false; + } + + if (pAttribsBuffer != nullptr) + { + if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) + { + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer '", + pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + return false; + } + } + else + { + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer is null."); + return false; + } + + return true; +} + +template +inline bool DeviceContextBase:: + DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (m_pPipelineState->GetDesc().IsComputePipeline) + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is a compute pipeline."); + return false; + } + + if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: IndexType (", + GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + return false; + } + + if (!m_pIndexBuffer) + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound."); + return false; + } + + if (pAttribsBuffer != nullptr) + { + if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer '", + pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + return false; + } + } + else + { + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer is null."); + return false; + } + + return true; +} + +template +inline void DeviceContextBase:: + DvpVerifyRenderTargets() const +{ + if (!m_pPipelineState) + { + LOG_ERROR("No pipeline state is bound"); + return; + } + + TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN}; + TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN; + + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) + { + if (auto* pRT = m_pBoundRenderTargets[rt].RawPtr()) + BoundRTVFormats[rt] = pRT->GetDesc().Format; + else + BoundRTVFormats[rt] = TEX_FORMAT_UNKNOWN; + } + + BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; + + const auto& PSODesc = m_pPipelineState->GetDesc(); + const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; + if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) + { + LOG_WARNING_MESSAGE("Number of currently bound render targets (", m_NumBoundRenderTargets, + ") does not match the number of outputs specified by the PSO '", PSODesc.Name, + "' (", Uint32{GraphicsPipeline.NumRenderTargets}, ")."); + } + + if (BoundDSVFormat != GraphicsPipeline.DSVFormat) + { + LOG_WARNING_MESSAGE("Currently bound depth-stencil buffer format (", GetTextureFormatAttribs(BoundDSVFormat).Name, + ") does not match the DSV format specified by the PSO '", PSODesc.Name, + "' (", GetTextureFormatAttribs(GraphicsPipeline.DSVFormat).Name, ")."); + } + + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) + { + auto BoundFmt = BoundRTVFormats[rt]; + auto PSOFmt = GraphicsPipeline.RTVFormats[rt]; + if (BoundFmt != PSOFmt) + { + LOG_WARNING_MESSAGE("Render target bound to slot ", rt, " (", GetTextureFormatAttribs(BoundFmt).Name, + ") does not match the RTV format specified by the PSO '", PSODesc.Name, + "' (", GetTextureFormatAttribs(PSOFmt).Name, ")."); + } + } +} + + + +template +inline bool DeviceContextBase:: + DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const +{ + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DispatchCompute command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (!m_pPipelineState->GetDesc().IsComputePipeline) + { + LOG_ERROR_MESSAGE("DispatchCompute command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, + "' is a graphics pipeline."); + return false; + } + + if (Attribs.ThreadGroupCountX == 0) + LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero."); + + if (Attribs.ThreadGroupCountY == 0) + LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountY is zero."); + + if (Attribs.ThreadGroupCountZ == 0) + LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountZ is zero."); + + return true; +} + +template +inline bool DeviceContextBase:: + DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +{ + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (!m_pPipelineState->GetDesc().IsComputePipeline) + { + LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is a graphics pipeline."); + return false; + } + + if (pAttribsBuffer != nullptr) + { + if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) + { + LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer '", + pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + return false; + } + } + else + { + LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer is null."); + return false; + } + + return true; +} + + +template +void DeviceContextBase:: + DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const +{ + DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null"); + DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + if (Barrier.pTexture) + { + const auto& TexDesc = Barrier.pTexture->GetDesc(); + + DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'"); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState(); + DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, + "The state of texture '", TexDesc.Name, + "' is unknown to the engine and is not explicitly specified in the barrier"); + DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'"); + + DEV_CHECK_ERR(Barrier.FirstMipLevel < TexDesc.MipLevels, "First mip level (", Barrier.FirstMipLevel, + ") specified by the barrier is out of range. Texture '", + TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); + DEV_CHECK_ERR(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels, + "Mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1, + " specified by the barrier is out of range. Texture '", + TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); + + DEV_CHECK_ERR(Barrier.FirstArraySlice < TexDesc.ArraySize, "First array slice (", Barrier.FirstArraySlice, + ") specified by the barrier is out of range. Array size of texture '", + TexDesc.Name, "' is ", TexDesc.ArraySize); + DEV_CHECK_ERR(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize, + "Array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1, + " specified by the barrier is out of range. Array size of texture '", + TexDesc.Name, "' is ", TexDesc.ArraySize); + + auto DevType = m_pDevice->GetDeviceCaps().DevType; + if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN) + { + DEV_CHECK_ERR(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels), + "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); + DEV_CHECK_ERR(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize), + "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); + } + } + else + { + const auto& BuffDesc = Barrier.pBuffer->GetDesc(); + DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState(); + DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); + } + + if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) + { + DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE"); + } + + if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN) + { + DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier"); + } +} + +template +bool DeviceContextBase:: + DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const +{ + if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState)) + { + LOG_ERROR_MESSAGE(OperationName, " requires texture '", Texture.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), + " state. Actual texture state: ", GetResourceStateString(Texture.GetState()), + ". Use appropriate state transiton flags or explicitly transition the texture using IDeviceContext::TransitionResourceStates() method."); + return false; + } + + return true; +} + +template +bool DeviceContextBase:: + DvpVerifyBufferState(const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const +{ + if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState)) + { + LOG_ERROR_MESSAGE(OperationName, " requires buffer '", Buffer.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), + " state. Actual buffer state: ", GetResourceStateString(Buffer.GetState()), + ". Use appropriate state transiton flags or explicitly transition the buffer using IDeviceContext::TransitionResourceStates() method."); + return false; + } + + return true; +} + +#endif // DEVELOPMENT + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceObjectBase.h b/Graphics/GraphicsEngine/include/DeviceObjectBase.h deleted file mode 100644 index 31a00f40..00000000 --- a/Graphics/GraphicsEngine/include/DeviceObjectBase.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2019-2020 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::DeviceObjectBase template class - -#include -#include -#include "RefCntAutoPtr.h" -#include "ObjectBase.h" -#include "UniqueIdentifier.h" -#include "EngineMemory.h" - -namespace Diligent -{ - -/// Template class implementing base functionality for a device object -template -class DeviceObjectBase : public ObjectBase -{ -public: - typedef ObjectBase TBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this device object - /// \param pDevice - pointer to the render device. - /// \param ObjDesc - object description. - /// \param bIsDeviceInternal - flag indicating if the object is an internal device object - /// and must not keep a strong reference to the device. - DeviceObjectBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const ObjectDescType& ObjDesc, - bool bIsDeviceInternal = false) : - // clang-format off - TBase {pRefCounters}, - m_pDevice {pDevice }, - m_Desc {ObjDesc }, - m_bIsDeviceInternal{bIsDeviceInternal} - //clang-format on - { - // Do not keep strong reference to the device if the object is an internal device object - if (!m_bIsDeviceInternal) - { - m_pDevice->AddRef(); - } - - if (ObjDesc.Name != nullptr) - { - auto size = strlen(ObjDesc.Name) + 1; - auto* NameCopy = ALLOCATE(GetStringAllocator(), "Object name copy", char, size); - memcpy(NameCopy, ObjDesc.Name, size); - m_Desc.Name = NameCopy; - } - else - { - size_t size = 16 + 2 + 1; // 0x12345678 - auto* AddressStr = ALLOCATE(GetStringAllocator(), "Object address string", char, size); - snprintf(AddressStr, size, "0x%llX", static_cast(reinterpret_cast(this))); - m_Desc.Name = AddressStr; - } - - // !!!WARNING!!! - // We cannot add resource to the hash table from here, because the object - // has not been completely created yet and the reference counters object - // is not initialized! - //m_pDevice->AddResourceToHash( this ); - ERROR! - } - - // clang-format off - DeviceObjectBase (const DeviceObjectBase& ) = delete; - DeviceObjectBase ( DeviceObjectBase&&) = delete; - DeviceObjectBase& operator = (const DeviceObjectBase& ) = delete; - DeviceObjectBase& operator = ( DeviceObjectBase&&) = delete; - // clang-format on - - virtual ~DeviceObjectBase() - { - FREE(GetStringAllocator(), const_cast(m_Desc.Name)); - - if (!m_bIsDeviceInternal) - { - m_pDevice->Release(); - } - } - - inline virtual Atomics::Long Release() override final - { - // Render device owns allocators for all types of device objects, - // so it must be destroyed after all device objects are released. - // Consider the following scenario: an object A owns the last strong - // reference to the device: - // - // 1. A::~A() completes - // 2. A::~DeviceObjectBase() completes - // 3. A::m_pDevice is released - // Render device is destroyed, all allocators are invalid - // 4. RefCountersImpl::ObjectWrapperBase::DestroyObject() calls - // m_pAllocator->Free(m_pObject) - crash! - - RefCntAutoPtr pDevice; - return TBase::Release( - [&]() // - { - // We must keep the device alive while the object is being destroyed - // Note that internal device objects do not keep strong reference to the device - if (!m_bIsDeviceInternal) - { - pDevice = m_pDevice; - } - }); - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceObject, TBase) - - virtual const ObjectDescType& GetDesc() const override final - { - return m_Desc; - } - - /// Returns unique identifier - virtual Int32 GetUniqueID() const override final - { - /// \note - /// This unique ID is used to unambiguously identify device object for - /// tracking purposes. - /// Niether GL handle nor pointer could be safely used for this purpose - /// as both GL reuses released handles and the OS reuses released pointers - return m_UniqueID.GetID(); - } - - static bool IsSameObject(DeviceObjectBase* pObj1, DeviceObjectBase* pObj2) - { - UniqueIdentifier Id1 = (pObj1 != nullptr) ? pObj1->GetUniqueID() : 0; - UniqueIdentifier Id2 = (pObj2 != nullptr) ? pObj2->GetUniqueID() : 0; - return Id1 == Id2; - } - - RenderDeviceImplType* GetDevice() const { return m_pDevice; } - -protected: - /// Pointer to the device - RenderDeviceImplType* const m_pDevice; - - /// Object description - ObjectDescType m_Desc; - - // Template argument is only used to separate counters for - // different groups of objects - UniqueIdHelper m_UniqueID; - const bool m_bIsDeviceInternal; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceObjectBase.hpp b/Graphics/GraphicsEngine/include/DeviceObjectBase.hpp new file mode 100644 index 00000000..31a00f40 --- /dev/null +++ b/Graphics/GraphicsEngine/include/DeviceObjectBase.hpp @@ -0,0 +1,178 @@ +/* + * Copyright 2019-2020 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::DeviceObjectBase template class + +#include +#include +#include "RefCntAutoPtr.h" +#include "ObjectBase.h" +#include "UniqueIdentifier.h" +#include "EngineMemory.h" + +namespace Diligent +{ + +/// Template class implementing base functionality for a device object +template +class DeviceObjectBase : public ObjectBase +{ +public: + typedef ObjectBase TBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this device object + /// \param pDevice - pointer to the render device. + /// \param ObjDesc - object description. + /// \param bIsDeviceInternal - flag indicating if the object is an internal device object + /// and must not keep a strong reference to the device. + DeviceObjectBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const ObjectDescType& ObjDesc, + bool bIsDeviceInternal = false) : + // clang-format off + TBase {pRefCounters}, + m_pDevice {pDevice }, + m_Desc {ObjDesc }, + m_bIsDeviceInternal{bIsDeviceInternal} + //clang-format on + { + // Do not keep strong reference to the device if the object is an internal device object + if (!m_bIsDeviceInternal) + { + m_pDevice->AddRef(); + } + + if (ObjDesc.Name != nullptr) + { + auto size = strlen(ObjDesc.Name) + 1; + auto* NameCopy = ALLOCATE(GetStringAllocator(), "Object name copy", char, size); + memcpy(NameCopy, ObjDesc.Name, size); + m_Desc.Name = NameCopy; + } + else + { + size_t size = 16 + 2 + 1; // 0x12345678 + auto* AddressStr = ALLOCATE(GetStringAllocator(), "Object address string", char, size); + snprintf(AddressStr, size, "0x%llX", static_cast(reinterpret_cast(this))); + m_Desc.Name = AddressStr; + } + + // !!!WARNING!!! + // We cannot add resource to the hash table from here, because the object + // has not been completely created yet and the reference counters object + // is not initialized! + //m_pDevice->AddResourceToHash( this ); - ERROR! + } + + // clang-format off + DeviceObjectBase (const DeviceObjectBase& ) = delete; + DeviceObjectBase ( DeviceObjectBase&&) = delete; + DeviceObjectBase& operator = (const DeviceObjectBase& ) = delete; + DeviceObjectBase& operator = ( DeviceObjectBase&&) = delete; + // clang-format on + + virtual ~DeviceObjectBase() + { + FREE(GetStringAllocator(), const_cast(m_Desc.Name)); + + if (!m_bIsDeviceInternal) + { + m_pDevice->Release(); + } + } + + inline virtual Atomics::Long Release() override final + { + // Render device owns allocators for all types of device objects, + // so it must be destroyed after all device objects are released. + // Consider the following scenario: an object A owns the last strong + // reference to the device: + // + // 1. A::~A() completes + // 2. A::~DeviceObjectBase() completes + // 3. A::m_pDevice is released + // Render device is destroyed, all allocators are invalid + // 4. RefCountersImpl::ObjectWrapperBase::DestroyObject() calls + // m_pAllocator->Free(m_pObject) - crash! + + RefCntAutoPtr pDevice; + return TBase::Release( + [&]() // + { + // We must keep the device alive while the object is being destroyed + // Note that internal device objects do not keep strong reference to the device + if (!m_bIsDeviceInternal) + { + pDevice = m_pDevice; + } + }); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_DeviceObject, TBase) + + virtual const ObjectDescType& GetDesc() const override final + { + return m_Desc; + } + + /// Returns unique identifier + virtual Int32 GetUniqueID() const override final + { + /// \note + /// This unique ID is used to unambiguously identify device object for + /// tracking purposes. + /// Niether GL handle nor pointer could be safely used for this purpose + /// as both GL reuses released handles and the OS reuses released pointers + return m_UniqueID.GetID(); + } + + static bool IsSameObject(DeviceObjectBase* pObj1, DeviceObjectBase* pObj2) + { + UniqueIdentifier Id1 = (pObj1 != nullptr) ? pObj1->GetUniqueID() : 0; + UniqueIdentifier Id2 = (pObj2 != nullptr) ? pObj2->GetUniqueID() : 0; + return Id1 == Id2; + } + + RenderDeviceImplType* GetDevice() const { return m_pDevice; } + +protected: + /// Pointer to the device + RenderDeviceImplType* const m_pDevice; + + /// Object description + ObjectDescType m_Desc; + + // Template argument is only used to separate counters for + // different groups of objects + UniqueIdHelper m_UniqueID; + const bool m_bIsDeviceInternal; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/EngineFactoryBase.h b/Graphics/GraphicsEngine/include/EngineFactoryBase.h deleted file mode 100644 index 2e0b954c..00000000 --- a/Graphics/GraphicsEngine/include/EngineFactoryBase.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2019-2020 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::EngineFactoryBase template class - -#include "Object.h" -#include "EngineFactory.h" -#include "DefaultShaderSourceStreamFactory.h" - -namespace Diligent -{ - -const APIInfo& GetAPIInfo(); - -/// Template class implementing base functionality for an engine factory - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IEngineFactoryD3D11, Diligent::IEngineFactoryD3D12, -/// Diligent::IEngineFactoryVk or Diligent::IEngineFactoryOpenGL). -template -class EngineFactoryBase : public BaseInterface -{ -public: - EngineFactoryBase(const INTERFACE_ID& FactoryIID) noexcept : - // clang-format off - m_FactoryIID {FactoryIID}, - m_RefCounters {*this } - // clang-format on - { - } - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final - { - if (ppInterface == nullptr) - return; - - *ppInterface = nullptr; - if (IID == IID_Unknown || IID == m_FactoryIID || IID == IID_EngineFactory) - { - *ppInterface = this; - (*ppInterface)->AddRef(); - } - } - - virtual ReferenceCounterValueType AddRef() override final - { - return m_RefCounters.AddStrongRef(); - } - - virtual ReferenceCounterValueType Release() override final - { - return m_RefCounters.ReleaseStrongRef(); - } - - virtual IReferenceCounters* GetReferenceCounters() const override final - { - return const_cast(static_cast(&m_RefCounters)); - } - - virtual const APIInfo& GetAPIInfo() const override final - { - return Diligent::GetAPIInfo(); - } - - virtual void CreateDefaultShaderSourceStreamFactory(const Char* SearchDirectories, - IShaderSourceInputStreamFactory** ppShaderSourceFactory) const override final - { - Diligent::CreateDefaultShaderSourceStreamFactory(SearchDirectories, ppShaderSourceFactory); - } - -private: - class DummyReferenceCounters final : public IReferenceCounters - { - public: - DummyReferenceCounters(EngineFactoryBase& Factory) noexcept : - m_Factory{Factory} - { - m_lNumStrongReferences = 0; - m_lNumWeakReferences = 0; - } - - virtual ReferenceCounterValueType AddStrongRef() override final - { - return Atomics::AtomicIncrement(m_lNumStrongReferences); - } - - virtual ReferenceCounterValueType ReleaseStrongRef() override final - { - return Atomics::AtomicDecrement(m_lNumStrongReferences); - } - - virtual ReferenceCounterValueType AddWeakRef() override final - { - return Atomics::AtomicIncrement(m_lNumWeakReferences); - } - - virtual ReferenceCounterValueType ReleaseWeakRef() override final - { - return Atomics::AtomicDecrement(m_lNumWeakReferences); - } - - virtual void GetObject(IObject** ppObject) override final - { - if (ppObject != nullptr) - m_Factory.QueryInterface(IID_Unknown, ppObject); - } - - virtual ReferenceCounterValueType GetNumStrongRefs() const override final - { - return m_lNumStrongReferences; - } - - virtual ReferenceCounterValueType GetNumWeakRefs() const override final - { - return m_lNumWeakReferences; - } - - private: - EngineFactoryBase& m_Factory; - Atomics::AtomicLong m_lNumStrongReferences; - Atomics::AtomicLong m_lNumWeakReferences; - }; - - const INTERFACE_ID m_FactoryIID; - DummyReferenceCounters m_RefCounters; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/EngineFactoryBase.hpp b/Graphics/GraphicsEngine/include/EngineFactoryBase.hpp new file mode 100644 index 00000000..2e0b954c --- /dev/null +++ b/Graphics/GraphicsEngine/include/EngineFactoryBase.hpp @@ -0,0 +1,155 @@ +/* + * Copyright 2019-2020 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::EngineFactoryBase template class + +#include "Object.h" +#include "EngineFactory.h" +#include "DefaultShaderSourceStreamFactory.h" + +namespace Diligent +{ + +const APIInfo& GetAPIInfo(); + +/// Template class implementing base functionality for an engine factory + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IEngineFactoryD3D11, Diligent::IEngineFactoryD3D12, +/// Diligent::IEngineFactoryVk or Diligent::IEngineFactoryOpenGL). +template +class EngineFactoryBase : public BaseInterface +{ +public: + EngineFactoryBase(const INTERFACE_ID& FactoryIID) noexcept : + // clang-format off + m_FactoryIID {FactoryIID}, + m_RefCounters {*this } + // clang-format on + { + } + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final + { + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (IID == IID_Unknown || IID == m_FactoryIID || IID == IID_EngineFactory) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } + } + + virtual ReferenceCounterValueType AddRef() override final + { + return m_RefCounters.AddStrongRef(); + } + + virtual ReferenceCounterValueType Release() override final + { + return m_RefCounters.ReleaseStrongRef(); + } + + virtual IReferenceCounters* GetReferenceCounters() const override final + { + return const_cast(static_cast(&m_RefCounters)); + } + + virtual const APIInfo& GetAPIInfo() const override final + { + return Diligent::GetAPIInfo(); + } + + virtual void CreateDefaultShaderSourceStreamFactory(const Char* SearchDirectories, + IShaderSourceInputStreamFactory** ppShaderSourceFactory) const override final + { + Diligent::CreateDefaultShaderSourceStreamFactory(SearchDirectories, ppShaderSourceFactory); + } + +private: + class DummyReferenceCounters final : public IReferenceCounters + { + public: + DummyReferenceCounters(EngineFactoryBase& Factory) noexcept : + m_Factory{Factory} + { + m_lNumStrongReferences = 0; + m_lNumWeakReferences = 0; + } + + virtual ReferenceCounterValueType AddStrongRef() override final + { + return Atomics::AtomicIncrement(m_lNumStrongReferences); + } + + virtual ReferenceCounterValueType ReleaseStrongRef() override final + { + return Atomics::AtomicDecrement(m_lNumStrongReferences); + } + + virtual ReferenceCounterValueType AddWeakRef() override final + { + return Atomics::AtomicIncrement(m_lNumWeakReferences); + } + + virtual ReferenceCounterValueType ReleaseWeakRef() override final + { + return Atomics::AtomicDecrement(m_lNumWeakReferences); + } + + virtual void GetObject(IObject** ppObject) override final + { + if (ppObject != nullptr) + m_Factory.QueryInterface(IID_Unknown, ppObject); + } + + virtual ReferenceCounterValueType GetNumStrongRefs() const override final + { + return m_lNumStrongReferences; + } + + virtual ReferenceCounterValueType GetNumWeakRefs() const override final + { + return m_lNumWeakReferences; + } + + private: + EngineFactoryBase& m_Factory; + Atomics::AtomicLong m_lNumStrongReferences; + Atomics::AtomicLong m_lNumWeakReferences; + }; + + const INTERFACE_ID m_FactoryIID; + DummyReferenceCounters m_RefCounters; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/FenceBase.h b/Graphics/GraphicsEngine/include/FenceBase.h deleted file mode 100644 index 2fac4355..00000000 --- a/Graphics/GraphicsEngine/include/FenceBase.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019-2020 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::FenceBase template class - -#include "DeviceObjectBase.h" -#include "GraphicsTypes.h" -#include "RefCntAutoPtr.h" - -namespace Diligent -{ - -class IRenderDevice; -class IFence; - -/// Template class implementing base functionality for a Fence object - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IFenceD3D11, Diligent::IFenceD3D12, -/// Diligent::IFenceGL or Diligent::IFenceVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -template -class FenceBase : public DeviceObjectBase -{ -public: - typedef DeviceObjectBase TDeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this command list. - /// \param Desc - fence description - /// \param pDevice - pointer to the device. - /// \param bIsDeviceInternal - flag indicating if the Fence is an internal device object and - /// must not keep a strong reference to the device. - FenceBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const FenceDesc& Desc, bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} - {} - - ~FenceBase() - { - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Fence, TDeviceObjectBase) -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/FenceBase.hpp b/Graphics/GraphicsEngine/include/FenceBase.hpp new file mode 100644 index 00000000..b596e8c8 --- /dev/null +++ b/Graphics/GraphicsEngine/include/FenceBase.hpp @@ -0,0 +1,71 @@ +/* + * Copyright 2019-2020 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::FenceBase template class + +#include "DeviceObjectBase.hpp" +#include "GraphicsTypes.h" +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + +class IRenderDevice; +class IFence; + +/// Template class implementing base functionality for a Fence object + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IFenceD3D11, Diligent::IFenceD3D12, +/// Diligent::IFenceGL or Diligent::IFenceVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +template +class FenceBase : public DeviceObjectBase +{ +public: + typedef DeviceObjectBase TDeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this command list. + /// \param Desc - fence description + /// \param pDevice - pointer to the device. + /// \param bIsDeviceInternal - flag indicating if the Fence is an internal device object and + /// must not keep a strong reference to the device. + FenceBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const FenceDesc& Desc, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + {} + + ~FenceBase() + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Fence, TDeviceObjectBase) +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.h b/Graphics/GraphicsEngine/include/PipelineStateBase.h deleted file mode 100644 index fd3563a0..00000000 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2019-2020 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::PipelineStateBase template class - -#include -#include - -#include "PipelineState.h" -#include "DeviceObjectBase.h" -#include "STDAllocator.h" -#include "EngineMemory.h" -#include "GraphicsAccessories.hpp" -#include "StringPool.h" - -namespace Diligent -{ - -/// Template class implementing base functionality for a pipeline state object. - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IPipelineStateD3D11, Diligent::IPipelineStateD3D12, -/// Diligent::IPipelineStateGL or Diligent::IPipelineStateVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class PipelineStateBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this PSO - /// \param pDevice - pointer to the device. - /// \param PSODesc - pipeline state description. - /// \param bIsDeviceInternal - flag indicating if the blend state is an internal device object and - /// must not keep a strong reference to the device. - PipelineStateBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const PipelineStateDesc& PSODesc, - bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}, - m_NumShaders{0} - { - const auto& SrcLayout = PSODesc.ResourceLayout; - size_t StringPoolSize = 0; - if (SrcLayout.Variables != nullptr) - { - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1; - } - - if (SrcLayout.StaticSamplers != nullptr) - { - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1; - } - - if (!PSODesc.IsComputePipeline) - { - const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; - } - else - { - DEV_CHECK_ERR(PSODesc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements"); - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - auto& DstLayout = this->m_Desc.ResourceLayout; - if (SrcLayout.Variables != nullptr) - { - ShaderResourceVariableDesc* Variables = - ALLOCATE(GetRawAllocator(), "Memory for ShaderResourceVariableDesc array", ShaderResourceVariableDesc, SrcLayout.NumVariables); - DstLayout.Variables = Variables; - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - { - VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); - Variables[i] = SrcLayout.Variables[i]; - Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name); - } - } - - if (SrcLayout.StaticSamplers != nullptr) - { - StaticSamplerDesc* StaticSamplers = - ALLOCATE(GetRawAllocator(), "Memory for StaticSamplerDesc array", StaticSamplerDesc, SrcLayout.NumStaticSamplers); - DstLayout.StaticSamplers = StaticSamplers; - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - { - VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); -#ifdef DEVELOPMENT - const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; - if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || - (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || - (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) - { - LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (", - BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], - "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); - } -#endif - - StaticSamplers[i] = SrcLayout.StaticSamplers[i]; - StaticSamplers[i].SamplerOrTextureName = m_StringPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); - } - } - - - if (this->m_Desc.IsComputePipeline) - { - const auto& ComputePipeline = PSODesc.ComputePipeline; - if (ComputePipeline.pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is not provided"); - } - -#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ - if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ - { \ - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ - } - - VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute") - - m_pCS = ComputePipeline.pCS; - m_ppShaders[0] = ComputePipeline.pCS; - m_NumShaders = 1; - } - else - { - const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; - - VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain") -#undef VALIDATE_SHADER_TYPE - - m_pVS = GraphicsPipeline.pVS; - m_pPS = GraphicsPipeline.pPS; - m_pGS = GraphicsPipeline.pGS; - m_pDS = GraphicsPipeline.pDS; - m_pHS = GraphicsPipeline.pHS; - - if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS; - if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS; - if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS; - if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS; - if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS; - - DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State"); - - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) - { - auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; - if (RTVFmt != TEX_FORMAT_UNKNOWN) - { - LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, - " must be set to TEX_FORMAT_UNKNOWN"); - } - } - - const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; - LayoutElement* pLayoutElements = nullptr; - if (InputLayout.NumElements > 0) - { - pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements); - } - this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; - for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) - { - pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; - pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); - } - - - // Correct description and compute offsets and tight strides - std::array Strides, TightStrides = {}; - // Set all strides to an invalid value because an application may want to use 0 stride - for (auto& Stride : Strides) - Stride = LAYOUT_ELEMENT_AUTO_STRIDE; - - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - { - auto& LayoutElem = pLayoutElements[i]; - - if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16) - LayoutElem.IsNormalized = false; // Floating point values cannot be normalized - - auto BuffSlot = LayoutElem.BufferSlot; - if (BuffSlot >= Strides.size()) - { - UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); - continue; - } - m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1); - - auto& CurrAutoStride = TightStrides[BuffSlot]; - // If offset is not explicitly specified, use current auto stride value - if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET) - { - LayoutElem.RelativeOffset = CurrAutoStride; - } - - // If stride is explicitly specified, use it for the current buffer slot - if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE) - { - // Verify that the value is consistent with the previously specified stride, if any - if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride) - { - LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot, - ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ", - LayoutElem.Stride, ", while current value is ", Strides[BuffSlot], - ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow " - "the engine compute strides automatically."); - } - Strides[BuffSlot] = LayoutElem.Stride; - } - - CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType)); - } - - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - { - auto& LayoutElem = pLayoutElements[i]; - - auto BuffSlot = LayoutElem.BufferSlot; - // If no input elements explicitly specified stride for this buffer slot, use automatic stride - if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE) - { - Strides[BuffSlot] = TightStrides[BuffSlot]; - } - else - { - if (Strides[BuffSlot] < TightStrides[BuffSlot]) - { - LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, - " is smaller than the minimum stride ", TightStrides[BuffSlot], - " required to accomodate all input elements."); - } - } - if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE) - LayoutElem.Stride = Strides[BuffSlot]; - } - - if (m_BufferSlotsUsed > 0) - { - m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed); - - // Set strides for all unused slots to 0 - for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) - { - auto Stride = Strides[i]; - m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; - } - } - } - - VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); - - Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); - DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, - "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, - ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); - this->m_Desc.CommandQueueMask &= DeviceQueuesMask; - } - - ~PipelineStateBase() - { - /* - /// \note Destructor cannot directly remove the object from the registry as this may cause a - /// deadlock at the point where StateObjectsRegistry::Find() locks the weak pointer: if we - /// are in dtor, the object is locked by Diligent::RefCountedObject::Release() and - /// StateObjectsRegistry::Find() will wait for that lock to be released. - /// A the same time this thread will be waiting for the other thread to unlock the registry.\n - /// Thus destructor only notifies the registry that there is a deleted object. - /// The reference to the object will be removed later. - auto &PipelineStateRegistry = static_cast(this->GetDevice())->GetBSRegistry(); - auto &RasterizerStateRegistry = static_cast(this->GetDevice())->GetRSRegistry(); - auto &DSSRegistry = static_cast(this->GetDevice())->GetDSSRegistry(); - // StateObjectsRegistry::ReportDeletedObject() does not lock the registry, but only - // atomically increments the outstanding deleted objects counter. - PipelineStateRegistry.ReportDeletedObject(); - RasterizerStateRegistry.ReportDeletedObject(); - DSSRegistry.ReportDeletedObject(); - */ - - auto& RawAllocator = GetRawAllocator(); - if (this->m_Desc.ResourceLayout.Variables != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.Variables)); - if (this->m_Desc.ResourceLayout.StaticSamplers != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.StaticSamplers)); - if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements)); - if (m_pStrides != nullptr) - RawAllocator.Free(m_pStrides); - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) - - Uint32 GetBufferStride(Uint32 BufferSlot) const - { - return BufferSlot < m_BufferSlotsUsed ? m_pStrides[BufferSlot] : 0; - } - - Uint32 GetNumBufferSlotsUsed() const - { - return m_BufferSlotsUsed; - } - - IShader* GetVS() { return m_pVS; } - IShader* GetPS() { return m_pPS; } - IShader* GetGS() { return m_pGS; } - IShader* GetDS() { return m_pDS; } - IShader* GetHS() { return m_pHS; } - IShader* GetCS() { return m_pCS; } - - IShader* const* GetShaders() const { return m_ppShaders; } - Uint32 GetNumShaders() const { return m_NumShaders; } - - template - ShaderType* GetShader(Uint32 ShaderInd) - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return ValidatedCast(m_ppShaders[ShaderInd]); - } - template - ShaderType* GetShader(Uint32 ShaderInd) const - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return ValidatedCast(m_ppShaders[ShaderInd]); - } - - // This function only compares shader resource layout hashes, so - // it can potentially give false negatives - bool IsIncompatibleWith(const IPipelineState* pPSO) const - { - return m_ShaderResourceLayoutHash != ValidatedCast(pPSO)->m_ShaderResourceLayoutHash; - } - -protected: - Uint32 m_BufferSlotsUsed = 0; - Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses - Uint32* m_pStrides = nullptr; - - StringPool m_StringPool; - - RefCntAutoPtr m_pVS; ///< Strong reference to the vertex shader - RefCntAutoPtr m_pPS; ///< Strong reference to the pixel shader - RefCntAutoPtr m_pGS; ///< Strong reference to the geometry shader - RefCntAutoPtr m_pDS; ///< Strong reference to the domain shader - RefCntAutoPtr m_pHS; ///< Strong reference to the hull shader - RefCntAutoPtr m_pCS; ///< Strong reference to the compute shader - - IShader* m_ppShaders[5] = {}; ///< Array of pointers to the shaders used by this PSO - size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp new file mode 100644 index 00000000..5dddbaea --- /dev/null +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -0,0 +1,390 @@ +/* + * Copyright 2019-2020 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::PipelineStateBase template class + +#include +#include + +#include "PipelineState.h" +#include "DeviceObjectBase.hpp" +#include "STDAllocator.h" +#include "EngineMemory.h" +#include "GraphicsAccessories.hpp" +#include "StringPool.h" + +namespace Diligent +{ + +/// Template class implementing base functionality for a pipeline state object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IPipelineStateD3D11, Diligent::IPipelineStateD3D12, +/// Diligent::IPipelineStateGL or Diligent::IPipelineStateVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class PipelineStateBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this PSO + /// \param pDevice - pointer to the device. + /// \param PSODesc - pipeline state description. + /// \param bIsDeviceInternal - flag indicating if the blend state is an internal device object and + /// must not keep a strong reference to the device. + PipelineStateBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const PipelineStateDesc& PSODesc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}, + m_NumShaders{0} + { + const auto& SrcLayout = PSODesc.ResourceLayout; + size_t StringPoolSize = 0; + if (SrcLayout.Variables != nullptr) + { + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1; + } + + if (SrcLayout.StaticSamplers != nullptr) + { + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1; + } + + if (!PSODesc.IsComputePipeline) + { + const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; + } + else + { + DEV_CHECK_ERR(PSODesc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements"); + } + + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + + auto& DstLayout = this->m_Desc.ResourceLayout; + if (SrcLayout.Variables != nullptr) + { + ShaderResourceVariableDesc* Variables = + ALLOCATE(GetRawAllocator(), "Memory for ShaderResourceVariableDesc array", ShaderResourceVariableDesc, SrcLayout.NumVariables); + DstLayout.Variables = Variables; + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); + Variables[i] = SrcLayout.Variables[i]; + Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name); + } + } + + if (SrcLayout.StaticSamplers != nullptr) + { + StaticSamplerDesc* StaticSamplers = + ALLOCATE(GetRawAllocator(), "Memory for StaticSamplerDesc array", StaticSamplerDesc, SrcLayout.NumStaticSamplers); + DstLayout.StaticSamplers = StaticSamplers; + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { + VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); +#ifdef DEVELOPMENT + const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; + if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || + (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || + (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) + { + LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (", + BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], + "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); + } +#endif + + StaticSamplers[i] = SrcLayout.StaticSamplers[i]; + StaticSamplers[i].SamplerOrTextureName = m_StringPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); + } + } + + + if (this->m_Desc.IsComputePipeline) + { + const auto& ComputePipeline = PSODesc.ComputePipeline; + if (ComputePipeline.pCS == nullptr) + { + LOG_ERROR_AND_THROW("Compute shader is not provided"); + } + +#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ + if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ + { \ + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ + } + + VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute") + + m_pCS = ComputePipeline.pCS; + m_ppShaders[0] = ComputePipeline.pCS; + m_NumShaders = 1; + } + else + { + const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; + + VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain") +#undef VALIDATE_SHADER_TYPE + + m_pVS = GraphicsPipeline.pVS; + m_pPS = GraphicsPipeline.pPS; + m_pGS = GraphicsPipeline.pGS; + m_pDS = GraphicsPipeline.pDS; + m_pHS = GraphicsPipeline.pHS; + + if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS; + if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS; + if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS; + if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS; + if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS; + + DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State"); + + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) + { + auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; + if (RTVFmt != TEX_FORMAT_UNKNOWN) + { + LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, + " must be set to TEX_FORMAT_UNKNOWN"); + } + } + + const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; + LayoutElement* pLayoutElements = nullptr; + if (InputLayout.NumElements > 0) + { + pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements); + } + this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; + for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) + { + pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; + pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); + } + + + // Correct description and compute offsets and tight strides + std::array Strides, TightStrides = {}; + // Set all strides to an invalid value because an application may want to use 0 stride + for (auto& Stride : Strides) + Stride = LAYOUT_ELEMENT_AUTO_STRIDE; + + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + { + auto& LayoutElem = pLayoutElements[i]; + + if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16) + LayoutElem.IsNormalized = false; // Floating point values cannot be normalized + + auto BuffSlot = LayoutElem.BufferSlot; + if (BuffSlot >= Strides.size()) + { + UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); + continue; + } + m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1); + + auto& CurrAutoStride = TightStrides[BuffSlot]; + // If offset is not explicitly specified, use current auto stride value + if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET) + { + LayoutElem.RelativeOffset = CurrAutoStride; + } + + // If stride is explicitly specified, use it for the current buffer slot + if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE) + { + // Verify that the value is consistent with the previously specified stride, if any + if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride) + { + LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot, + ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ", + LayoutElem.Stride, ", while current value is ", Strides[BuffSlot], + ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow " + "the engine compute strides automatically."); + } + Strides[BuffSlot] = LayoutElem.Stride; + } + + CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType)); + } + + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + { + auto& LayoutElem = pLayoutElements[i]; + + auto BuffSlot = LayoutElem.BufferSlot; + // If no input elements explicitly specified stride for this buffer slot, use automatic stride + if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE) + { + Strides[BuffSlot] = TightStrides[BuffSlot]; + } + else + { + if (Strides[BuffSlot] < TightStrides[BuffSlot]) + { + LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, + " is smaller than the minimum stride ", TightStrides[BuffSlot], + " required to accomodate all input elements."); + } + } + if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE) + LayoutElem.Stride = Strides[BuffSlot]; + } + + if (m_BufferSlotsUsed > 0) + { + m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed); + + // Set strides for all unused slots to 0 + for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) + { + auto Stride = Strides[i]; + m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; + } + } + } + + VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); + + Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); + DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, + "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, + ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); + this->m_Desc.CommandQueueMask &= DeviceQueuesMask; + } + + ~PipelineStateBase() + { + /* + /// \note Destructor cannot directly remove the object from the registry as this may cause a + /// deadlock at the point where StateObjectsRegistry::Find() locks the weak pointer: if we + /// are in dtor, the object is locked by Diligent::RefCountedObject::Release() and + /// StateObjectsRegistry::Find() will wait for that lock to be released. + /// A the same time this thread will be waiting for the other thread to unlock the registry.\n + /// Thus destructor only notifies the registry that there is a deleted object. + /// The reference to the object will be removed later. + auto &PipelineStateRegistry = static_cast(this->GetDevice())->GetBSRegistry(); + auto &RasterizerStateRegistry = static_cast(this->GetDevice())->GetRSRegistry(); + auto &DSSRegistry = static_cast(this->GetDevice())->GetDSSRegistry(); + // StateObjectsRegistry::ReportDeletedObject() does not lock the registry, but only + // atomically increments the outstanding deleted objects counter. + PipelineStateRegistry.ReportDeletedObject(); + RasterizerStateRegistry.ReportDeletedObject(); + DSSRegistry.ReportDeletedObject(); + */ + + auto& RawAllocator = GetRawAllocator(); + if (this->m_Desc.ResourceLayout.Variables != nullptr) + RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.Variables)); + if (this->m_Desc.ResourceLayout.StaticSamplers != nullptr) + RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.StaticSamplers)); + if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr) + RawAllocator.Free(const_cast(this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements)); + if (m_pStrides != nullptr) + RawAllocator.Free(m_pStrides); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) + + Uint32 GetBufferStride(Uint32 BufferSlot) const + { + return BufferSlot < m_BufferSlotsUsed ? m_pStrides[BufferSlot] : 0; + } + + Uint32 GetNumBufferSlotsUsed() const + { + return m_BufferSlotsUsed; + } + + IShader* GetVS() { return m_pVS; } + IShader* GetPS() { return m_pPS; } + IShader* GetGS() { return m_pGS; } + IShader* GetDS() { return m_pDS; } + IShader* GetHS() { return m_pHS; } + IShader* GetCS() { return m_pCS; } + + IShader* const* GetShaders() const { return m_ppShaders; } + Uint32 GetNumShaders() const { return m_NumShaders; } + + template + ShaderType* GetShader(Uint32 ShaderInd) + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return ValidatedCast(m_ppShaders[ShaderInd]); + } + template + ShaderType* GetShader(Uint32 ShaderInd) const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return ValidatedCast(m_ppShaders[ShaderInd]); + } + + // This function only compares shader resource layout hashes, so + // it can potentially give false negatives + bool IsIncompatibleWith(const IPipelineState* pPSO) const + { + return m_ShaderResourceLayoutHash != ValidatedCast(pPSO)->m_ShaderResourceLayoutHash; + } + +protected: + Uint32 m_BufferSlotsUsed = 0; + Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses + Uint32* m_pStrides = nullptr; + + StringPool m_StringPool; + + RefCntAutoPtr m_pVS; ///< Strong reference to the vertex shader + RefCntAutoPtr m_pPS; ///< Strong reference to the pixel shader + RefCntAutoPtr m_pGS; ///< Strong reference to the geometry shader + RefCntAutoPtr m_pDS; ///< Strong reference to the domain shader + RefCntAutoPtr m_pHS; ///< Strong reference to the hull shader + RefCntAutoPtr m_pCS; ///< Strong reference to the compute shader + + IShader* m_ppShaders[5] = {}; ///< Array of pointers to the shaders used by this PSO + size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/QueryBase.h b/Graphics/GraphicsEngine/include/QueryBase.h deleted file mode 100644 index daa0d30e..00000000 --- a/Graphics/GraphicsEngine/include/QueryBase.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2019-2020 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 Diligent::QueryBase template class - -#include "Query.h" -#include "DeviceObjectBase.h" -#include "GraphicsTypes.h" -#include "RefCntAutoPtr.h" - -namespace Diligent -{ - -class IDeviceContext; - -/// Template class implementing base functionality for a Query object - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IQueryD3D11, Diligent::IQueryD3D12, -/// Diligent::IQueryGL or Diligent::IQueryVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -template -class QueryBase : public DeviceObjectBase -{ -public: - enum class QueryState - { - Inactive, - Querying, - Complete - }; - - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this command list. - /// \param pDevice - pointer to the device. - /// \param Desc - Query description - /// \param bIsDeviceInternal - flag indicating if the Query is an internal device object and - /// must not keep a strong reference to the device. - QueryBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const QueryDesc& Desc, - bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} - { - const auto& deviceFeatures = pDevice->GetDeviceCaps().Features; - switch (Desc.Type) - { - case QUERY_TYPE_OCCLUSION: - if (!deviceFeatures.OcclusionQueries) - LOG_ERROR_AND_THROW("Occlusion queries are not supported by this device"); - break; - - case QUERY_TYPE_BINARY_OCCLUSION: - if (!deviceFeatures.BinaryOcclusionQueries) - LOG_ERROR_AND_THROW("Binary occlusion queries are not supported by this device"); - break; - - case QUERY_TYPE_TIMESTAMP: - if (!deviceFeatures.TimestampQueries) - LOG_ERROR_AND_THROW("Timestamp queries are not supported by this device"); - break; - - case QUERY_TYPE_PIPELINE_STATISTICS: - if (!deviceFeatures.PipelineStatisticsQueries) - LOG_ERROR_AND_THROW("Pipeline statistics queries are not supported by this device"); - break; - - default: - UNEXPECTED("Unexpected device type"); - } - } - - ~QueryBase() - { - if (m_State == QueryState::Querying) - { - LOG_ERROR_MESSAGE("Destroying query '", this->m_Desc.Name, - "' that is in querying state. End the query before releasing it."); - } - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Query, TDeviceObjectBase) - - virtual void Invalidate() override - { - m_State = QueryState::Inactive; - } - - bool OnBeginQuery(IDeviceContext* pContext) - { - if (this->m_Desc.Type == QUERY_TYPE_TIMESTAMP) - { - LOG_ERROR_MESSAGE("BeginQuery cannot be called on timestamp query '", this->m_Desc.Name, - "'. Call EndQuery to set the timestamp."); - return false; - } - - if (m_State == QueryState::Querying) - { - LOG_ERROR_MESSAGE("Attempting to begin query '", this->m_Desc.Name, - "' twice. A query must be ended before it can be begun again."); - return false; - } - - m_pContext = pContext; - m_State = QueryState::Querying; - return true; - } - - bool OnEndQuery(IDeviceContext* pContext) - { - if (this->m_Desc.Type != QUERY_TYPE_TIMESTAMP) - { - if (m_State != QueryState::Querying) - { - LOG_ERROR_MESSAGE("Attempting to end query '", this->m_Desc.Name, "' that has not been begun"); - return false; - } - } - - if (m_pContext == nullptr) - { - if (this->m_Desc.Type != QUERY_TYPE_TIMESTAMP) - { - LOG_ERROR_MESSAGE("Ending query '", this->m_Desc.Name, "' that has not been begun"); - return false; - } - - m_pContext = pContext; - } - else if (m_pContext != pContext) - { - LOG_ERROR_MESSAGE("Query '", this->m_Desc.Name, "' has been begun by another context"); - return false; - } - - m_State = QueryState::Complete; - return true; - } - - QueryState GetState() const - { - return m_State; - } - - bool CheckQueryDataPtr(void* pData, Uint32 DataSize) - { - if (m_State != QueryState::Complete) - { - LOG_ERROR_MESSAGE("Attempting to get data of query '", this->m_Desc.Name, "' that has not been ended"); - return false; - } - - if (pData != nullptr) - { - if (*reinterpret_cast(pData) != this->m_Desc.Type) - { - LOG_ERROR_MESSAGE("Incorrect query data structure type."); - return false; - } - - switch (this->m_Desc.Type) - { - case QUERY_TYPE_UNDEFINED: - UNEXPECTED("Undefined query type is unexpected"); - return false; - - case QUERY_TYPE_OCCLUSION: - if (DataSize != sizeof(QueryDataOcclusion)) - { - LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataOcclusion), " (aka sizeof(QueryDataOcclusion)) is expected"); - return false; - } - break; - - case QUERY_TYPE_BINARY_OCCLUSION: - if (DataSize != sizeof(QueryDataBinaryOcclusion)) - { - LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataBinaryOcclusion), " (aka sizeof(QueryDataBinaryOcclusion)) is expected"); - return false; - } - break; - - case QUERY_TYPE_TIMESTAMP: - if (DataSize != sizeof(QueryDataTimestamp)) - { - LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataTimestamp), " (aka sizeof(QueryDataTimestamp)) is expected"); - return false; - } - break; - - case QUERY_TYPE_PIPELINE_STATISTICS: - if (DataSize != sizeof(QueryDataPipelineStatistics)) - { - LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataPipelineStatistics), " (aka sizeof(QueryDataPipelineStatistics)) is expected"); - return false; - } - break; - - default: - UNEXPECTED("Unexpected query type"); - return false; - } - } - - return true; - } - -protected: - RefCntAutoPtr m_pContext; - - QueryState m_State = QueryState::Inactive; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/QueryBase.hpp b/Graphics/GraphicsEngine/include/QueryBase.hpp new file mode 100644 index 00000000..91e5f034 --- /dev/null +++ b/Graphics/GraphicsEngine/include/QueryBase.hpp @@ -0,0 +1,243 @@ +/* + * Copyright 2019-2020 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 Diligent::QueryBase template class + +#include "Query.h" +#include "DeviceObjectBase.hpp" +#include "GraphicsTypes.h" +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + +class IDeviceContext; + +/// Template class implementing base functionality for a Query object + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IQueryD3D11, Diligent::IQueryD3D12, +/// Diligent::IQueryGL or Diligent::IQueryVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +template +class QueryBase : public DeviceObjectBase +{ +public: + enum class QueryState + { + Inactive, + Querying, + Complete + }; + + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this command list. + /// \param pDevice - pointer to the device. + /// \param Desc - Query description + /// \param bIsDeviceInternal - flag indicating if the Query is an internal device object and + /// must not keep a strong reference to the device. + QueryBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const QueryDesc& Desc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + { + const auto& deviceFeatures = pDevice->GetDeviceCaps().Features; + switch (Desc.Type) + { + case QUERY_TYPE_OCCLUSION: + if (!deviceFeatures.OcclusionQueries) + LOG_ERROR_AND_THROW("Occlusion queries are not supported by this device"); + break; + + case QUERY_TYPE_BINARY_OCCLUSION: + if (!deviceFeatures.BinaryOcclusionQueries) + LOG_ERROR_AND_THROW("Binary occlusion queries are not supported by this device"); + break; + + case QUERY_TYPE_TIMESTAMP: + if (!deviceFeatures.TimestampQueries) + LOG_ERROR_AND_THROW("Timestamp queries are not supported by this device"); + break; + + case QUERY_TYPE_PIPELINE_STATISTICS: + if (!deviceFeatures.PipelineStatisticsQueries) + LOG_ERROR_AND_THROW("Pipeline statistics queries are not supported by this device"); + break; + + default: + UNEXPECTED("Unexpected device type"); + } + } + + ~QueryBase() + { + if (m_State == QueryState::Querying) + { + LOG_ERROR_MESSAGE("Destroying query '", this->m_Desc.Name, + "' that is in querying state. End the query before releasing it."); + } + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Query, TDeviceObjectBase) + + virtual void Invalidate() override + { + m_State = QueryState::Inactive; + } + + bool OnBeginQuery(IDeviceContext* pContext) + { + if (this->m_Desc.Type == QUERY_TYPE_TIMESTAMP) + { + LOG_ERROR_MESSAGE("BeginQuery cannot be called on timestamp query '", this->m_Desc.Name, + "'. Call EndQuery to set the timestamp."); + return false; + } + + if (m_State == QueryState::Querying) + { + LOG_ERROR_MESSAGE("Attempting to begin query '", this->m_Desc.Name, + "' twice. A query must be ended before it can be begun again."); + return false; + } + + m_pContext = pContext; + m_State = QueryState::Querying; + return true; + } + + bool OnEndQuery(IDeviceContext* pContext) + { + if (this->m_Desc.Type != QUERY_TYPE_TIMESTAMP) + { + if (m_State != QueryState::Querying) + { + LOG_ERROR_MESSAGE("Attempting to end query '", this->m_Desc.Name, "' that has not been begun"); + return false; + } + } + + if (m_pContext == nullptr) + { + if (this->m_Desc.Type != QUERY_TYPE_TIMESTAMP) + { + LOG_ERROR_MESSAGE("Ending query '", this->m_Desc.Name, "' that has not been begun"); + return false; + } + + m_pContext = pContext; + } + else if (m_pContext != pContext) + { + LOG_ERROR_MESSAGE("Query '", this->m_Desc.Name, "' has been begun by another context"); + return false; + } + + m_State = QueryState::Complete; + return true; + } + + QueryState GetState() const + { + return m_State; + } + + bool CheckQueryDataPtr(void* pData, Uint32 DataSize) + { + if (m_State != QueryState::Complete) + { + LOG_ERROR_MESSAGE("Attempting to get data of query '", this->m_Desc.Name, "' that has not been ended"); + return false; + } + + if (pData != nullptr) + { + if (*reinterpret_cast(pData) != this->m_Desc.Type) + { + LOG_ERROR_MESSAGE("Incorrect query data structure type."); + return false; + } + + switch (this->m_Desc.Type) + { + case QUERY_TYPE_UNDEFINED: + UNEXPECTED("Undefined query type is unexpected"); + return false; + + case QUERY_TYPE_OCCLUSION: + if (DataSize != sizeof(QueryDataOcclusion)) + { + LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataOcclusion), " (aka sizeof(QueryDataOcclusion)) is expected"); + return false; + } + break; + + case QUERY_TYPE_BINARY_OCCLUSION: + if (DataSize != sizeof(QueryDataBinaryOcclusion)) + { + LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataBinaryOcclusion), " (aka sizeof(QueryDataBinaryOcclusion)) is expected"); + return false; + } + break; + + case QUERY_TYPE_TIMESTAMP: + if (DataSize != sizeof(QueryDataTimestamp)) + { + LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataTimestamp), " (aka sizeof(QueryDataTimestamp)) is expected"); + return false; + } + break; + + case QUERY_TYPE_PIPELINE_STATISTICS: + if (DataSize != sizeof(QueryDataPipelineStatistics)) + { + LOG_ERROR_MESSAGE("The size of query data (", DataSize, ") is incorrect: ", sizeof(QueryDataPipelineStatistics), " (aka sizeof(QueryDataPipelineStatistics)) is expected"); + return false; + } + break; + + default: + UNEXPECTED("Unexpected query type"); + return false; + } + } + + return true; + } + +protected: + RefCntAutoPtr m_pContext; + + QueryState m_State = QueryState::Inactive; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/RenderDeviceBase.h b/Graphics/GraphicsEngine/include/RenderDeviceBase.h deleted file mode 100644 index 68ab63a6..00000000 --- a/Graphics/GraphicsEngine/include/RenderDeviceBase.h +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright 2019-2020 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.h" -#include "Defines.h" -#include "ResourceMappingImpl.h" -#include "StateObjectsRegistry.h" -#include "HashUtils.h" -#include "ObjectBase.h" -#include "DeviceContext.h" -#include "SwapChain.h" -#include "GraphicsAccessories.hpp" -#include "FixedBlockMemoryAllocator.h" -#include "EngineMemory.h" -#include "STDAllocator.h" - -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 (int 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 BaseInterface - base interface that this class will inheret. -/// \warning -/// Render device must *NOT* hold strong references to any -/// object it creates to avoid circular 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 TObjectBase = ObjectBase; - - /// Describes the sizes of device objects - struct DeviceObjectSizes - { - /// Size of the texture object (TextureD3D12Impl, TextureVkImpl, etc.), in bytes - const size_t TextureObjSize; - - /// Size of the texture view object (TextureViewD3D12Impl, TextureViewVkImpl, etc.), in bytes - const size_t TexViewObjSize; - - /// Size of the buffer object (BufferD3D12Impl, BufferVkImpl, etc.), in bytes - const size_t BufferObjSize; - - /// Size of the buffer view object (BufferViewD3D12Impl, BufferViewVkImpl, etc.), in bytes - const size_t BuffViewObjSize; - - /// Size of the shader object (ShaderD3D12Impl, ShaderVkImpl, etc.), in bytes - const size_t ShaderObjSize; - - /// Size of the sampler object (SamplerD3D12Impl, SamplerVkImpl, etc.), in bytes - const size_t SamplerObjSize; - - /// Size of the pipeline state object (PipelineStateD3D12Impl, PipelineStateVkImpl, etc.), in bytes - const size_t PSOSize; - - /// Size of the shader resource binding object (ShaderResourceBindingD3D12Impl, ShaderResourceBindingVkImpl, etc.), in bytes - const size_t SRBSize; - - /// Size of the fence object (FenceD3D12Impl, FenceVkImpl, etc.), in bytes - const size_t FenceSize; - - /// Size of the query object (QueryD3D12Impl, QueryVkImpl, etc.), in bytes - const size_t QuerySize; - }; - - /// \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 - number of deferred device contexts - /// \param ObjectSizes - device object sizes - /// - /// \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, - const DeviceObjectSizes& ObjectSizes) : - // 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, ObjectSizes.TextureObjSize, 64 }, - m_TexViewObjAllocator {RawMemAllocator, ObjectSizes.TexViewObjSize, 64 }, - m_BufObjAllocator {RawMemAllocator, ObjectSizes.BufferObjSize, 128 }, - m_BuffViewObjAllocator {RawMemAllocator, ObjectSizes.BuffViewObjSize, 128 }, - m_ShaderObjAllocator {RawMemAllocator, ObjectSizes.ShaderObjSize, 32 }, - m_SamplerObjAllocator {RawMemAllocator, ObjectSizes.SamplerObjSize, 32 }, - m_PSOAllocator {RawMemAllocator, ObjectSizes.PSOSize, 128 }, - m_SRBAllocator {RawMemAllocator, ObjectSizes.SRBSize, 1024}, - m_ResMappingAllocator {RawMemAllocator, sizeof(ResourceMappingImpl), 16 }, - m_FenceAllocator {RawMemAllocator, ObjectSizes.FenceSize, 16 }, - m_QueryAllocator {RawMemAllocator, ObjectSizes.QuerySize, 16 } - // 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 Release() override final - { - return TObjectBase::Release(); - } - - /// Implementation of IRenderDevice::CreateResourceMapping(). - virtual void CreateResourceMapping(const ResourceMappingDesc& MappingDesc, IResourceMapping** ppMapping) override final; - - /// Implementation of IRenderDevice::GetDeviceCaps(). - virtual const DeviceCaps& GetDeviceCaps() const override final - { - return m_DeviceCaps; - } - - /// Implementation of IRenderDevice::GetTextureFormatInfo(). - virtual const TextureFormatInfo& 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& 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* GetEngineFactory() const override final - { - return m_pEngineFactory.RawPtr(); - } - - void OnCreateDeviceObject(IDeviceObject* pNewObject) - { - } - - 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 - template - void CreateDeviceObject(const Char* ObjectTypeName, const TObjectDescType& Desc, TObjectType** ppObject, TObjectConstructor ConstructObject); - - RefCntAutoPtr m_pEngineFactory; - - DeviceCaps m_DeviceCaps; - - // 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 -}; - - -template -void RenderDeviceBase::CreateResourceMapping(const ResourceMappingDesc& MappingDesc, IResourceMapping** ppMapping) -{ - VERIFY(ppMapping != nullptr, "Null pointer provided"); - if (ppMapping == nullptr) - return; - VERIFY(*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); - } - } -} - - -/// \tparam TObjectType - type of the object being created (IBuffer, ITexture, etc.) -/// \tparam TObjectDescType - type of the object description structure (BufferDesc, TextureDesc, etc.) -/// \tparam TObjectConstructor - 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 -template -void RenderDeviceBase::CreateDeviceObject(const Char* ObjectTypeName, const TObjectDescType& Desc, TObjectType** ppObject, TObjectConstructor ConstructObject) -{ - VERIFY(ppObject != nullptr, "Null pointer provided"); - if (!ppObject) - return; - - VERIFY(*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 (const std::runtime_error&) - { - VERIFY(*ppObject == nullptr, "Object was created despite error"); - if (*ppObject) - { - (*ppObject)->Release(); - *ppObject = nullptr; - } - auto ObjectDescString = GetObjectDescString(Desc); - if (ObjectDescString.length()) - { - 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 : "", "'"); - } - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp new file mode 100644 index 00000000..8c16321d --- /dev/null +++ b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp @@ -0,0 +1,502 @@ +/* + * Copyright 2019-2020 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.h" +#include "ObjectBase.h" +#include "DeviceContext.h" +#include "SwapChain.h" +#include "GraphicsAccessories.hpp" +#include "FixedBlockMemoryAllocator.h" +#include "EngineMemory.h" +#include "STDAllocator.h" + +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 (int 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 BaseInterface - base interface that this class will inheret. +/// \warning +/// Render device must *NOT* hold strong references to any +/// object it creates to avoid circular 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 TObjectBase = ObjectBase; + + /// Describes the sizes of device objects + struct DeviceObjectSizes + { + /// Size of the texture object (TextureD3D12Impl, TextureVkImpl, etc.), in bytes + const size_t TextureObjSize; + + /// Size of the texture view object (TextureViewD3D12Impl, TextureViewVkImpl, etc.), in bytes + const size_t TexViewObjSize; + + /// Size of the buffer object (BufferD3D12Impl, BufferVkImpl, etc.), in bytes + const size_t BufferObjSize; + + /// Size of the buffer view object (BufferViewD3D12Impl, BufferViewVkImpl, etc.), in bytes + const size_t BuffViewObjSize; + + /// Size of the shader object (ShaderD3D12Impl, ShaderVkImpl, etc.), in bytes + const size_t ShaderObjSize; + + /// Size of the sampler object (SamplerD3D12Impl, SamplerVkImpl, etc.), in bytes + const size_t SamplerObjSize; + + /// Size of the pipeline state object (PipelineStateD3D12Impl, PipelineStateVkImpl, etc.), in bytes + const size_t PSOSize; + + /// Size of the shader resource binding object (ShaderResourceBindingD3D12Impl, ShaderResourceBindingVkImpl, etc.), in bytes + const size_t SRBSize; + + /// Size of the fence object (FenceD3D12Impl, FenceVkImpl, etc.), in bytes + const size_t FenceSize; + + /// Size of the query object (QueryD3D12Impl, QueryVkImpl, etc.), in bytes + const size_t QuerySize; + }; + + /// \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 - number of deferred device contexts + /// \param ObjectSizes - device object sizes + /// + /// \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, + const DeviceObjectSizes& ObjectSizes) : + // 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, ObjectSizes.TextureObjSize, 64 }, + m_TexViewObjAllocator {RawMemAllocator, ObjectSizes.TexViewObjSize, 64 }, + m_BufObjAllocator {RawMemAllocator, ObjectSizes.BufferObjSize, 128 }, + m_BuffViewObjAllocator {RawMemAllocator, ObjectSizes.BuffViewObjSize, 128 }, + m_ShaderObjAllocator {RawMemAllocator, ObjectSizes.ShaderObjSize, 32 }, + m_SamplerObjAllocator {RawMemAllocator, ObjectSizes.SamplerObjSize, 32 }, + m_PSOAllocator {RawMemAllocator, ObjectSizes.PSOSize, 128 }, + m_SRBAllocator {RawMemAllocator, ObjectSizes.SRBSize, 1024}, + m_ResMappingAllocator {RawMemAllocator, sizeof(ResourceMappingImpl), 16 }, + m_FenceAllocator {RawMemAllocator, ObjectSizes.FenceSize, 16 }, + m_QueryAllocator {RawMemAllocator, ObjectSizes.QuerySize, 16 } + // 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 Release() override final + { + return TObjectBase::Release(); + } + + /// Implementation of IRenderDevice::CreateResourceMapping(). + virtual void CreateResourceMapping(const ResourceMappingDesc& MappingDesc, IResourceMapping** ppMapping) override final; + + /// Implementation of IRenderDevice::GetDeviceCaps(). + virtual const DeviceCaps& GetDeviceCaps() const override final + { + return m_DeviceCaps; + } + + /// Implementation of IRenderDevice::GetTextureFormatInfo(). + virtual const TextureFormatInfo& 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& 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* GetEngineFactory() const override final + { + return m_pEngineFactory.RawPtr(); + } + + void OnCreateDeviceObject(IDeviceObject* pNewObject) + { + } + + 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 + template + void CreateDeviceObject(const Char* ObjectTypeName, const TObjectDescType& Desc, TObjectType** ppObject, TObjectConstructor ConstructObject); + + RefCntAutoPtr m_pEngineFactory; + + DeviceCaps m_DeviceCaps; + + // 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 +}; + + +template +void RenderDeviceBase::CreateResourceMapping(const ResourceMappingDesc& MappingDesc, IResourceMapping** ppMapping) +{ + VERIFY(ppMapping != nullptr, "Null pointer provided"); + if (ppMapping == nullptr) + return; + VERIFY(*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); + } + } +} + + +/// \tparam TObjectType - type of the object being created (IBuffer, ITexture, etc.) +/// \tparam TObjectDescType - type of the object description structure (BufferDesc, TextureDesc, etc.) +/// \tparam TObjectConstructor - 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 +template +void RenderDeviceBase::CreateDeviceObject(const Char* ObjectTypeName, const TObjectDescType& Desc, TObjectType** ppObject, TObjectConstructor ConstructObject) +{ + VERIFY(ppObject != nullptr, "Null pointer provided"); + if (!ppObject) + return; + + VERIFY(*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 (const std::runtime_error&) + { + VERIFY(*ppObject == nullptr, "Object was created despite error"); + if (*ppObject) + { + (*ppObject)->Release(); + *ppObject = nullptr; + } + auto ObjectDescString = GetObjectDescString(Desc); + if (ObjectDescString.length()) + { + 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 : "", "'"); + } + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ResourceMappingImpl.h b/Graphics/GraphicsEngine/include/ResourceMappingImpl.h deleted file mode 100644 index 011e4e7a..00000000 --- a/Graphics/GraphicsEngine/include/ResourceMappingImpl.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of the Diligent::ResourceMappingImpl class - -#include "ResourceMapping.h" -#include "ObjectBase.h" -#include -#include "HashUtils.h" -#include "STDAllocator.h" - -namespace Diligent -{ -struct ResMappingHashKey -{ - ResMappingHashKey(const Char* Str, bool bMakeCopy, Uint32 ArrInd) : - StrKey{Str, bMakeCopy}, - ArrayIndex{ArrInd} - { - } - - ResMappingHashKey(ResMappingHashKey&& rhs) : - StrKey{std::move(rhs.StrKey)}, - ArrayIndex{rhs.ArrayIndex} - {} - - bool operator==(const ResMappingHashKey& RHS) const - { - return StrKey == RHS.StrKey && ArrayIndex == RHS.ArrayIndex; - } - - size_t GetHash() const - { - if (Hash == 0) - { - Hash = ComputeHash(StrKey.GetHash(), ArrayIndex); - } - - return Hash; - } - - // clang-format off - ResMappingHashKey ( const ResMappingHashKey& ) = delete; - ResMappingHashKey& operator = ( const ResMappingHashKey& ) = delete; - ResMappingHashKey& operator = ( ResMappingHashKey&& ) = delete; - // clang-format on - - HashMapStringKey StrKey; - Uint32 ArrayIndex; - mutable size_t Hash = 0; -}; -} // namespace Diligent - -namespace std -{ -template <> -struct hash -{ - size_t operator()(const Diligent::ResMappingHashKey& Key) const - { - return Key.GetHash(); - } -}; -} // namespace std - -namespace Diligent -{ -class FixedBlockMemoryAllocator; - -/// Implementation of the resource mapping -class ResourceMappingImpl : public ObjectBase -{ -public: - typedef ObjectBase TObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this resource mapping - /// \param RawMemAllocator - raw memory allocator that is used by the m_HashTable member - ResourceMappingImpl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator) : - TObjectBase(pRefCounters), - m_HashTable(STD_ALLOCATOR_RAW_MEM(HashTableElem, RawMemAllocator, "Allocator for unordered_map< ResMappingHashKey, RefCntAutoPtr >")) - {} - - ~ResourceMappingImpl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IResourceMapping::AddResource() - virtual void AddResource(const Char* Name, IDeviceObject* pObject, bool bIsUnique) override final; - - /// Implementation of IResourceMapping::AddResourceArray() - virtual void AddResourceArray(const Char* Name, Uint32 StartIndex, IDeviceObject* const* ppObjects, Uint32 NumElements, bool bIsUnique) override final; - - /// Implementation of IResourceMapping::RemoveResourceByName() - virtual void RemoveResourceByName(const Char* Name, Uint32 ArrayIndex) override final; - - /// Implementation of IResourceMapping::GetResource() - virtual void GetResource(const Char* Name, IDeviceObject** ppResource, Uint32 ArrayIndex) override final; - - /// Returns number of resources in the resource mapping. - virtual size_t GetSize() override final; - -private: - ThreadingTools::LockHelper Lock(); - - ThreadingTools::LockFlag m_LockFlag; - typedef std::pair> HashTableElem; - std::unordered_map, std::hash, std::equal_to, STDAllocatorRawMem> m_HashTable; -}; -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp new file mode 100644 index 00000000..011e4e7a --- /dev/null +++ b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp @@ -0,0 +1,136 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of the Diligent::ResourceMappingImpl class + +#include "ResourceMapping.h" +#include "ObjectBase.h" +#include +#include "HashUtils.h" +#include "STDAllocator.h" + +namespace Diligent +{ +struct ResMappingHashKey +{ + ResMappingHashKey(const Char* Str, bool bMakeCopy, Uint32 ArrInd) : + StrKey{Str, bMakeCopy}, + ArrayIndex{ArrInd} + { + } + + ResMappingHashKey(ResMappingHashKey&& rhs) : + StrKey{std::move(rhs.StrKey)}, + ArrayIndex{rhs.ArrayIndex} + {} + + bool operator==(const ResMappingHashKey& RHS) const + { + return StrKey == RHS.StrKey && ArrayIndex == RHS.ArrayIndex; + } + + size_t GetHash() const + { + if (Hash == 0) + { + Hash = ComputeHash(StrKey.GetHash(), ArrayIndex); + } + + return Hash; + } + + // clang-format off + ResMappingHashKey ( const ResMappingHashKey& ) = delete; + ResMappingHashKey& operator = ( const ResMappingHashKey& ) = delete; + ResMappingHashKey& operator = ( ResMappingHashKey&& ) = delete; + // clang-format on + + HashMapStringKey StrKey; + Uint32 ArrayIndex; + mutable size_t Hash = 0; +}; +} // namespace Diligent + +namespace std +{ +template <> +struct hash +{ + size_t operator()(const Diligent::ResMappingHashKey& Key) const + { + return Key.GetHash(); + } +}; +} // namespace std + +namespace Diligent +{ +class FixedBlockMemoryAllocator; + +/// Implementation of the resource mapping +class ResourceMappingImpl : public ObjectBase +{ +public: + typedef ObjectBase TObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this resource mapping + /// \param RawMemAllocator - raw memory allocator that is used by the m_HashTable member + ResourceMappingImpl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator) : + TObjectBase(pRefCounters), + m_HashTable(STD_ALLOCATOR_RAW_MEM(HashTableElem, RawMemAllocator, "Allocator for unordered_map< ResMappingHashKey, RefCntAutoPtr >")) + {} + + ~ResourceMappingImpl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IResourceMapping::AddResource() + virtual void AddResource(const Char* Name, IDeviceObject* pObject, bool bIsUnique) override final; + + /// Implementation of IResourceMapping::AddResourceArray() + virtual void AddResourceArray(const Char* Name, Uint32 StartIndex, IDeviceObject* const* ppObjects, Uint32 NumElements, bool bIsUnique) override final; + + /// Implementation of IResourceMapping::RemoveResourceByName() + virtual void RemoveResourceByName(const Char* Name, Uint32 ArrayIndex) override final; + + /// Implementation of IResourceMapping::GetResource() + virtual void GetResource(const Char* Name, IDeviceObject** ppResource, Uint32 ArrayIndex) override final; + + /// Returns number of resources in the resource mapping. + virtual size_t GetSize() override final; + +private: + ThreadingTools::LockHelper Lock(); + + ThreadingTools::LockFlag m_LockFlag; + typedef std::pair> HashTableElem; + std::unordered_map, std::hash, std::equal_to, STDAllocatorRawMem> m_HashTable; +}; +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/SamplerBase.h b/Graphics/GraphicsEngine/include/SamplerBase.h deleted file mode 100644 index aa408556..00000000 --- a/Graphics/GraphicsEngine/include/SamplerBase.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2019-2020 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::SamplerBase template class - -#include "Sampler.h" -#include "DeviceObjectBase.h" -#include "RenderDeviceBase.h" - -namespace Diligent -{ - -/// Template class implementing base functionality for a sampler object. - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ISamplerD3D11, Diligent::ISamplerD3D12, -/// Diligent::ISamplerGL or Diligent::ISamplerVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class SamplerBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this sampler. - /// \param pDevice - pointer to the device. - /// \param SamDesc - sampler description. - /// \param bIsDeviceInternal - flag indicating if the sampler is an internal device object and - /// must not keep a strong reference to the device. - SamplerBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const SamplerDesc& SamDesc, bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, SamDesc, bIsDeviceInternal} - {} - - ~SamplerBase() - { - /// \note Destructor cannot directly remove the object from the registry as this may cause a - /// deadlock. - auto& SamplerRegistry = this->GetDevice()->GetSamplerRegistry(); - SamplerRegistry.ReportDeletedObject(); - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Sampler, TDeviceObjectBase) -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/SamplerBase.hpp b/Graphics/GraphicsEngine/include/SamplerBase.hpp new file mode 100644 index 00000000..4c9c505d --- /dev/null +++ b/Graphics/GraphicsEngine/include/SamplerBase.hpp @@ -0,0 +1,74 @@ +/* + * Copyright 2019-2020 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::SamplerBase template class + +#include "Sampler.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" + +namespace Diligent +{ + +/// Template class implementing base functionality for a sampler object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ISamplerD3D11, Diligent::ISamplerD3D12, +/// Diligent::ISamplerGL or Diligent::ISamplerVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class SamplerBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this sampler. + /// \param pDevice - pointer to the device. + /// \param SamDesc - sampler description. + /// \param bIsDeviceInternal - flag indicating if the sampler is an internal device object and + /// must not keep a strong reference to the device. + SamplerBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const SamplerDesc& SamDesc, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, SamDesc, bIsDeviceInternal} + {} + + ~SamplerBase() + { + /// \note Destructor cannot directly remove the object from the registry as this may cause a + /// deadlock. + auto& SamplerRegistry = this->GetDevice()->GetSamplerRegistry(); + SamplerRegistry.ReportDeletedObject(); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Sampler, TDeviceObjectBase) +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderBase.h b/Graphics/GraphicsEngine/include/ShaderBase.h deleted file mode 100644 index cf99cdc0..00000000 --- a/Graphics/GraphicsEngine/include/ShaderBase.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2019-2020 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::ShaderBase template class - -#include - -#include "Shader.h" -#include "DeviceObjectBase.h" -#include "STDAllocator.h" -#include "PlatformMisc.h" -#include "EngineMemory.h" -#include "Align.h" - -namespace Diligent -{ - -inline SHADER_TYPE GetShaderTypeFromIndex(Int32 Index) -{ - return static_cast(1 << Index); -} - -inline Int32 GetShaderTypeIndex(SHADER_TYPE Type) -{ - VERIFY(IsPowerOfTwo(Uint32{Type}), "Only single shader stage should be provided"); - - Int32 ShaderIndex = PlatformMisc::GetLSB(Type); - -#ifdef _DEBUG - switch (Type) - { - // clang-format off - case SHADER_TYPE_UNKNOWN: VERIFY_EXPR(ShaderIndex == -1); break; - case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderIndex == 0); break; - case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderIndex == 1); break; - case SHADER_TYPE_GEOMETRY:VERIFY_EXPR(ShaderIndex == 2); break; - case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderIndex == 3); break; - case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderIndex == 4); break; - case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderIndex == 5); break; - // clang-format on - default: UNEXPECTED("Unexpected shader type (", Type, ")"); break; - } - VERIFY(Type == GetShaderTypeFromIndex(ShaderIndex), "Incorrect shader type index"); -#endif - return ShaderIndex; -} - -static const int VSInd = GetShaderTypeIndex(SHADER_TYPE_VERTEX); -static const int PSInd = GetShaderTypeIndex(SHADER_TYPE_PIXEL); -static const int GSInd = GetShaderTypeIndex(SHADER_TYPE_GEOMETRY); -static const int HSInd = GetShaderTypeIndex(SHADER_TYPE_HULL); -static const int DSInd = GetShaderTypeIndex(SHADER_TYPE_DOMAIN); -static const int CSInd = GetShaderTypeIndex(SHADER_TYPE_COMPUTE); - - -/// Template class implementing base functionality for a shader object - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IShaderD3D11, Diligent::IShaderD3D12, -/// Diligent::IShaderGL or Diligent::IShaderVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class ShaderBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this shader. - /// \param pDevice - pointer to the device. - /// \param ShdrDesc - shader description. - /// \param bIsDeviceInternal - flag indicating if the shader is an internal device object and - /// must not keep a strong reference to the device. - ShaderBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const ShaderDesc& ShdrDesc, - bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, ShdrDesc, bIsDeviceInternal} - { - const auto& deviceFeatures = pDevice->GetDeviceCaps().Features; - if (ShdrDesc.ShaderType == SHADER_TYPE_GEOMETRY && !deviceFeatures.GeometryShaders) - LOG_ERROR_AND_THROW("Geometry shaders are not supported by this device"); - - if ((ShdrDesc.ShaderType == SHADER_TYPE_DOMAIN || ShdrDesc.ShaderType == SHADER_TYPE_HULL) && !deviceFeatures.Tessellation) - LOG_ERROR_AND_THROW("Tessellation shaders are not supported by this device"); - - if (ShdrDesc.ShaderType == SHADER_TYPE_COMPUTE && !deviceFeatures.ComputeShaders) - LOG_ERROR_AND_THROW("Compute shaders are not supported by this device"); - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Shader, TDeviceObjectBase) -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderBase.hpp b/Graphics/GraphicsEngine/include/ShaderBase.hpp new file mode 100644 index 00000000..252f11ac --- /dev/null +++ b/Graphics/GraphicsEngine/include/ShaderBase.hpp @@ -0,0 +1,122 @@ +/* + * Copyright 2019-2020 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::ShaderBase template class + +#include + +#include "Shader.h" +#include "DeviceObjectBase.hpp" +#include "STDAllocator.h" +#include "PlatformMisc.h" +#include "EngineMemory.h" +#include "Align.h" + +namespace Diligent +{ + +inline SHADER_TYPE GetShaderTypeFromIndex(Int32 Index) +{ + return static_cast(1 << Index); +} + +inline Int32 GetShaderTypeIndex(SHADER_TYPE Type) +{ + VERIFY(IsPowerOfTwo(Uint32{Type}), "Only single shader stage should be provided"); + + Int32 ShaderIndex = PlatformMisc::GetLSB(Type); + +#ifdef _DEBUG + switch (Type) + { + // clang-format off + case SHADER_TYPE_UNKNOWN: VERIFY_EXPR(ShaderIndex == -1); break; + case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderIndex == 0); break; + case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderIndex == 1); break; + case SHADER_TYPE_GEOMETRY:VERIFY_EXPR(ShaderIndex == 2); break; + case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderIndex == 3); break; + case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderIndex == 4); break; + case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderIndex == 5); break; + // clang-format on + default: UNEXPECTED("Unexpected shader type (", Type, ")"); break; + } + VERIFY(Type == GetShaderTypeFromIndex(ShaderIndex), "Incorrect shader type index"); +#endif + return ShaderIndex; +} + +static const int VSInd = GetShaderTypeIndex(SHADER_TYPE_VERTEX); +static const int PSInd = GetShaderTypeIndex(SHADER_TYPE_PIXEL); +static const int GSInd = GetShaderTypeIndex(SHADER_TYPE_GEOMETRY); +static const int HSInd = GetShaderTypeIndex(SHADER_TYPE_HULL); +static const int DSInd = GetShaderTypeIndex(SHADER_TYPE_DOMAIN); +static const int CSInd = GetShaderTypeIndex(SHADER_TYPE_COMPUTE); + + +/// Template class implementing base functionality for a shader object + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IShaderD3D11, Diligent::IShaderD3D12, +/// Diligent::IShaderGL or Diligent::IShaderVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class ShaderBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this shader. + /// \param pDevice - pointer to the device. + /// \param ShdrDesc - shader description. + /// \param bIsDeviceInternal - flag indicating if the shader is an internal device object and + /// must not keep a strong reference to the device. + ShaderBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const ShaderDesc& ShdrDesc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, ShdrDesc, bIsDeviceInternal} + { + const auto& deviceFeatures = pDevice->GetDeviceCaps().Features; + if (ShdrDesc.ShaderType == SHADER_TYPE_GEOMETRY && !deviceFeatures.GeometryShaders) + LOG_ERROR_AND_THROW("Geometry shaders are not supported by this device"); + + if ((ShdrDesc.ShaderType == SHADER_TYPE_DOMAIN || ShdrDesc.ShaderType == SHADER_TYPE_HULL) && !deviceFeatures.Tessellation) + LOG_ERROR_AND_THROW("Tessellation shaders are not supported by this device"); + + if (ShdrDesc.ShaderType == SHADER_TYPE_COMPUTE && !deviceFeatures.ComputeShaders) + LOG_ERROR_AND_THROW("Compute shaders are not supported by this device"); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Shader, TDeviceObjectBase) +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.h b/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.h deleted file mode 100644 index 9600294c..00000000 --- a/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2019-2020 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::ShaderResourceBindingBase template class - -#include "ShaderResourceBinding.h" -#include "ObjectBase.h" -#include "GraphicsTypes.h" -#include "RefCntAutoPtr.h" - -namespace Diligent -{ - -/// Template class implementing base functionality for a shader resource binding - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IShaderResourceBindingGL, Diligent::IShaderResourceBindingD3D11, -/// Diligent::IShaderResourceBindingD3D12 or Diligent::IShaderResourceBindingVk). -template -class ShaderResourceBindingBase : public ObjectBase -{ -public: - typedef ObjectBase TObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this SRB. - /// \param pPSO - pipeline state that this SRB belongs to. - /// \param IsInternal - flag indicating if the shader resource binding is an internal PSO object and - /// must not keep a strong reference to the PSO. - ShaderResourceBindingBase(IReferenceCounters* pRefCounters, IPipelineState* pPSO, bool IsInternal = false) : - TObjectBase{pRefCounters}, - m_spPSO{IsInternal ? nullptr : pPSO}, - m_pPSO{pPSO} - {} - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBinding, TObjectBase) - - /// Implementation of IShaderResourceBinding::GetPipelineState(). - virtual IPipelineState* GetPipelineState() override final - { - return m_pPSO; - } - - template - PSOType* GetPipelineState() - { - return ValidatedCast(m_pPSO); - } - - template - PSOType* GetPipelineState() const - { - return ValidatedCast(m_pPSO); - } - -protected: - /// Strong reference to PSO. We must use strong reference, because - /// shader resource binding uses PSO's memory allocator to allocate - /// memory for shader resource cache. - RefCntAutoPtr m_spPSO; - IPipelineState* const m_pPSO; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp new file mode 100644 index 00000000..9600294c --- /dev/null +++ b/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp @@ -0,0 +1,90 @@ +/* + * Copyright 2019-2020 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::ShaderResourceBindingBase template class + +#include "ShaderResourceBinding.h" +#include "ObjectBase.h" +#include "GraphicsTypes.h" +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + +/// Template class implementing base functionality for a shader resource binding + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IShaderResourceBindingGL, Diligent::IShaderResourceBindingD3D11, +/// Diligent::IShaderResourceBindingD3D12 or Diligent::IShaderResourceBindingVk). +template +class ShaderResourceBindingBase : public ObjectBase +{ +public: + typedef ObjectBase TObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this SRB. + /// \param pPSO - pipeline state that this SRB belongs to. + /// \param IsInternal - flag indicating if the shader resource binding is an internal PSO object and + /// must not keep a strong reference to the PSO. + ShaderResourceBindingBase(IReferenceCounters* pRefCounters, IPipelineState* pPSO, bool IsInternal = false) : + TObjectBase{pRefCounters}, + m_spPSO{IsInternal ? nullptr : pPSO}, + m_pPSO{pPSO} + {} + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBinding, TObjectBase) + + /// Implementation of IShaderResourceBinding::GetPipelineState(). + virtual IPipelineState* GetPipelineState() override final + { + return m_pPSO; + } + + template + PSOType* GetPipelineState() + { + return ValidatedCast(m_pPSO); + } + + template + PSOType* GetPipelineState() const + { + return ValidatedCast(m_pPSO); + } + +protected: + /// Strong reference to PSO. We must use strong reference, because + /// shader resource binding uses PSO's memory allocator to allocate + /// memory for shader resource cache. + RefCntAutoPtr m_spPSO; + IPipelineState* const m_pPSO; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h deleted file mode 100644 index 4e8f49e0..00000000 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2019-2020 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::ShaderBase template class - -#include - -#include "ShaderResourceVariable.h" -#include "PipelineState.h" -#include "StringTools.h" -#include "GraphicsAccessories.hpp" - -namespace Diligent -{ - -template -SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, - SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, - const ShaderResourceVariableDesc* Variables, - Uint32 NumVars, - TNameCompare NameCompare) -{ - for (Uint32 v = 0; v < NumVars; ++v) - { - const auto& CurrVarDesc = Variables[v]; - if (((CurrVarDesc.ShaderStages & ShaderStage) != 0) && NameCompare(CurrVarDesc.Name)) - { - return CurrVarDesc.Type; - } - } - return DefaultVariableType; -} - -inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, - const Char* Name, - SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, - const ShaderResourceVariableDesc* Variables, - Uint32 NumVars) -{ - return GetShaderVariableType(ShaderStage, DefaultVariableType, Variables, NumVars, - [&](const char* VarName) // - { - return strcmp(VarName, Name) == 0; - }); -} - -inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, - const Char* Name, - const PipelineResourceLayoutDesc& LayoutDesc) -{ - return GetShaderVariableType(ShaderStage, Name, LayoutDesc.DefaultVariableType, LayoutDesc.Variables, LayoutDesc.NumVariables); -} - -inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, - const String& Name, - SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, - const ShaderResourceVariableDesc* Variables, - Uint32 NumVars) -{ - return GetShaderVariableType(ShaderStage, DefaultVariableType, Variables, NumVars, - [&](const char* VarName) // - { - return Name.compare(VarName) == 0; - }); -} - -inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, - const String& Name, - const PipelineResourceLayoutDesc& LayoutDesc) -{ - return GetShaderVariableType(ShaderStage, Name, LayoutDesc.DefaultVariableType, LayoutDesc.Variables, LayoutDesc.NumVariables); -} - -inline bool IsAllowedType(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 AllowedTypeBits) noexcept -{ - return ((1 << VarType) & AllowedTypeBits) != 0; -} - -inline Uint32 GetAllowedTypeBits(const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes) noexcept -{ - if (AllowedVarTypes == nullptr) - return 0xFFFFFFFF; - - Uint32 AllowedTypeBits = 0; - for (Uint32 i = 0; i < NumAllowedTypes; ++i) - AllowedTypeBits |= 1 << AllowedVarTypes[i]; - return AllowedTypeBits; -} - -inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers, - Uint32 NumStaticSamplers, - SHADER_TYPE ShaderType, - const char* ResourceName, - const char* SamplerSuffix) -{ - for (Uint32 s = 0; s < NumStaticSamplers; ++s) - { - const auto& StSam = StaticSamplers[s]; - if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(ResourceName, StSam.SamplerOrTextureName, SamplerSuffix)) - return s; - } - - return -1; -} - - - - -template -bool VerifyConstantBufferBinding(const ResourceAttribsType& Attribs, - SHADER_RESOURCE_VARIABLE_TYPE VarType, - Uint32 ArrayIndex, - const IDeviceObject* pBuffer, - const BufferImplType* pBufferImpl, - const IDeviceObject* pCachedBuffer, - const char* ShaderName = nullptr) -{ - if (pBuffer != nullptr && pBufferImpl == nullptr) - { - std::stringstream ss; - ss << "Failed to bind resource '" << pBuffer->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". Invalid resource type: buffer is expected."; - LOG_ERROR_MESSAGE(ss.str()); - return false; - } - - bool BindingOK = true; - if (pBufferImpl != nullptr && (pBufferImpl->GetDesc().BindFlags & BIND_UNIFORM_BUFFER) == 0) - { - std::stringstream ss; - ss << "Error binding buffer '" << pBufferImpl->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". The buffer was not created with BIND_UNIFORM_BUFFER flag."; - LOG_ERROR_MESSAGE(ss.str()); - BindingOK = false; - } - - if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedBuffer != nullptr && pCachedBuffer != pBufferImpl) - { - auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); - - std::stringstream ss; - ss << "Non-null constant (uniform) buffer '" << pCachedBuffer->GetDesc().Name << "' is already bound to " << VarTypeStr - << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". Attempting to bind "; - if (pBufferImpl) - { - ss << "another resource ('" << pBufferImpl->GetDesc().Name << "')"; - } - else - { - ss << "null"; - } - ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; - LOG_ERROR_MESSAGE(ss.str()); - - BindingOK = false; - } - - return BindingOK; -} - -template -const char* GetResourceTypeName(); - -template <> -inline const char* GetResourceTypeName() -{ - return "texture view"; -} - -template <> -inline const char* GetResourceTypeName() -{ - return "buffer view"; -} - -template -bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, - SHADER_RESOURCE_VARIABLE_TYPE VarType, - Uint32 ArrayIndex, - const IDeviceObject* pView, - const ResourceViewImplType* pViewImpl, - std::initializer_list ExpectedViewTypes, - const IDeviceObject* pCachedView, - const char* ShaderName = nullptr) -{ - const char* ExpectedResourceType = GetResourceTypeName(); - - if (pView && !pViewImpl) - { - std::stringstream ss; - ss << "Failed to bind resource '" << pView->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". Invalid resource type: " << ExpectedResourceType << " is expected."; - LOG_ERROR_MESSAGE(ss.str()); - return false; - } - - bool BindingOK = true; - if (pViewImpl) - { - auto ViewType = pViewImpl->GetDesc().ViewType; - bool IsExpectedViewType = false; - for (auto ExpectedViewType : ExpectedViewTypes) - { - if (ExpectedViewType == ViewType) - IsExpectedViewType = true; - } - - if (!IsExpectedViewType) - { - std::string ExpectedViewTypeName; - - std::stringstream ss; - ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '" - << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". Incorrect view type: "; - bool IsFirstViewType = true; - for (auto ExpectedViewType : ExpectedViewTypes) - { - if (!IsFirstViewType) - { - ss << " or "; - } - ss << GetViewTypeLiteralName(ExpectedViewType); - IsFirstViewType = false; - } - ss << " is expected, " << GetViewTypeLiteralName(ViewType) << " is provided."; - LOG_ERROR_MESSAGE(ss.str()); - - BindingOK = false; - } - } - - if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl) - { - auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); - std::stringstream ss; - ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr - << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; - if (ShaderName != nullptr) - { - ss << " in shader '" << ShaderName << '\''; - } - ss << ". Attempting to bind "; - if (pViewImpl) - { - ss << "another resource ('" << pViewImpl->GetDesc().Name << "')"; - } - else - { - ss << "null"; - } - ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; - LOG_ERROR_MESSAGE(ss.str()); - - BindingOK = false; - } - return BindingOK; -} - -inline void VerifyAndCorrectSetArrayArguments(const char* Name, Uint32 ArraySize, Uint32& FirstElement, Uint32& NumElements) -{ - if (FirstElement >= ArraySize) - { - LOG_ERROR_MESSAGE("SetArray arguments are invalid for '", Name, "' variable: FirstElement (", FirstElement, ") is out of allowed range 0 .. ", ArraySize - 1); - FirstElement = ArraySize - 1; - NumElements = 0; - } - - if (FirstElement + NumElements > ArraySize) - { - LOG_ERROR_MESSAGE("SetArray arguments are invalid for '", Name, "' variable: specified element range (", FirstElement, " .. ", - FirstElement + NumElements - 1, ") is out of array bounds 0 .. ", ArraySize - 1); - NumElements = ArraySize - FirstElement; - } -} - -struct DefaultShaderVariableIDComparator -{ - bool operator()(const INTERFACE_ID& IID) const - { - return IID == IID_ShaderResourceVariable || IID == IID_Unknown; - } -}; - -/// Base implementation of a shader variable -template -struct ShaderVariableBase : public ResourceVariableBaseInterface -{ - ShaderVariableBase(ResourceLayoutType& ParentResLayout) : - m_ParentResLayout(ParentResLayout) - { - } - - void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final - { - if (ppInterface == nullptr) - return; - - *ppInterface = nullptr; - if (VariableIDComparator{}(IID)) - { - *ppInterface = this; - (*ppInterface)->AddRef(); - } - } - - virtual Atomics::Long AddRef() override final - { - return m_ParentResLayout.GetOwner().AddRef(); - } - - virtual Atomics::Long Release() override final - { - return m_ParentResLayout.GetOwner().Release(); - } - - virtual IReferenceCounters* GetReferenceCounters() const override final - { - return m_ParentResLayout.GetOwner().GetReferenceCounters(); - } - -protected: - ResourceLayoutType& m_ParentResLayout; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp new file mode 100644 index 00000000..4e8f49e0 --- /dev/null +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -0,0 +1,379 @@ +/* + * Copyright 2019-2020 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::ShaderBase template class + +#include + +#include "ShaderResourceVariable.h" +#include "PipelineState.h" +#include "StringTools.h" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +template +SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, + SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, + const ShaderResourceVariableDesc* Variables, + Uint32 NumVars, + TNameCompare NameCompare) +{ + for (Uint32 v = 0; v < NumVars; ++v) + { + const auto& CurrVarDesc = Variables[v]; + if (((CurrVarDesc.ShaderStages & ShaderStage) != 0) && NameCompare(CurrVarDesc.Name)) + { + return CurrVarDesc.Type; + } + } + return DefaultVariableType; +} + +inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, + const Char* Name, + SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, + const ShaderResourceVariableDesc* Variables, + Uint32 NumVars) +{ + return GetShaderVariableType(ShaderStage, DefaultVariableType, Variables, NumVars, + [&](const char* VarName) // + { + return strcmp(VarName, Name) == 0; + }); +} + +inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, + const Char* Name, + const PipelineResourceLayoutDesc& LayoutDesc) +{ + return GetShaderVariableType(ShaderStage, Name, LayoutDesc.DefaultVariableType, LayoutDesc.Variables, LayoutDesc.NumVariables); +} + +inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, + const String& Name, + SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType, + const ShaderResourceVariableDesc* Variables, + Uint32 NumVars) +{ + return GetShaderVariableType(ShaderStage, DefaultVariableType, Variables, NumVars, + [&](const char* VarName) // + { + return Name.compare(VarName) == 0; + }); +} + +inline SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType(SHADER_TYPE ShaderStage, + const String& Name, + const PipelineResourceLayoutDesc& LayoutDesc) +{ + return GetShaderVariableType(ShaderStage, Name, LayoutDesc.DefaultVariableType, LayoutDesc.Variables, LayoutDesc.NumVariables); +} + +inline bool IsAllowedType(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 AllowedTypeBits) noexcept +{ + return ((1 << VarType) & AllowedTypeBits) != 0; +} + +inline Uint32 GetAllowedTypeBits(const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes) noexcept +{ + if (AllowedVarTypes == nullptr) + return 0xFFFFFFFF; + + Uint32 AllowedTypeBits = 0; + for (Uint32 i = 0; i < NumAllowedTypes; ++i) + AllowedTypeBits |= 1 << AllowedVarTypes[i]; + return AllowedTypeBits; +} + +inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers, + Uint32 NumStaticSamplers, + SHADER_TYPE ShaderType, + const char* ResourceName, + const char* SamplerSuffix) +{ + for (Uint32 s = 0; s < NumStaticSamplers; ++s) + { + const auto& StSam = StaticSamplers[s]; + if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(ResourceName, StSam.SamplerOrTextureName, SamplerSuffix)) + return s; + } + + return -1; +} + + + + +template +bool VerifyConstantBufferBinding(const ResourceAttribsType& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 ArrayIndex, + const IDeviceObject* pBuffer, + const BufferImplType* pBufferImpl, + const IDeviceObject* pCachedBuffer, + const char* ShaderName = nullptr) +{ + if (pBuffer != nullptr && pBufferImpl == nullptr) + { + std::stringstream ss; + ss << "Failed to bind resource '" << pBuffer->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Invalid resource type: buffer is expected."; + LOG_ERROR_MESSAGE(ss.str()); + return false; + } + + bool BindingOK = true; + if (pBufferImpl != nullptr && (pBufferImpl->GetDesc().BindFlags & BIND_UNIFORM_BUFFER) == 0) + { + std::stringstream ss; + ss << "Error binding buffer '" << pBufferImpl->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". The buffer was not created with BIND_UNIFORM_BUFFER flag."; + LOG_ERROR_MESSAGE(ss.str()); + BindingOK = false; + } + + if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedBuffer != nullptr && pCachedBuffer != pBufferImpl) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + + std::stringstream ss; + ss << "Non-null constant (uniform) buffer '" << pCachedBuffer->GetDesc().Name << "' is already bound to " << VarTypeStr + << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Attempting to bind "; + if (pBufferImpl) + { + ss << "another resource ('" << pBufferImpl->GetDesc().Name << "')"; + } + else + { + ss << "null"; + } + ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + + return BindingOK; +} + +template +const char* GetResourceTypeName(); + +template <> +inline const char* GetResourceTypeName() +{ + return "texture view"; +} + +template <> +inline const char* GetResourceTypeName() +{ + return "buffer view"; +} + +template +bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 ArrayIndex, + const IDeviceObject* pView, + const ResourceViewImplType* pViewImpl, + std::initializer_list ExpectedViewTypes, + const IDeviceObject* pCachedView, + const char* ShaderName = nullptr) +{ + const char* ExpectedResourceType = GetResourceTypeName(); + + if (pView && !pViewImpl) + { + std::stringstream ss; + ss << "Failed to bind resource '" << pView->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Invalid resource type: " << ExpectedResourceType << " is expected."; + LOG_ERROR_MESSAGE(ss.str()); + return false; + } + + bool BindingOK = true; + if (pViewImpl) + { + auto ViewType = pViewImpl->GetDesc().ViewType; + bool IsExpectedViewType = false; + for (auto ExpectedViewType : ExpectedViewTypes) + { + if (ExpectedViewType == ViewType) + IsExpectedViewType = true; + } + + if (!IsExpectedViewType) + { + std::string ExpectedViewTypeName; + + std::stringstream ss; + ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '" + << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Incorrect view type: "; + bool IsFirstViewType = true; + for (auto ExpectedViewType : ExpectedViewTypes) + { + if (!IsFirstViewType) + { + ss << " or "; + } + ss << GetViewTypeLiteralName(ExpectedViewType); + IsFirstViewType = false; + } + ss << " is expected, " << GetViewTypeLiteralName(ViewType) << " is provided."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + } + + if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + std::stringstream ss; + ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr + << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Attempting to bind "; + if (pViewImpl) + { + ss << "another resource ('" << pViewImpl->GetDesc().Name << "')"; + } + else + { + ss << "null"; + } + ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + return BindingOK; +} + +inline void VerifyAndCorrectSetArrayArguments(const char* Name, Uint32 ArraySize, Uint32& FirstElement, Uint32& NumElements) +{ + if (FirstElement >= ArraySize) + { + LOG_ERROR_MESSAGE("SetArray arguments are invalid for '", Name, "' variable: FirstElement (", FirstElement, ") is out of allowed range 0 .. ", ArraySize - 1); + FirstElement = ArraySize - 1; + NumElements = 0; + } + + if (FirstElement + NumElements > ArraySize) + { + LOG_ERROR_MESSAGE("SetArray arguments are invalid for '", Name, "' variable: specified element range (", FirstElement, " .. ", + FirstElement + NumElements - 1, ") is out of array bounds 0 .. ", ArraySize - 1); + NumElements = ArraySize - FirstElement; + } +} + +struct DefaultShaderVariableIDComparator +{ + bool operator()(const INTERFACE_ID& IID) const + { + return IID == IID_ShaderResourceVariable || IID == IID_Unknown; + } +}; + +/// Base implementation of a shader variable +template +struct ShaderVariableBase : public ResourceVariableBaseInterface +{ + ShaderVariableBase(ResourceLayoutType& ParentResLayout) : + m_ParentResLayout(ParentResLayout) + { + } + + void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final + { + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (VariableIDComparator{}(IID)) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } + } + + virtual Atomics::Long AddRef() override final + { + return m_ParentResLayout.GetOwner().AddRef(); + } + + virtual Atomics::Long Release() override final + { + return m_ParentResLayout.GetOwner().Release(); + } + + virtual IReferenceCounters* GetReferenceCounters() const override final + { + return m_ParentResLayout.GetOwner().GetReferenceCounters(); + } + +protected: + ResourceLayoutType& m_ParentResLayout; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/StateObjectsRegistry.h b/Graphics/GraphicsEngine/include/StateObjectsRegistry.h deleted file mode 100644 index f3484bc1..00000000 --- a/Graphics/GraphicsEngine/include/StateObjectsRegistry.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2019-2020 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::StateObjectsRegistry template class - -#include "DeviceObject.h" -#include -#include "STDAllocator.h" - -namespace Diligent -{ -/// Template class implementing state object registry - -/// \tparam ResourceDescType - type of the resource description. The type must have -/// operator== and a hash function defined. -/// -/// \remarks -/// The following strategies do not work: -/// - To store raw pointers and remove the object from the registry in the -/// object's destructor. In this case other thread may obtain a reference -/// to the object while it is being deleted. This scenario is possible if one thread -/// has just entered the destructor, but other is executing Find() and entered -/// the protection section. -/// - Strong pointers will cause circular references and result in memory leaks. -/// \remarks -/// Only weak pointers provide thread-safe solution. The object is either atomically destroyed, -/// so that no other thread can obtain a reference to it through weak pointers. Or it is atomically -/// locked, so that strong reference is obtained. In this case no other thread can destroy the object, -/// because there is at least one strong reference now. Note however that removing the object from the -/// registry in the object's destructor may cause a deadlock at the point where Find() locks the weak pointer: -/// if other thread has started dtor, the object will be locked by Diligent::RefCountedObject::Release(). -/// If after that this thread locks the registry first, it will be waiting for the object to unlock in -/// Diligent::RefCntWeakPtr::Lock(), while the dtor thread will be waiting for the registry to unlock. -template -class StateObjectsRegistry -{ -public: - /// Number of outstanding deleted objects to purge the registry. - static constexpr int DeletedObjectsToPurge = 32; - - StateObjectsRegistry(IMemoryAllocator& RawAllocator, const Char* RegistryName) : - m_DescToObjHashMap(STD_ALLOCATOR_RAW_MEM(HashMapElem, RawAllocator, "Allocator for unordered_map >")), - m_RegistryName{RegistryName} - {} - - ~StateObjectsRegistry() - { - // Object registry is part of the device, and every device - // object holds a strong reference to the device. So device - // is destroyed after all device objects are destroyed, and there - // may only be expired references in the registry. After we - // purge it, the registry must be empty. - Purge(); - VERIFY(m_DescToObjHashMap.empty(), "DescToObjHashMap is not empty"); - } - - /// Adds a new object to the registry - - /// \param [in] ObjectDesc - object description. - /// \param [in] pObject - pointer to the object. - /// - /// Besides adding a new object, the function also checks the number of - /// outstanding deleted objects and calls Purge() if the number has reached - /// the threshold value DeletedObjectsToPurge. Creating a state object is - /// assumed to be an expensive operation and should be performed during - /// the initialization. Occasional purge operations should not add significant - /// cost to it. - void Add(const ResourceDescType& ObjectDesc, IDeviceObject* pObject) - { - ThreadingTools::LockHelper Lock(m_LockFlag); - - // If the number of outstanding deleted objects reached the threshold value, - // purge the registry. Since we have exclusive access now, it is safe - // to do. - if (m_NumDeletedObjects >= DeletedObjectsToPurge) - { - Purge(); - m_NumDeletedObjects = 0; - } - - // Try to construct the new element in place - auto Elems = m_DescToObjHashMap.emplace(std::make_pair(ObjectDesc, Diligent::RefCntWeakPtr(pObject))); - // It is theorertically possible that the same object can be found - // in the registry. This might happen if two threads try to create - // the same object at the same time. They both will not find the - // object and then will create and try to add it. - // - // If the object already exists, we replace the existing reference. - // This is safer as there might be scenarios where existing reference - // might be expired. For instance, two threads try to create the same - // object which is not in the registry. The first thread creates - // the object, adds it to the registry and then releases it. After that - // the second thread creates the same object and tries to add it to - // the registry. It will find an existing expired reference to the - // object. - if (!Elems.second) - { - VERIFY(Elems.first->first == ObjectDesc, "Incorrect object description"); - LOG_WARNING_MESSAGE("Object named '", Elems.first->first.Name, - "' with the same description already exists in the registry." - "Replacing with the new object named '", - ObjectDesc.Name ? ObjectDesc.Name : "", "'."); - Elems.first->second = pObject; - } - } - - /// Finds the object in the registry - void Find(const ResourceDescType& Desc, IDeviceObject** ppObject) - { - VERIFY(*ppObject == nullptr, "Overwriting reference to existing object may cause memory leaks"); - *ppObject = nullptr; - ThreadingTools::LockHelper Lock(m_LockFlag); - - auto It = m_DescToObjHashMap.find(Desc); - if (It != m_DescToObjHashMap.end()) - { - // Try to obtain strong reference to the object. - // This is an atomic operation and we either get - // a new strong reference or object has been destroyed - // and we get null. - auto pObject = It->second.Lock(); - if (pObject) - { - *ppObject = pObject.Detach(); - //LOG_INFO_MESSAGE( "Equivalent of the requested state object named \"", Desc.Name ? Desc.Name : "", "\" found in the ", m_RegistryName, " registry. Reusing existing object."); - } - else - { - // Expired object found: remove it from the map - m_DescToObjHashMap.erase(It); - Atomics::AtomicDecrement(m_NumDeletedObjects); - } - } - } - - /// Purges outstanding deleted objects from the registry - void Purge() - { - Uint32 NumPurgedObjects = 0; - auto It = m_DescToObjHashMap.begin(); - while (It != m_DescToObjHashMap.end()) - { - auto NextIt = It; - ++NextIt; - // Note that IsValid() is not a thread-safe function in the sense that it - // can give false positive results. The only thread-safe way to check if the - // object is alive is to lock the weak pointer, but that requires thread - // synchronization. We will immediately unlock the pointer anyway, so we - // want to detect 100% expired pointers. IsValid() does provide that information - // because once a weak pointer becomes invalid, it will be invalid - // until it is destroyed. It is not a problem if we miss an expired weak - // pointer as it will definitiely be removed next time. - if (!It->second.IsValid()) - { - m_DescToObjHashMap.erase(It); - ++NumPurgedObjects; - } - - It = NextIt; - } - LOG_INFO_MESSAGE("Purged ", NumPurgedObjects, " deleted objects from the ", m_RegistryName, " registry"); - } - - /// Increments the number of outstanding deleted objects. - /// When this number reaches DeletedObjectsToPurge, Purge() will - /// be called. - void ReportDeletedObject() - { - Atomics::AtomicIncrement(m_NumDeletedObjects); - } - -private: - /// Lock flag to protect the m_DescToObjHashMap - ThreadingTools::LockFlag m_LockFlag; - - /// Nmber of outstanding deleted objects that have not been purged - Atomics::AtomicLong m_NumDeletedObjects; - - /// Hash map that stores weak pointers to the referenced objects - typedef std::pair> HashMapElem; - std::unordered_map, std::hash, std::equal_to, STDAllocatorRawMem> m_DescToObjHashMap; - - /// Registry name used for debug output - const String m_RegistryName; -}; -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/StateObjectsRegistry.hpp b/Graphics/GraphicsEngine/include/StateObjectsRegistry.hpp new file mode 100644 index 00000000..f3484bc1 --- /dev/null +++ b/Graphics/GraphicsEngine/include/StateObjectsRegistry.hpp @@ -0,0 +1,213 @@ +/* + * Copyright 2019-2020 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::StateObjectsRegistry template class + +#include "DeviceObject.h" +#include +#include "STDAllocator.h" + +namespace Diligent +{ +/// Template class implementing state object registry + +/// \tparam ResourceDescType - type of the resource description. The type must have +/// operator== and a hash function defined. +/// +/// \remarks +/// The following strategies do not work: +/// - To store raw pointers and remove the object from the registry in the +/// object's destructor. In this case other thread may obtain a reference +/// to the object while it is being deleted. This scenario is possible if one thread +/// has just entered the destructor, but other is executing Find() and entered +/// the protection section. +/// - Strong pointers will cause circular references and result in memory leaks. +/// \remarks +/// Only weak pointers provide thread-safe solution. The object is either atomically destroyed, +/// so that no other thread can obtain a reference to it through weak pointers. Or it is atomically +/// locked, so that strong reference is obtained. In this case no other thread can destroy the object, +/// because there is at least one strong reference now. Note however that removing the object from the +/// registry in the object's destructor may cause a deadlock at the point where Find() locks the weak pointer: +/// if other thread has started dtor, the object will be locked by Diligent::RefCountedObject::Release(). +/// If after that this thread locks the registry first, it will be waiting for the object to unlock in +/// Diligent::RefCntWeakPtr::Lock(), while the dtor thread will be waiting for the registry to unlock. +template +class StateObjectsRegistry +{ +public: + /// Number of outstanding deleted objects to purge the registry. + static constexpr int DeletedObjectsToPurge = 32; + + StateObjectsRegistry(IMemoryAllocator& RawAllocator, const Char* RegistryName) : + m_DescToObjHashMap(STD_ALLOCATOR_RAW_MEM(HashMapElem, RawAllocator, "Allocator for unordered_map >")), + m_RegistryName{RegistryName} + {} + + ~StateObjectsRegistry() + { + // Object registry is part of the device, and every device + // object holds a strong reference to the device. So device + // is destroyed after all device objects are destroyed, and there + // may only be expired references in the registry. After we + // purge it, the registry must be empty. + Purge(); + VERIFY(m_DescToObjHashMap.empty(), "DescToObjHashMap is not empty"); + } + + /// Adds a new object to the registry + + /// \param [in] ObjectDesc - object description. + /// \param [in] pObject - pointer to the object. + /// + /// Besides adding a new object, the function also checks the number of + /// outstanding deleted objects and calls Purge() if the number has reached + /// the threshold value DeletedObjectsToPurge. Creating a state object is + /// assumed to be an expensive operation and should be performed during + /// the initialization. Occasional purge operations should not add significant + /// cost to it. + void Add(const ResourceDescType& ObjectDesc, IDeviceObject* pObject) + { + ThreadingTools::LockHelper Lock(m_LockFlag); + + // If the number of outstanding deleted objects reached the threshold value, + // purge the registry. Since we have exclusive access now, it is safe + // to do. + if (m_NumDeletedObjects >= DeletedObjectsToPurge) + { + Purge(); + m_NumDeletedObjects = 0; + } + + // Try to construct the new element in place + auto Elems = m_DescToObjHashMap.emplace(std::make_pair(ObjectDesc, Diligent::RefCntWeakPtr(pObject))); + // It is theorertically possible that the same object can be found + // in the registry. This might happen if two threads try to create + // the same object at the same time. They both will not find the + // object and then will create and try to add it. + // + // If the object already exists, we replace the existing reference. + // This is safer as there might be scenarios where existing reference + // might be expired. For instance, two threads try to create the same + // object which is not in the registry. The first thread creates + // the object, adds it to the registry and then releases it. After that + // the second thread creates the same object and tries to add it to + // the registry. It will find an existing expired reference to the + // object. + if (!Elems.second) + { + VERIFY(Elems.first->first == ObjectDesc, "Incorrect object description"); + LOG_WARNING_MESSAGE("Object named '", Elems.first->first.Name, + "' with the same description already exists in the registry." + "Replacing with the new object named '", + ObjectDesc.Name ? ObjectDesc.Name : "", "'."); + Elems.first->second = pObject; + } + } + + /// Finds the object in the registry + void Find(const ResourceDescType& Desc, IDeviceObject** ppObject) + { + VERIFY(*ppObject == nullptr, "Overwriting reference to existing object may cause memory leaks"); + *ppObject = nullptr; + ThreadingTools::LockHelper Lock(m_LockFlag); + + auto It = m_DescToObjHashMap.find(Desc); + if (It != m_DescToObjHashMap.end()) + { + // Try to obtain strong reference to the object. + // This is an atomic operation and we either get + // a new strong reference or object has been destroyed + // and we get null. + auto pObject = It->second.Lock(); + if (pObject) + { + *ppObject = pObject.Detach(); + //LOG_INFO_MESSAGE( "Equivalent of the requested state object named \"", Desc.Name ? Desc.Name : "", "\" found in the ", m_RegistryName, " registry. Reusing existing object."); + } + else + { + // Expired object found: remove it from the map + m_DescToObjHashMap.erase(It); + Atomics::AtomicDecrement(m_NumDeletedObjects); + } + } + } + + /// Purges outstanding deleted objects from the registry + void Purge() + { + Uint32 NumPurgedObjects = 0; + auto It = m_DescToObjHashMap.begin(); + while (It != m_DescToObjHashMap.end()) + { + auto NextIt = It; + ++NextIt; + // Note that IsValid() is not a thread-safe function in the sense that it + // can give false positive results. The only thread-safe way to check if the + // object is alive is to lock the weak pointer, but that requires thread + // synchronization. We will immediately unlock the pointer anyway, so we + // want to detect 100% expired pointers. IsValid() does provide that information + // because once a weak pointer becomes invalid, it will be invalid + // until it is destroyed. It is not a problem if we miss an expired weak + // pointer as it will definitiely be removed next time. + if (!It->second.IsValid()) + { + m_DescToObjHashMap.erase(It); + ++NumPurgedObjects; + } + + It = NextIt; + } + LOG_INFO_MESSAGE("Purged ", NumPurgedObjects, " deleted objects from the ", m_RegistryName, " registry"); + } + + /// Increments the number of outstanding deleted objects. + /// When this number reaches DeletedObjectsToPurge, Purge() will + /// be called. + void ReportDeletedObject() + { + Atomics::AtomicIncrement(m_NumDeletedObjects); + } + +private: + /// Lock flag to protect the m_DescToObjHashMap + ThreadingTools::LockFlag m_LockFlag; + + /// Nmber of outstanding deleted objects that have not been purged + Atomics::AtomicLong m_NumDeletedObjects; + + /// Hash map that stores weak pointers to the referenced objects + typedef std::pair> HashMapElem; + std::unordered_map, std::hash, std::equal_to, STDAllocatorRawMem> m_DescToObjHashMap; + + /// Registry name used for debug output + const String m_RegistryName; +}; +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/SwapChainBase.h b/Graphics/GraphicsEngine/include/SwapChainBase.h deleted file mode 100644 index 7db31f8d..00000000 --- a/Graphics/GraphicsEngine/include/SwapChainBase.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2019-2020 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::SwapChainBase template class - -#include "RenderDevice.h" -#include "DeviceContext.h" -#include "SwapChain.h" -#include "ObjectBase.h" -#include "Errors.h" -#include "RefCntAutoPtr.h" - -namespace Diligent -{ - -/// Base implementation of the swap chain. - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ISwapChainGL, Diligent::ISwapChainD3D11, -/// Diligent::ISwapChainD3D12 or Diligent::ISwapChainVk). -/// \remarks Swap chain holds the strong reference to the device and a weak reference to the -/// immediate context. -template -class SwapChainBase : public ObjectBase -{ -public: - using TObjectBase = ObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this swap chain. - /// \param pDevice - pointer to the device. - /// \param pDeviceContext - pointer to the device context. - /// \param SCDesc - swap chain description - SwapChainBase(IReferenceCounters* pRefCounters, - IRenderDevice* pDevice, - IDeviceContext* pDeviceContext, - const SwapChainDesc& SCDesc) : - // clang-format off - TObjectBase {pRefCounters}, - m_pRenderDevice {pDevice }, - m_wpDeviceContext {pDeviceContext}, - m_SwapChainDesc {SCDesc } - // clang-format on - { - } - - // clang-format off - SwapChainBase (const SwapChainBase&) = delete; - SwapChainBase ( SwapChainBase&&) = delete; - SwapChainBase& operator = (const SwapChainBase&) = delete; - SwapChainBase& operator = ( SwapChainBase&&) = delete; - // clang-format on - - ~SwapChainBase() - { - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_SwapChain, TObjectBase) - - /// Implementation of ISwapChain::GetDesc() - virtual const SwapChainDesc& GetDesc() const override final - { - return m_SwapChainDesc; - } - -protected: - bool Resize(Uint32 NewWidth, Uint32 NewHeight, Int32 Dummy = 0 /*To be different from virtual function*/) - { - if (NewWidth != 0 && NewHeight != 0 && - (m_SwapChainDesc.Width != NewWidth || m_SwapChainDesc.Height != NewHeight)) - { - m_SwapChainDesc.Width = NewWidth; - m_SwapChainDesc.Height = NewHeight; - LOG_INFO_MESSAGE("Resizing the swap chain to ", m_SwapChainDesc.Width, "x", m_SwapChainDesc.Height); - return true; - } - - return false; - } - - /// Strong reference to the render device - RefCntAutoPtr m_pRenderDevice; - - /// Weak references to the immediate device context. The context holds - /// the strong reference to the swap chain. - RefCntWeakPtr m_wpDeviceContext; - - /// Swap chain description - SwapChainDesc m_SwapChainDesc; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/SwapChainBase.hpp b/Graphics/GraphicsEngine/include/SwapChainBase.hpp new file mode 100644 index 00000000..7db31f8d --- /dev/null +++ b/Graphics/GraphicsEngine/include/SwapChainBase.hpp @@ -0,0 +1,118 @@ +/* + * Copyright 2019-2020 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::SwapChainBase template class + +#include "RenderDevice.h" +#include "DeviceContext.h" +#include "SwapChain.h" +#include "ObjectBase.h" +#include "Errors.h" +#include "RefCntAutoPtr.h" + +namespace Diligent +{ + +/// Base implementation of the swap chain. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ISwapChainGL, Diligent::ISwapChainD3D11, +/// Diligent::ISwapChainD3D12 or Diligent::ISwapChainVk). +/// \remarks Swap chain holds the strong reference to the device and a weak reference to the +/// immediate context. +template +class SwapChainBase : public ObjectBase +{ +public: + using TObjectBase = ObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this swap chain. + /// \param pDevice - pointer to the device. + /// \param pDeviceContext - pointer to the device context. + /// \param SCDesc - swap chain description + SwapChainBase(IReferenceCounters* pRefCounters, + IRenderDevice* pDevice, + IDeviceContext* pDeviceContext, + const SwapChainDesc& SCDesc) : + // clang-format off + TObjectBase {pRefCounters}, + m_pRenderDevice {pDevice }, + m_wpDeviceContext {pDeviceContext}, + m_SwapChainDesc {SCDesc } + // clang-format on + { + } + + // clang-format off + SwapChainBase (const SwapChainBase&) = delete; + SwapChainBase ( SwapChainBase&&) = delete; + SwapChainBase& operator = (const SwapChainBase&) = delete; + SwapChainBase& operator = ( SwapChainBase&&) = delete; + // clang-format on + + ~SwapChainBase() + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_SwapChain, TObjectBase) + + /// Implementation of ISwapChain::GetDesc() + virtual const SwapChainDesc& GetDesc() const override final + { + return m_SwapChainDesc; + } + +protected: + bool Resize(Uint32 NewWidth, Uint32 NewHeight, Int32 Dummy = 0 /*To be different from virtual function*/) + { + if (NewWidth != 0 && NewHeight != 0 && + (m_SwapChainDesc.Width != NewWidth || m_SwapChainDesc.Height != NewHeight)) + { + m_SwapChainDesc.Width = NewWidth; + m_SwapChainDesc.Height = NewHeight; + LOG_INFO_MESSAGE("Resizing the swap chain to ", m_SwapChainDesc.Width, "x", m_SwapChainDesc.Height); + return true; + } + + return false; + } + + /// Strong reference to the render device + RefCntAutoPtr m_pRenderDevice; + + /// Weak references to the immediate device context. The context holds + /// the strong reference to the swap chain. + RefCntWeakPtr m_wpDeviceContext; + + /// Swap chain description + SwapChainDesc m_SwapChainDesc; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TextureBase.h b/Graphics/GraphicsEngine/include/TextureBase.h deleted file mode 100644 index 8a3bc8d3..00000000 --- a/Graphics/GraphicsEngine/include/TextureBase.h +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2019-2020 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::TextureBase template class - -#include "Texture.h" -#include "GraphicsTypes.h" -#include "DeviceObjectBase.h" -#include "GraphicsAccessories.hpp" -#include "STDAllocator.h" -#include "FormatString.h" -#include - -namespace Diligent -{ - -struct CopyTextureAttribs; - -void ValidateTextureDesc(const TextureDesc& TexDesc); -void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData); -void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs); -void ValidateMapTextureParams(const TextureDesc& TexDesc, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - Uint32 MapFlags, - const Box* pMapRegion); - -/// Base implementation of the ITexture interface - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ITextureD3D11, Diligent::ITextureD3D12, -/// Diligent::ITextureGL or Diligent::ITextureVk). -/// \tparam TRenderDeviceImpl - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -/// \tparam TTextureViewImpl - type of the texture view implementation -/// (Diligent::TextureViewD3D11Impl, Diligent::TextureViewD3D12Impl, -/// Diligent::TextureViewGLImpl or Diligent::TextureViewVkImpl). -/// \tparam TTexViewObjAllocator - type of the allocator that is used to allocate memory for the texture view object instances -template -class TextureBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - /// \param pRefCounters - reference counters object that controls the lifetime of this texture. - /// \param TexViewObjAllocator - allocator that is used to allocate memory for the instances of the texture view object. - /// This parameter is only used for debug purposes. - /// \param pDevice - pointer to the device - /// \param Desc - texture description - /// \param bIsDeviceInternal - flag indicating if the texture is an internal device object and - /// must not keep a strong reference to the device - TextureBase(IReferenceCounters* pRefCounters, - TTexViewObjAllocator& TexViewObjAllocator, - TRenderDeviceImpl* pDevice, - const TextureDesc& Desc, - bool bIsDeviceInternal = false) : - TDeviceObjectBase(pRefCounters, pDevice, Desc, bIsDeviceInternal), -#ifdef _DEBUG - m_dbgTexViewObjAllocator(TexViewObjAllocator), -#endif - m_pDefaultSRV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultRTV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultDSV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultUAV(nullptr, STDDeleter(TexViewObjAllocator)) - { - if (this->m_Desc.MipLevels == 0) - { - // Compute the number of levels in the full mipmap chain - if (this->m_Desc.Type == RESOURCE_DIM_TEX_1D || - this->m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY) - { - this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width); - } - else if (this->m_Desc.Type == RESOURCE_DIM_TEX_2D || - this->m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || - this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || - this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width, this->m_Desc.Height); - } - else if (this->m_Desc.Type == RESOURCE_DIM_TEX_3D) - { - this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width, this->m_Desc.Height, this->m_Desc.Depth); - } - else - { - UNEXPECTED("Unknown texture type"); - } - } - - Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); - DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, - "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, - ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); - this->m_Desc.CommandQueueMask &= DeviceQueuesMask; - - // Validate correctness of texture description - ValidateTextureDesc(this->m_Desc); - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Texture, TDeviceObjectBase) - - /// Implementaiton of ITexture::CreateView(); calls CreateViewInternal() virtual function that - /// creates texture view for the specific engine implementation. - virtual void CreateView(const struct TextureViewDesc& ViewDesc, ITextureView** ppView) override - { - DEV_CHECK_ERR(ViewDesc.ViewType != TEXTURE_VIEW_UNDEFINED, "Texture view type is not specified"); - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for texture '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); - else if (ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for texture '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); - else if (ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_RENDER_TARGET, "Attempting to create RTV for texture '", this->m_Desc.Name, "' that was not created with BIND_RENDER_TARGET flag"); - else if (ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_DEPTH_STENCIL, "Attempting to create DSV for texture '", this->m_Desc.Name, "' that was not created with BIND_DEPTH_STENCIL flag"); - else - UNEXPECTED("Unexpected texture view type"); - - CreateViewInternal(ViewDesc, ppView, false); - } - - /// Creates default texture views. - - /// - /// - Creates default shader resource view addressing the entire texture if Diligent::BIND_SHADER_RESOURCE flag is set. - /// - Creates default render target view addressing the most detailed mip level if Diligent::BIND_RENDER_TARGET flag is set. - /// - Creates default depth-stencil view addressing the most detailed mip level if Diligent::BIND_DEPTH_STENCIL flag is set. - /// - Creates default unordered access view addressing the entire texture if Diligent::BIND_UNORDERED_ACCESS flag is set. - /// - /// The function calls CreateViewInternal(). - void CreateDefaultViews(); - - virtual void SetState(RESOURCE_STATE State) override final - { - this->m_State = State; - } - - virtual RESOURCE_STATE GetState() const override final - { - return this->m_State; - } - - bool IsInKnownState() const - { - return this->m_State != RESOURCE_STATE_UNKNOWN; - } - - bool CheckState(RESOURCE_STATE State) const - { - VERIFY((State & (State - 1)) == 0, "Single state is expected"); - VERIFY(IsInKnownState(), "Texture state is unknown"); - return (this->m_State & State) == State; - } - - /// Implementation of ITexture::GetDefaultView(). - virtual ITextureView* GetDefaultView(TEXTURE_VIEW_TYPE ViewType) override - { - switch (ViewType) - { - // clang-format off - case TEXTURE_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); - case TEXTURE_VIEW_RENDER_TARGET: return m_pDefaultRTV.get(); - case TEXTURE_VIEW_DEPTH_STENCIL: return m_pDefaultDSV.get(); - case TEXTURE_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); - // clang-format on - default: UNEXPECTED("Unknown view type"); return nullptr; - } - } - -protected: - /// Pure virtual function that creates texture view for the specific engine implementation. - virtual void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) = 0; - -#ifdef _DEBUG - TTexViewObjAllocator& m_dbgTexViewObjAllocator; -#endif - // WARNING! We cannot use ITextureView here, because ITextureView has no virtual dtor! - /// Default SRV addressing the entire texture - std::unique_ptr> m_pDefaultSRV; - /// Default RTV addressing the most detailed mip level - std::unique_ptr> m_pDefaultRTV; - /// Default DSV addressing the most detailed mip level - std::unique_ptr> m_pDefaultDSV; - /// Default UAV addressing the entire texture - std::unique_ptr> m_pDefaultUAV; - - void CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc); - - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; -}; - - -template -void TextureBase::CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc) -{ -#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", this->m_Desc.Name, "': ", ##__VA_ARGS__) - - if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) - TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); - - if (ViewDesc.MostDetailedMip >= this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) - ViewDesc.Format = GetDefaultTextureViewFormat(this->m_Desc.Format, ViewDesc.ViewType, this->m_Desc.BindFlags); - - if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) - { - if (this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - switch (ViewDesc.ViewType) - { - case TEXTURE_VIEW_SHADER_RESOURCE: - ViewDesc.TextureDim = this->m_Desc.Type; - break; - - case TEXTURE_VIEW_RENDER_TARGET: - case TEXTURE_VIEW_DEPTH_STENCIL: - case TEXTURE_VIEW_UNORDERED_ACCESS: - ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; - break; - - default: UNEXPECTED("Unexpected view type"); - } - } - else - { - ViewDesc.TextureDim = this->m_Desc.Type; - } - } - - switch (this->m_Desc.Type) - { - case RESOURCE_DIM_TEX_1D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_3D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_CUBE: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - case RESOURCE_DIM_TEX_CUBE_ARRAY: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - default: - UNEXPECTED("Unexpected texture type"); - break; - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) - TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); - } - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) - TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) - { - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) - TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.FirstArraySlice >= this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", this->m_Desc.ArraySize, ")"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", this->m_Desc.ArraySize, ")"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); - } - else - { - UNEXPECTED("Unexpected texture dimension"); - } - - if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) - { - TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); - } - - if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) - { - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); - - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); - } - -#undef TEX_VIEW_VALIDATION_ERROR - - if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) - { - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - ViewDesc.NumMipLevels = this->m_Desc.MipLevels - ViewDesc.MostDetailedMip; - else - ViewDesc.NumMipLevels = 1; - } - - if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) - { - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - ViewDesc.NumArraySlices = this->m_Desc.ArraySize - ViewDesc.FirstArraySlice; - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; - } - else - ViewDesc.NumArraySlices = 1; - } - - if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && - (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || - ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) - { - const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; - LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" - "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" - "Use UNORM format instead."); - } -} - -template -void TextureBase::CreateDefaultViews() -{ - const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); - if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) - { - // Cannot create default view for TYPELESS formats - return; - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE; - auto ViewName = FormatString("Default SRV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pSRV = nullptr; - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) - ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; - auto ViewName = FormatString("Default RTV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pRTV = nullptr; - CreateViewInternal(ViewDesc, &pRTV, true); - m_pDefaultRTV.reset(static_cast(pRTV)); - VERIFY(m_pDefaultRTV->GetDesc().ViewType == TEXTURE_VIEW_RENDER_TARGET, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL; - auto ViewName = FormatString("Default DSV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pDSV = nullptr; - CreateViewInternal(ViewDesc, &pDSV, true); - m_pDefaultDSV.reset(static_cast(pDSV)); - VERIFY(m_pDefaultDSV->GetDesc().ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS; - auto ViewName = FormatString("Default UAV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; - ITextureView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp new file mode 100644 index 00000000..9e1a29ed --- /dev/null +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -0,0 +1,515 @@ +/* + * Copyright 2019-2020 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::TextureBase template class + +#include "Texture.h" +#include "GraphicsTypes.h" +#include "DeviceObjectBase.hpp" +#include "GraphicsAccessories.hpp" +#include "STDAllocator.h" +#include "FormatString.h" +#include + +namespace Diligent +{ + +struct CopyTextureAttribs; + +void ValidateTextureDesc(const TextureDesc& TexDesc); +void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData); +void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs); +void ValidateMapTextureParams(const TextureDesc& TexDesc, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + Uint32 MapFlags, + const Box* pMapRegion); + +/// Base implementation of the ITexture interface + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ITextureD3D11, Diligent::ITextureD3D12, +/// Diligent::ITextureGL or Diligent::ITextureVk). +/// \tparam TRenderDeviceImpl - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +/// \tparam TTextureViewImpl - type of the texture view implementation +/// (Diligent::TextureViewD3D11Impl, Diligent::TextureViewD3D12Impl, +/// Diligent::TextureViewGLImpl or Diligent::TextureViewVkImpl). +/// \tparam TTexViewObjAllocator - type of the allocator that is used to allocate memory for the texture view object instances +template +class TextureBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this texture. + /// \param TexViewObjAllocator - allocator that is used to allocate memory for the instances of the texture view object. + /// This parameter is only used for debug purposes. + /// \param pDevice - pointer to the device + /// \param Desc - texture description + /// \param bIsDeviceInternal - flag indicating if the texture is an internal device object and + /// must not keep a strong reference to the device + TextureBase(IReferenceCounters* pRefCounters, + TTexViewObjAllocator& TexViewObjAllocator, + TRenderDeviceImpl* pDevice, + const TextureDesc& Desc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase(pRefCounters, pDevice, Desc, bIsDeviceInternal), +#ifdef _DEBUG + m_dbgTexViewObjAllocator(TexViewObjAllocator), +#endif + m_pDefaultSRV(nullptr, STDDeleter(TexViewObjAllocator)), + m_pDefaultRTV(nullptr, STDDeleter(TexViewObjAllocator)), + m_pDefaultDSV(nullptr, STDDeleter(TexViewObjAllocator)), + m_pDefaultUAV(nullptr, STDDeleter(TexViewObjAllocator)) + { + if (this->m_Desc.MipLevels == 0) + { + // Compute the number of levels in the full mipmap chain + if (this->m_Desc.Type == RESOURCE_DIM_TEX_1D || + this->m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY) + { + this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width); + } + else if (this->m_Desc.Type == RESOURCE_DIM_TEX_2D || + this->m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY || + this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || + this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width, this->m_Desc.Height); + } + else if (this->m_Desc.Type == RESOURCE_DIM_TEX_3D) + { + this->m_Desc.MipLevels = ComputeMipLevelsCount(this->m_Desc.Width, this->m_Desc.Height, this->m_Desc.Depth); + } + else + { + UNEXPECTED("Unknown texture type"); + } + } + + Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); + DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, + "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, + ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); + this->m_Desc.CommandQueueMask &= DeviceQueuesMask; + + // Validate correctness of texture description + ValidateTextureDesc(this->m_Desc); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Texture, TDeviceObjectBase) + + /// Implementaiton of ITexture::CreateView(); calls CreateViewInternal() virtual function that + /// creates texture view for the specific engine implementation. + virtual void CreateView(const struct TextureViewDesc& ViewDesc, ITextureView** ppView) override + { + DEV_CHECK_ERR(ViewDesc.ViewType != TEXTURE_VIEW_UNDEFINED, "Texture view type is not specified"); + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for texture '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); + else if (ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for texture '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); + else if (ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_RENDER_TARGET, "Attempting to create RTV for texture '", this->m_Desc.Name, "' that was not created with BIND_RENDER_TARGET flag"); + else if (ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_DEPTH_STENCIL, "Attempting to create DSV for texture '", this->m_Desc.Name, "' that was not created with BIND_DEPTH_STENCIL flag"); + else + UNEXPECTED("Unexpected texture view type"); + + CreateViewInternal(ViewDesc, ppView, false); + } + + /// Creates default texture views. + + /// + /// - Creates default shader resource view addressing the entire texture if Diligent::BIND_SHADER_RESOURCE flag is set. + /// - Creates default render target view addressing the most detailed mip level if Diligent::BIND_RENDER_TARGET flag is set. + /// - Creates default depth-stencil view addressing the most detailed mip level if Diligent::BIND_DEPTH_STENCIL flag is set. + /// - Creates default unordered access view addressing the entire texture if Diligent::BIND_UNORDERED_ACCESS flag is set. + /// + /// The function calls CreateViewInternal(). + void CreateDefaultViews(); + + virtual void SetState(RESOURCE_STATE State) override final + { + this->m_State = State; + } + + virtual RESOURCE_STATE GetState() const override final + { + return this->m_State; + } + + bool IsInKnownState() const + { + return this->m_State != RESOURCE_STATE_UNKNOWN; + } + + bool CheckState(RESOURCE_STATE State) const + { + VERIFY((State & (State - 1)) == 0, "Single state is expected"); + VERIFY(IsInKnownState(), "Texture state is unknown"); + return (this->m_State & State) == State; + } + + /// Implementation of ITexture::GetDefaultView(). + virtual ITextureView* GetDefaultView(TEXTURE_VIEW_TYPE ViewType) override + { + switch (ViewType) + { + // clang-format off + case TEXTURE_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); + case TEXTURE_VIEW_RENDER_TARGET: return m_pDefaultRTV.get(); + case TEXTURE_VIEW_DEPTH_STENCIL: return m_pDefaultDSV.get(); + case TEXTURE_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); + // clang-format on + default: UNEXPECTED("Unknown view type"); return nullptr; + } + } + +protected: + /// Pure virtual function that creates texture view for the specific engine implementation. + virtual void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) = 0; + +#ifdef _DEBUG + TTexViewObjAllocator& m_dbgTexViewObjAllocator; +#endif + // WARNING! We cannot use ITextureView here, because ITextureView has no virtual dtor! + /// Default SRV addressing the entire texture + std::unique_ptr> m_pDefaultSRV; + /// Default RTV addressing the most detailed mip level + std::unique_ptr> m_pDefaultRTV; + /// Default DSV addressing the most detailed mip level + std::unique_ptr> m_pDefaultDSV; + /// Default UAV addressing the entire texture + std::unique_ptr> m_pDefaultUAV; + + void CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc); + + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; +}; + + +template +void TextureBase::CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc) +{ +#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", this->m_Desc.Name, "': ", ##__VA_ARGS__) + + if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) + TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); + + if (ViewDesc.MostDetailedMip >= this->m_Desc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > this->m_Desc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) + ViewDesc.Format = GetDefaultTextureViewFormat(this->m_Desc.Format, ViewDesc.ViewType, this->m_Desc.BindFlags); + + if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) + { + if (this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + switch (ViewDesc.ViewType) + { + case TEXTURE_VIEW_SHADER_RESOURCE: + ViewDesc.TextureDim = this->m_Desc.Type; + break; + + case TEXTURE_VIEW_RENDER_TARGET: + case TEXTURE_VIEW_DEPTH_STENCIL: + case TEXTURE_VIEW_UNORDERED_ACCESS: + ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; + break; + + default: UNEXPECTED("Unexpected view type"); + } + } + else + { + ViewDesc.TextureDim = this->m_Desc.Type; + } + } + + switch (this->m_Desc.Type) + { + case RESOURCE_DIM_TEX_1D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_3D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_CUBE: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + case RESOURCE_DIM_TEX_CUBE_ARRAY: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + default: + UNEXPECTED("Unexpected texture type"); + break; + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) + TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); + } + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) + TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) + { + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) + TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.FirstArraySlice >= this->m_Desc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", this->m_Desc.ArraySize, ")"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > this->m_Desc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", this->m_Desc.ArraySize, ")"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; + if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); + } + else + { + UNEXPECTED("Unexpected texture dimension"); + } + + if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) + { + TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); + } + + if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) + { + if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); + + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); + } + +#undef TEX_VIEW_VALIDATION_ERROR + + if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) + { + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + ViewDesc.NumMipLevels = this->m_Desc.MipLevels - ViewDesc.MostDetailedMip; + else + ViewDesc.NumMipLevels = 1; + } + + if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) + { + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + ViewDesc.NumArraySlices = this->m_Desc.ArraySize - ViewDesc.FirstArraySlice; + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; + ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; + } + else + ViewDesc.NumArraySlices = 1; + } + + if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && + (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || + ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) + { + const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; + LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" + "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" + "Use UNORM format instead."); + } +} + +template +void TextureBase::CreateDefaultViews() +{ + const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); + if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) + { + // Cannot create default view for TYPELESS formats + return; + } + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE; + auto ViewName = FormatString("Default SRV of texture '", this->m_Desc.Name, "'"); + ViewDesc.Name = ViewName.c_str(); + + ITextureView* pSRV = nullptr; + if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) + ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; + CreateViewInternal(ViewDesc, &pSRV, true); + m_pDefaultSRV.reset(static_cast(pSRV)); + VERIFY(m_pDefaultSRV->GetDesc().ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; + auto ViewName = FormatString("Default RTV of texture '", this->m_Desc.Name, "'"); + ViewDesc.Name = ViewName.c_str(); + + ITextureView* pRTV = nullptr; + CreateViewInternal(ViewDesc, &pRTV, true); + m_pDefaultRTV.reset(static_cast(pRTV)); + VERIFY(m_pDefaultRTV->GetDesc().ViewType == TEXTURE_VIEW_RENDER_TARGET, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL; + auto ViewName = FormatString("Default DSV of texture '", this->m_Desc.Name, "'"); + ViewDesc.Name = ViewName.c_str(); + + ITextureView* pDSV = nullptr; + CreateViewInternal(ViewDesc, &pDSV, true); + m_pDefaultDSV.reset(static_cast(pDSV)); + VERIFY(m_pDefaultDSV->GetDesc().ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS; + auto ViewName = FormatString("Default UAV of texture '", this->m_Desc.Name, "'"); + ViewDesc.Name = ViewName.c_str(); + + ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; + ITextureView* pUAV = nullptr; + CreateViewInternal(ViewDesc, &pUAV, true); + m_pDefaultUAV.reset(static_cast(pUAV)); + VERIFY(m_pDefaultUAV->GetDesc().ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TextureViewBase.h b/Graphics/GraphicsEngine/include/TextureViewBase.h deleted file mode 100644 index 3a2c4e90..00000000 --- a/Graphics/GraphicsEngine/include/TextureViewBase.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019-2020 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::TextureViewBase template class - -#include "TextureView.h" -#include "DeviceObjectBase.h" -#include "RefCntAutoPtr.h" -#include "GraphicsAccessories.hpp" - -namespace Diligent -{ - -/// Template class implementing base functionality for a texture view interface - -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ITextureViewD3D11, Diligent::ITextureViewD3D12, -/// Diligent::ITextureViewGL or Diligent::ITextureViewVk). -/// \tparam RenderDeviceImplType - type of the render device implementation -/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, -/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) -template -class TextureViewBase : public DeviceObjectBase -{ -public: - using TDeviceObjectBase = DeviceObjectBase; - - - /// \param pRefCounters - reference counters object that controls the lifetime of this texture view. - /// \param pDevice - pointer to the render device. - /// \param ViewDesc - texture view description. - /// \param pTexture - pointer to the texture that the view is to be created for. - /// \param bIsDefaultView - flag indicating if the view is default view, and is thus - /// part of the texture object. In this case the view will attach - /// to the texture's reference counters. - TextureViewBase(IReferenceCounters* pRefCounters, - RenderDeviceImplType* pDevice, - const TextureViewDesc& ViewDesc, - class ITexture* pTexture, - bool bIsDefaultView) : - // Default views are created as part of the texture, so we cannot not keep strong - // reference to the texture to avoid cyclic links. Instead, we will attach to the - // reference counters of the texture. - TDeviceObjectBase(pRefCounters, pDevice, ViewDesc), - m_pTexture(pTexture), - // For non-default view, we will keep strong reference to texture - m_spTexture(bIsDefaultView ? nullptr : pTexture) - {} - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TextureView, TDeviceObjectBase) - - /// Implementation of ITextureView::SetSampler() - virtual void SetSampler(class ISampler* pSampler) override final - { -#ifdef DEVELOPMENT - if (this->m_Desc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - LOG_ERROR("Texture view \"", this->m_Desc.Name, "\": a sampler can be attached to a shader resource view only. The view type is ", GetTexViewTypeLiteralName(this->m_Desc.ViewType)); -#endif - m_pSampler = pSampler; - } - - /// Implementation of ITextureView::GetSampler() - virtual ISampler* GetSampler() override final - { - return m_pSampler; - } - - const ISampler* GetSampler() const - { - return m_pSampler; - } - - /// Implementation of ITextureView::GetTexture() - virtual ITexture* GetTexture() override final - { - return m_pTexture; - } - - const ITexture* GetTexture() const - { - return m_pTexture; - } - - template - TextureType* GetTexture() - { - return ValidatedCast(m_pTexture); - } - - template - TextureType* GetTexture() const - { - return ValidatedCast(m_pTexture); - } - -protected: - /// Strong reference to the sampler - RefCntAutoPtr m_pSampler; - - /// Raw pointer to the texture - ITexture* const m_pTexture; - - /// Strong reference to the texture. Used for non-default views - /// to keep the texture alive - RefCntAutoPtr m_spTexture; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TextureViewBase.hpp b/Graphics/GraphicsEngine/include/TextureViewBase.hpp new file mode 100644 index 00000000..f9879264 --- /dev/null +++ b/Graphics/GraphicsEngine/include/TextureViewBase.hpp @@ -0,0 +1,135 @@ +/* + * Copyright 2019-2020 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::TextureViewBase template class + +#include "TextureView.h" +#include "DeviceObjectBase.hpp" +#include "RefCntAutoPtr.h" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +/// Template class implementing base functionality for a texture view interface + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ITextureViewD3D11, Diligent::ITextureViewD3D12, +/// Diligent::ITextureViewGL or Diligent::ITextureViewVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template +class TextureViewBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + + /// \param pRefCounters - reference counters object that controls the lifetime of this texture view. + /// \param pDevice - pointer to the render device. + /// \param ViewDesc - texture view description. + /// \param pTexture - pointer to the texture that the view is to be created for. + /// \param bIsDefaultView - flag indicating if the view is default view, and is thus + /// part of the texture object. In this case the view will attach + /// to the texture's reference counters. + TextureViewBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const TextureViewDesc& ViewDesc, + class ITexture* pTexture, + bool bIsDefaultView) : + // Default views are created as part of the texture, so we cannot not keep strong + // reference to the texture to avoid cyclic links. Instead, we will attach to the + // reference counters of the texture. + TDeviceObjectBase(pRefCounters, pDevice, ViewDesc), + m_pTexture(pTexture), + // For non-default view, we will keep strong reference to texture + m_spTexture(bIsDefaultView ? nullptr : pTexture) + {} + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TextureView, TDeviceObjectBase) + + /// Implementation of ITextureView::SetSampler() + virtual void SetSampler(class ISampler* pSampler) override final + { +#ifdef DEVELOPMENT + if (this->m_Desc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + LOG_ERROR("Texture view \"", this->m_Desc.Name, "\": a sampler can be attached to a shader resource view only. The view type is ", GetTexViewTypeLiteralName(this->m_Desc.ViewType)); +#endif + m_pSampler = pSampler; + } + + /// Implementation of ITextureView::GetSampler() + virtual ISampler* GetSampler() override final + { + return m_pSampler; + } + + const ISampler* GetSampler() const + { + return m_pSampler; + } + + /// Implementation of ITextureView::GetTexture() + virtual ITexture* GetTexture() override final + { + return m_pTexture; + } + + const ITexture* GetTexture() const + { + return m_pTexture; + } + + template + TextureType* GetTexture() + { + return ValidatedCast(m_pTexture); + } + + template + TextureType* GetTexture() const + { + return ValidatedCast(m_pTexture); + } + +protected: + /// Strong reference to the sampler + RefCntAutoPtr m_pSampler; + + /// Raw pointer to the texture + ITexture* const m_pTexture; + + /// Strong reference to the texture. Used for non-default views + /// to keep the texture alive + RefCntAutoPtr m_spTexture; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/pch.h b/Graphics/GraphicsEngine/include/pch.h index aa47fb15..1472ead3 100644 --- a/Graphics/GraphicsEngine/include/pch.h +++ b/Graphics/GraphicsEngine/include/pch.h @@ -41,5 +41,5 @@ #include "RefCntAutoPtr.h" #include "Errors.h" #include "DebugUtilities.h" -#include "RenderDeviceBase.h" -#include "DeviceContextBase.h" \ No newline at end of file +#include "RenderDeviceBase.hpp" +#include "DeviceContextBase.hpp" \ No newline at end of file diff --git a/Graphics/GraphicsEngine/src/ResourceMapping.cpp b/Graphics/GraphicsEngine/src/ResourceMapping.cpp index 11acb714..bf34056c 100644 --- a/Graphics/GraphicsEngine/src/ResourceMapping.cpp +++ b/Graphics/GraphicsEngine/src/ResourceMapping.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "ResourceMappingImpl.h" -#include "DeviceObjectBase.h" +#include "ResourceMappingImpl.hpp" +#include "DeviceObjectBase.hpp" using namespace std; diff --git a/Graphics/GraphicsEngineD3D11/CMakeLists.txt b/Graphics/GraphicsEngineD3D11/CMakeLists.txt index ab544ad1..614f6264 100644 --- a/Graphics/GraphicsEngineD3D11/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D11/CMakeLists.txt @@ -4,32 +4,32 @@ project(Diligent-GraphicsEngineD3D11 CXX) set(INCLUDE - include/BufferD3D11Impl.h - include/BufferViewD3D11Impl.h - include/CommandListD3D11Impl.h + include/BufferD3D11Impl.hpp + include/BufferViewD3D11Impl.hpp + include/CommandListD3D11Impl.hpp include/D3D11TypeConversions.h include/D3D11TypeDefinitions.h - include/DeviceContextD3D11Impl.h - include/DisjointQueryPool.h + include/DeviceContextD3D11Impl.hpp + include/DisjointQueryPool.hpp include/EngineD3D11Defines.h include/pch.h - include/FenceD3D11Impl.h - include/PipelineStateD3D11Impl.h - include/QueryD3D11Impl.h - include/RenderDeviceD3D11Impl.h - include/SamplerD3D11Impl.h - include/ShaderD3D11Impl.h - include/ShaderResourceBindingD3D11Impl.h - include/ShaderResourceCacheD3D11.h - include/ShaderResourceLayoutD3D11.h - include/ShaderResourcesD3D11.h - include/SwapChainD3D11Impl.h + include/FenceD3D11Impl.hpp + include/PipelineStateD3D11Impl.hpp + include/QueryD3D11Impl.hpp + include/RenderDeviceD3D11Impl.hpp + include/SamplerD3D11Impl.hpp + include/ShaderD3D11Impl.hpp + include/ShaderResourceBindingD3D11Impl.hpp + include/ShaderResourceCacheD3D11.hpp + include/ShaderResourceLayoutD3D11.hpp + include/ShaderResourcesD3D11.hpp + include/SwapChainD3D11Impl.hpp include/targetver.h - include/Texture1D_D3D11.h - include/Texture2D_D3D11.h - include/Texture3D_D3D11.h - include/TextureBaseD3D11.h - include/TextureViewD3D11Impl.h + include/Texture1D_D3D11.hpp + include/Texture2D_D3D11.hpp + include/Texture3D_D3D11.hpp + include/TextureBaseD3D11.hpp + include/TextureViewD3D11Impl.hpp ) set(INTERFACE diff --git a/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.h deleted file mode 100644 index 77c74f45..00000000 --- a/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::BufferD3D11Impl class - -#include "BufferD3D11.h" -#include "RenderDeviceD3D11.h" -#include "BufferBase.h" -#include "BufferViewD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Buffer object implementation in Direct3D11 backend. -class BufferD3D11Impl final : public BufferBase -{ -public: - using TBufferBase = BufferBase; - - BufferD3D11Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& BuffViewObjMemAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const BufferDesc& BuffDesc, - const BufferData* pBuffData = nullptr); - - BufferD3D11Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& BuffViewObjMemAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const BufferDesc& BuffDesc, - RESOURCE_STATE InitialState, - ID3D11Buffer* pd3d11Buffer); - - ~BufferD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IBufferD3D11::GetD3D11Buffer(). - virtual ID3D11Buffer* GetD3D11Buffer() override final { return m_pd3d11Buffer; } - - /// Implementation of IBuffer::GetNativeHandle(). - virtual void* GetNativeHandle() override final { return GetD3D11Buffer(); } - - void AddState(RESOURCE_STATE State) - { - m_State = static_cast(m_State & ~static_cast(RESOURCE_STATE_UNDEFINED)); - m_State = static_cast(m_State | State); - } - - void ClearState(RESOURCE_STATE State) - { - VERIFY_EXPR(IsInKnownState()); - m_State = static_cast(m_State & ~static_cast(State)); - if (m_State == RESOURCE_STATE_UNKNOWN) - m_State = RESOURCE_STATE_UNDEFINED; - } - -private: - virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) override; - - void CreateUAV(struct BufferViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV); - void CreateSRV(struct BufferViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV); - - friend class DeviceContextD3D11Impl; - CComPtr m_pd3d11Buffer; ///< D3D11 buffer object -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp new file mode 100644 index 00000000..1deb3f91 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp @@ -0,0 +1,97 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::BufferD3D11Impl class + +#include "BufferD3D11.h" +#include "RenderDeviceD3D11.h" +#include "BufferBase.hpp" +#include "BufferViewD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Buffer object implementation in Direct3D11 backend. +class BufferD3D11Impl final : public BufferBase +{ +public: + using TBufferBase = BufferBase; + + BufferD3D11Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& BuffViewObjMemAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const BufferDesc& BuffDesc, + const BufferData* pBuffData = nullptr); + + BufferD3D11Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& BuffViewObjMemAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const BufferDesc& BuffDesc, + RESOURCE_STATE InitialState, + ID3D11Buffer* pd3d11Buffer); + + ~BufferD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IBufferD3D11::GetD3D11Buffer(). + virtual ID3D11Buffer* GetD3D11Buffer() override final { return m_pd3d11Buffer; } + + /// Implementation of IBuffer::GetNativeHandle(). + virtual void* GetNativeHandle() override final { return GetD3D11Buffer(); } + + void AddState(RESOURCE_STATE State) + { + m_State = static_cast(m_State & ~static_cast(RESOURCE_STATE_UNDEFINED)); + m_State = static_cast(m_State | State); + } + + void ClearState(RESOURCE_STATE State) + { + VERIFY_EXPR(IsInKnownState()); + m_State = static_cast(m_State & ~static_cast(State)); + if (m_State == RESOURCE_STATE_UNKNOWN) + m_State = RESOURCE_STATE_UNDEFINED; + } + +private: + virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) override; + + void CreateUAV(struct BufferViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV); + void CreateSRV(struct BufferViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV); + + friend class DeviceContextD3D11Impl; + CComPtr m_pd3d11Buffer; ///< D3D11 buffer object +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.h deleted file mode 100644 index a44eae3a..00000000 --- a/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::BufferViewD3D11Impl class - -#include "BufferViewD3D11.h" -#include "RenderDeviceD3D11.h" -#include "BufferViewBase.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Buffer view implementation in Direct3D11 backend. -class BufferViewD3D11Impl final : public BufferViewBase -{ -public: - using TBufferViewBase = BufferViewBase; - - BufferViewD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pDevice, - const BufferViewDesc& ViewDesc, - class IBuffer* pBuffer, - ID3D11View* pD3D11View, - bool bIsDefaultView); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) final; - - /// Implementation of IBufferViewD3D11::GetD3D11View(). - virtual ID3D11View* GetD3D11View() override final - { - return m_pD3D11View; - } - -protected: - CComPtr m_pD3D11View; /// +{ +public: + using TBufferViewBase = BufferViewBase; + + BufferViewD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + const BufferViewDesc& ViewDesc, + class IBuffer* pBuffer, + ID3D11View* pD3D11View, + bool bIsDefaultView); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) final; + + /// Implementation of IBufferViewD3D11::GetD3D11View(). + virtual ID3D11View* GetD3D11View() override final + { + return m_pD3D11View; + } + +protected: + CComPtr m_pD3D11View; /// -{ -public: - using TCommandListBase = CommandListBase; - - CommandListD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pDevice, - ID3D11CommandList* pd3d11CommandList); - ~CommandListD3D11Impl(); - - ID3D11CommandList* GetD3D11CommandList() { return m_pd3d11CommandList; } - -private: - CComPtr m_pd3d11CommandList; ///< D3D11 CommandList object -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/CommandListD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/CommandListD3D11Impl.hpp new file mode 100644 index 00000000..031e8339 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/CommandListD3D11Impl.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::CommandListD3D11Impl class + +#include "RenderDeviceD3D11.h" +#include "CommandListBase.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Command list implementation in Direct3D11 backend. +class CommandListD3D11Impl final : public CommandListBase +{ +public: + using TCommandListBase = CommandListBase; + + CommandListD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + ID3D11CommandList* pd3d11CommandList); + ~CommandListD3D11Impl(); + + ID3D11CommandList* GetD3D11CommandList() { return m_pd3d11CommandList; } + +private: + CComPtr m_pd3d11CommandList; ///< D3D11 CommandList object +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h deleted file mode 100755 index 162a1285..00000000 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::DeviceContextD3D11Impl class - -#include "DeviceContextD3D11.h" -#include "DeviceContextBase.h" -#include "ShaderD3D11Impl.h" -#include "BufferD3D11Impl.h" -#include "TextureBaseD3D11.h" -#include "PipelineStateD3D11Impl.h" -#include "QueryD3D11Impl.h" -#include "DisjointQueryPool.h" - -#ifdef _DEBUG -# define VERIFY_CONTEXT_BINDINGS -#endif - -namespace Diligent -{ - -class RenderDeviceD3D11Impl; - -struct DeviceContextD3D11ImplTraits -{ - using BufferType = BufferD3D11Impl; - using TextureType = TextureBaseD3D11; - using PipelineStateType = PipelineStateD3D11Impl; - using DeviceType = RenderDeviceD3D11Impl; - using QueryType = QueryD3D11Impl; -}; - -/// Device context implementation in Direct3D11 backend. -class DeviceContextD3D11Impl final : public DeviceContextBase -{ -public: - using TDeviceContextBase = DeviceContextBase; - - DeviceContextD3D11Impl(IReferenceCounters* pRefCounters, - IMemoryAllocator& Allocator, - RenderDeviceD3D11Impl* pDevice, - ID3D11DeviceContext* pd3d11DeviceContext, - const struct EngineD3D11CreateInfo& EngineAttribs, - bool bIsDeferred); - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IDeviceContext::SetPipelineState() in Direct3D11 backend. - virtual void SetPipelineState(IPipelineState* pPipelineState) override final; - - /// Implementation of IDeviceContext::TransitionShaderResources() in Direct3D11 backend. - virtual void TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) override final; - - /// Implementation of IDeviceContext::CommitShaderResources() in Direct3D11 backend. - virtual void CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::SetStencilRef() in Direct3D11 backend. - virtual void SetStencilRef(Uint32 StencilRef) override final; - - /// Implementation of IDeviceContext::SetBlendFactors() in Direct3D11 backend. - virtual void SetBlendFactors(const float* pBlendFactors = nullptr) override final; - - /// Implementation of IDeviceContext::SetVertexBuffers() in Direct3D11 backend. - virtual void SetVertexBuffers(Uint32 StartSlot, - Uint32 NumBuffersSet, - IBuffer** ppBuffers, - Uint32* pOffsets, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - SET_VERTEX_BUFFERS_FLAGS Flags) override final; - - /// Implementation of IDeviceContext::InvalidateState() in Direct3D11 backend. - virtual void InvalidateState() override final; - - /// Implementation of IDeviceContext::SetIndexBuffer() in Direct3D11 backend. - virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::SetViewports() in Direct3D11 backend. - virtual void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight) override final; - - /// Implementation of IDeviceContext::SetScissorRects() in Direct3D11 backend. - virtual void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight) override final; - - /// Implementation of IDeviceContext::SetRenderTargets() in Direct3D11 backend. - virtual void SetRenderTargets(Uint32 NumRenderTargets, - ITextureView* ppRenderTargets[], - ITextureView* pDepthStencil, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::Draw() in Direct3D11 backend. - virtual void Draw(const DrawAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DrawIndexed() in Direct3D11 backend. - virtual void DrawIndexed(const DrawIndexedAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DrawIndirect() in Direct3D11 backend. - virtual void DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - /// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D11 backend. - virtual void DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - - /// Implementation of IDeviceContext::DispatchCompute() in Direct3D11 backend. - virtual void DispatchCompute(const DispatchComputeAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DispatchComputeIndirect() in Direct3D11 backend. - virtual void DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - - /// Implementation of IDeviceContext::ClearDepthStencil() in Direct3D11 backend. - virtual void ClearDepthStencil(ITextureView* pView, - CLEAR_DEPTH_STENCIL_FLAGS ClearFlags, - float fDepth, - Uint8 Stencil, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::ClearRenderTarget() in Direct3D11 backend. - virtual void ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::UpdateBuffer() in Direct3D11 backend. - virtual void UpdateBuffer(IBuffer* pBuffer, - Uint32 Offset, - Uint32 Size, - const void* pData, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::CopyBuffer() in Direct3D11 backend. - virtual void CopyBuffer(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - IBuffer* pDstBuffer, - Uint32 DstOffset, - Uint32 Size, - RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override final; - - /// Implementation of IDeviceContext::MapBuffer() in Direct3D11 backend. - virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override final; - - /// Implementation of IDeviceContext::UnmapBuffer() in Direct3D11 backend. - virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override final; - - /// Implementation of IDeviceContext::UpdateTexture() in Direct3D11 backend. - virtual void UpdateTexture(ITexture* pTexture, - Uint32 MipLevel, - Uint32 Slice, - const Box& DstBox, - const TextureSubResData& SubresData, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::CopyTexture() in Direct3D11 backend. - virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override final; - - /// Implementation of IDeviceContext::MapTextureSubresource() in Direct3D11 backend. - virtual void MapTextureSubresource(ITexture* pTexture, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - MAP_FLAGS MapFlags, - const Box* pMapRegion, - MappedTextureSubresource& MappedData) override final; - - /// Implementation of IDeviceContext::UnmapTextureSubresource() in Direct3D11 backend. - virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override final; - - /// Implementation of IDeviceContext::GenerateMips() in Direct3D11 backend. - virtual void GenerateMips(ITextureView* pTextureView) override final; - - /// Implementation of IDeviceContext::FinishFrame() in Direct3D11 backend. - virtual void FinishFrame() override final; - - /// Implementation of IDeviceContext::TransitionResourceStates() in Direct3D11 backend. - virtual void TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers) override final; - - /// Implementation of IDeviceContext::ResolveTextureSubresource() in Direct3D11 backend. - virtual void ResolveTextureSubresource(ITexture* pSrcTexture, - ITexture* pDstTexture, - const ResolveTextureSubresourceAttribs& ResolveAttribs) override final; - - /// Implementation of IDeviceContext::FinishCommandList() in Direct3D11 backend. - void FinishCommandList(class ICommandList** ppCommandList) override final; - - /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D11 backend. - virtual void ExecuteCommandList(class ICommandList* pCommandList) override final; - - /// Implementation of IDeviceContext::SignalFence() in Direct3D11 backend. - virtual void SignalFence(IFence* pFence, Uint64 Value) override final; - - /// Implementation of IDeviceContext::WaitForFence() in Direct3D11 backend. - virtual void WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext) override final; - - /// Implementation of IDeviceContext::WaitForIdle() in Direct3D11 backend. - virtual void WaitForIdle() override final; - - /// Implementation of IDeviceContext::BeginQuery() in Direct3D11 backend. - virtual void BeginQuery(IQuery* pQuery) override final; - - /// Implementation of IDeviceContext::EndQuery() in Direct3D11 backend. - virtual void EndQuery(IQuery* pQuery) override final; - - /// Implementation of IDeviceContext::Flush() in Direct3D11 backend. - virtual void Flush() override final; - - /// Implementation of IDeviceContextD3D11::GetD3D11DeviceContext(). - virtual ID3D11DeviceContext* GetD3D11DeviceContext() override final { return m_pd3d11DeviceContext; } - - void CommitRenderTargets(); - - /// Clears committed shader resource cache. This function - /// is called once per frame (before present) to release all - /// outstanding objects that are only kept alive by references - /// in the cache. The function does not release cached vertex and - /// index buffers, input layout, depth-stencil, rasterizer, and blend - /// states. - void ReleaseCommittedShaderResources(); - - /// Unbinds all render targets. Used when resizing the swap chain. - virtual void ResetRenderTargets() override final; - - /// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) - static constexpr int NumShaderTypes = 6; - -private: - /// Commits d3d11 index buffer to d3d11 device context. - void CommitD3D11IndexBuffer(VALUE_TYPE IndexType); - - /// Commits d3d11 vertex buffers to d3d11 device context. - void CommitD3D11VertexBuffers(class PipelineStateD3D11Impl* pPipelineStateD3D11); - - /// Helper template function used to facilitate resource unbinding - template - void UnbindResourceView(TD3D11ResourceViewType CommittedD3D11ViewsArr[][NumSlots], - ID3D11Resource* CommittedD3D11ResourcesArr[][NumSlots], - Uint8 NumCommittedResourcesArr[], - ID3D11Resource* pd3d11ResToUndind, - TSetD3D11View SetD3D11ViewMethods[]); - - /// Unbinds a texture from shader resource view slots. - /// \note The function only unbinds the texture from d3d11 device - /// context. All shader bindings are retained. - void UnbindTextureFromInput(TextureBaseD3D11* pTexture, ID3D11Resource* pd3d11Resource); - - /// Unbinds a buffer from input (shader resource views slots, index - /// and vertex buffer slots). - /// \note The function only unbinds the buffer from d3d11 device - /// context. All shader bindings are retained. - void UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3D11Resource* pd3d11Buffer); - - /// Unbinds a resource from UAV slots. - /// \note The function only unbinds the resource from d3d11 device - /// context. All shader bindings are retained. - void UnbindResourceFromUAV(IDeviceObject* pResource, ID3D11Resource* pd3d11Resource); - - /// Unbinds a texture from render target slots. - void UnbindTextureFromRenderTarget(TextureBaseD3D11* pResource); - - /// Unbinds a texture from depth-stencil. - void UnbindTextureFromDepthStencil(TextureBaseD3D11* pTexD3D11); - - /// Prepares for a draw command - __forceinline void PrepareForDraw(DRAW_FLAGS Flags); - - /// Prepares for an indexed draw command - __forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType); - - - template - void TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates); - - void ClearStateCache(); - - CComPtr m_pd3d11DeviceContext; ///< D3D11 device context - - // clang-format off - - /// An array of D3D11 constant buffers committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Buffer* m_CommittedD3D11CBs [NumShaderTypes][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {}; - - /// An array of D3D11 shader resource views committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11ShaderResourceView* m_CommittedD3D11SRVs [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; - - /// An array of D3D11 samplers committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11SamplerState* m_CommittedD3D11Samplers[NumShaderTypes][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {}; - - /// An array of D3D11 UAVs committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11UnorderedAccessView* m_CommittedD3D11UAVs [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; - - /// An array of D3D11 resources commited as SRV to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Resource* m_CommittedD3D11SRVResources [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; - - /// An array of D3D11 resources commited as UAV to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Resource* m_CommittedD3D11UAVResources [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; - - Uint8 m_NumCommittedCBs [NumShaderTypes] = {}; - Uint8 m_NumCommittedSRVs [NumShaderTypes] = {}; - Uint8 m_NumCommittedSamplers[NumShaderTypes] = {}; - Uint8 m_NumCommittedUAVs [NumShaderTypes] = {}; - - // clang-format on - - /// An array of D3D11 vertex buffers committed to D3D device context. - /// There is no need to keep strong references because D3D11 device context - /// already does. Buffers cannot be destroyed while bound to the context. - /// We only mirror all bindings. - ID3D11Buffer* m_CommittedD3D11VertexBuffers[MAX_BUFFER_SLOTS] = {}; - /// An array of strides of committed vertex buffers - UINT m_CommittedD3D11VBStrides[MAX_BUFFER_SLOTS] = {}; - /// An array of offsets of committed vertex buffers - UINT m_CommittedD3D11VBOffsets[MAX_BUFFER_SLOTS] = {}; - /// Number committed vertex buffers - UINT m_NumCommittedD3D11VBs = 0; - /// Flag indicating if currently committed D3D11 vertex buffers are up to date - bool m_bCommittedD3D11VBsUpToDate = false; - - /// D3D11 input layout committed to device context. - /// The context keeps the layout alive, so there is no need - /// to keep strong reference. - ID3D11InputLayout* m_CommittedD3D11InputLayout = nullptr; - - /// Strong reference to D3D11 buffer committed as index buffer - /// to D3D device context. - CComPtr m_CommittedD3D11IndexBuffer; - /// Format of the committed D3D11 index buffer - VALUE_TYPE m_CommittedIBFormat = VT_UNDEFINED; - /// Offset of the committed D3D11 index buffer - Uint32 m_CommittedD3D11IndexDataStartOffset = 0; - /// Flag indicating if currently committed D3D11 index buffer is up to date - bool m_bCommittedD3D11IBUpToDate = false; - - D3D11_PRIMITIVE_TOPOLOGY m_CommittedD3D11PrimTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; - PRIMITIVE_TOPOLOGY m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED; - - /// Strong references to committed D3D11 shaders - CComPtr m_CommittedD3DShaders[NumShaderTypes]; - - const Uint32 m_DebugFlags; - - FixedBlockMemoryAllocator m_CmdListAllocator; - - DisjointQueryPool m_DisjointQueryPool; - std::shared_ptr m_ActiveDisjointQuery; - -#ifdef VERIFY_CONTEXT_BINDINGS - - /// Helper template function used to facilitate context verification - template - void dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], - Uint8 NumCommittedResourcesArr[], - TGetD3D11ResourcesType GetD3D11ResMethods[], - const Char* ResourceName, - SHADER_TYPE ShaderType); - - /// Helper template function used to facilitate validation of SRV and UAV consistency with D3D11 resources - template - void dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], - ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources], - Uint8 NumCommittedResourcesArr[], - const Char* ResourceName, - SHADER_TYPE ShaderType); - - /// Debug function that verifies that SRVs cached in m_CommittedD3D11SRVs - /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); - - /// Debug function that verifies that UAVs cached in m_CommittedD3D11UAVs - /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); - - /// Debug function that verifies that samplers cached in m_CommittedD3D11Samplers - /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); - - /// Debug function that verifies that constant buffers cached in m_CommittedD3D11CBs - /// array comply with buffers actually committed to D3D11 device context - void dbgVerifyCommittedCBs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); - - /// Debug function that verifies that index buffer cached in - /// m_CommittedD3D11IndexBuffer is the buffer actually committed to D3D11 - /// device context - void dbgVerifyCommittedIndexBuffer(); - - /// Debug function that verifies that vertex buffers cached in - /// m_CommittedD3D11VertexBuffers are the buffers actually committed to D3D11 - /// device context - void dbgVerifyCommittedVertexBuffers(); - - /// Debug function that verifies that shaders cached in - /// m_CommittedD3DShaders are the shaders actually committed to D3D11 - /// device context - void dbgVerifyCommittedShaders(); - -#else -# define dbgVerifyRenderTargetFormats(...) -# define dbgVerifyCommittedSRVs(...) -# define dbgVerifyCommittedUAVs(...) -# define dbgVerifyCommittedSamplers(...) -# define dbgVerifyCommittedCBs(...) -# define dbgVerifyCommittedIndexBuffer(...) -# define dbgVerifyCommittedVertexBuffers(...) -# define dbgVerifyCommittedShaders(...) -#endif // VERIFY_CONTEXT_BINDINGS -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp new file mode 100644 index 00000000..f1105509 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -0,0 +1,438 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::DeviceContextD3D11Impl class + +#include "DeviceContextD3D11.h" +#include "DeviceContextBase.hpp" +#include "ShaderD3D11Impl.hpp" +#include "BufferD3D11Impl.hpp" +#include "TextureBaseD3D11.hpp" +#include "PipelineStateD3D11Impl.hpp" +#include "QueryD3D11Impl.hpp" +#include "DisjointQueryPool.hpp" + +#ifdef _DEBUG +# define VERIFY_CONTEXT_BINDINGS +#endif + +namespace Diligent +{ + +class RenderDeviceD3D11Impl; + +struct DeviceContextD3D11ImplTraits +{ + using BufferType = BufferD3D11Impl; + using TextureType = TextureBaseD3D11; + using PipelineStateType = PipelineStateD3D11Impl; + using DeviceType = RenderDeviceD3D11Impl; + using QueryType = QueryD3D11Impl; +}; + +/// Device context implementation in Direct3D11 backend. +class DeviceContextD3D11Impl final : public DeviceContextBase +{ +public: + using TDeviceContextBase = DeviceContextBase; + + DeviceContextD3D11Impl(IReferenceCounters* pRefCounters, + IMemoryAllocator& Allocator, + RenderDeviceD3D11Impl* pDevice, + ID3D11DeviceContext* pd3d11DeviceContext, + const struct EngineD3D11CreateInfo& EngineAttribs, + bool bIsDeferred); + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IDeviceContext::SetPipelineState() in Direct3D11 backend. + virtual void SetPipelineState(IPipelineState* pPipelineState) override final; + + /// Implementation of IDeviceContext::TransitionShaderResources() in Direct3D11 backend. + virtual void TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) override final; + + /// Implementation of IDeviceContext::CommitShaderResources() in Direct3D11 backend. + virtual void CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::SetStencilRef() in Direct3D11 backend. + virtual void SetStencilRef(Uint32 StencilRef) override final; + + /// Implementation of IDeviceContext::SetBlendFactors() in Direct3D11 backend. + virtual void SetBlendFactors(const float* pBlendFactors = nullptr) override final; + + /// Implementation of IDeviceContext::SetVertexBuffers() in Direct3D11 backend. + virtual void SetVertexBuffers(Uint32 StartSlot, + Uint32 NumBuffersSet, + IBuffer** ppBuffers, + Uint32* pOffsets, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + SET_VERTEX_BUFFERS_FLAGS Flags) override final; + + /// Implementation of IDeviceContext::InvalidateState() in Direct3D11 backend. + virtual void InvalidateState() override final; + + /// Implementation of IDeviceContext::SetIndexBuffer() in Direct3D11 backend. + virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::SetViewports() in Direct3D11 backend. + virtual void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight) override final; + + /// Implementation of IDeviceContext::SetScissorRects() in Direct3D11 backend. + virtual void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight) override final; + + /// Implementation of IDeviceContext::SetRenderTargets() in Direct3D11 backend. + virtual void SetRenderTargets(Uint32 NumRenderTargets, + ITextureView* ppRenderTargets[], + ITextureView* pDepthStencil, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::Draw() in Direct3D11 backend. + virtual void Draw(const DrawAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawIndexed() in Direct3D11 backend. + virtual void DrawIndexed(const DrawIndexedAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawIndirect() in Direct3D11 backend. + virtual void DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D11 backend. + virtual void DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + + /// Implementation of IDeviceContext::DispatchCompute() in Direct3D11 backend. + virtual void DispatchCompute(const DispatchComputeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DispatchComputeIndirect() in Direct3D11 backend. + virtual void DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + + /// Implementation of IDeviceContext::ClearDepthStencil() in Direct3D11 backend. + virtual void ClearDepthStencil(ITextureView* pView, + CLEAR_DEPTH_STENCIL_FLAGS ClearFlags, + float fDepth, + Uint8 Stencil, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::ClearRenderTarget() in Direct3D11 backend. + virtual void ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::UpdateBuffer() in Direct3D11 backend. + virtual void UpdateBuffer(IBuffer* pBuffer, + Uint32 Offset, + Uint32 Size, + const void* pData, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::CopyBuffer() in Direct3D11 backend. + virtual void CopyBuffer(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + IBuffer* pDstBuffer, + Uint32 DstOffset, + Uint32 Size, + RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override final; + + /// Implementation of IDeviceContext::MapBuffer() in Direct3D11 backend. + virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override final; + + /// Implementation of IDeviceContext::UnmapBuffer() in Direct3D11 backend. + virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override final; + + /// Implementation of IDeviceContext::UpdateTexture() in Direct3D11 backend. + virtual void UpdateTexture(ITexture* pTexture, + Uint32 MipLevel, + Uint32 Slice, + const Box& DstBox, + const TextureSubResData& SubresData, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::CopyTexture() in Direct3D11 backend. + virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override final; + + /// Implementation of IDeviceContext::MapTextureSubresource() in Direct3D11 backend. + virtual void MapTextureSubresource(ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) override final; + + /// Implementation of IDeviceContext::UnmapTextureSubresource() in Direct3D11 backend. + virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override final; + + /// Implementation of IDeviceContext::GenerateMips() in Direct3D11 backend. + virtual void GenerateMips(ITextureView* pTextureView) override final; + + /// Implementation of IDeviceContext::FinishFrame() in Direct3D11 backend. + virtual void FinishFrame() override final; + + /// Implementation of IDeviceContext::TransitionResourceStates() in Direct3D11 backend. + virtual void TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers) override final; + + /// Implementation of IDeviceContext::ResolveTextureSubresource() in Direct3D11 backend. + virtual void ResolveTextureSubresource(ITexture* pSrcTexture, + ITexture* pDstTexture, + const ResolveTextureSubresourceAttribs& ResolveAttribs) override final; + + /// Implementation of IDeviceContext::FinishCommandList() in Direct3D11 backend. + void FinishCommandList(class ICommandList** ppCommandList) override final; + + /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D11 backend. + virtual void ExecuteCommandList(class ICommandList* pCommandList) override final; + + /// Implementation of IDeviceContext::SignalFence() in Direct3D11 backend. + virtual void SignalFence(IFence* pFence, Uint64 Value) override final; + + /// Implementation of IDeviceContext::WaitForFence() in Direct3D11 backend. + virtual void WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext) override final; + + /// Implementation of IDeviceContext::WaitForIdle() in Direct3D11 backend. + virtual void WaitForIdle() override final; + + /// Implementation of IDeviceContext::BeginQuery() in Direct3D11 backend. + virtual void BeginQuery(IQuery* pQuery) override final; + + /// Implementation of IDeviceContext::EndQuery() in Direct3D11 backend. + virtual void EndQuery(IQuery* pQuery) override final; + + /// Implementation of IDeviceContext::Flush() in Direct3D11 backend. + virtual void Flush() override final; + + /// Implementation of IDeviceContextD3D11::GetD3D11DeviceContext(). + virtual ID3D11DeviceContext* GetD3D11DeviceContext() override final { return m_pd3d11DeviceContext; } + + void CommitRenderTargets(); + + /// Clears committed shader resource cache. This function + /// is called once per frame (before present) to release all + /// outstanding objects that are only kept alive by references + /// in the cache. The function does not release cached vertex and + /// index buffers, input layout, depth-stencil, rasterizer, and blend + /// states. + void ReleaseCommittedShaderResources(); + + /// Unbinds all render targets. Used when resizing the swap chain. + virtual void ResetRenderTargets() override final; + + /// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) + static constexpr int NumShaderTypes = 6; + +private: + /// Commits d3d11 index buffer to d3d11 device context. + void CommitD3D11IndexBuffer(VALUE_TYPE IndexType); + + /// Commits d3d11 vertex buffers to d3d11 device context. + void CommitD3D11VertexBuffers(class PipelineStateD3D11Impl* pPipelineStateD3D11); + + /// Helper template function used to facilitate resource unbinding + template + void UnbindResourceView(TD3D11ResourceViewType CommittedD3D11ViewsArr[][NumSlots], + ID3D11Resource* CommittedD3D11ResourcesArr[][NumSlots], + Uint8 NumCommittedResourcesArr[], + ID3D11Resource* pd3d11ResToUndind, + TSetD3D11View SetD3D11ViewMethods[]); + + /// Unbinds a texture from shader resource view slots. + /// \note The function only unbinds the texture from d3d11 device + /// context. All shader bindings are retained. + void UnbindTextureFromInput(TextureBaseD3D11* pTexture, ID3D11Resource* pd3d11Resource); + + /// Unbinds a buffer from input (shader resource views slots, index + /// and vertex buffer slots). + /// \note The function only unbinds the buffer from d3d11 device + /// context. All shader bindings are retained. + void UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3D11Resource* pd3d11Buffer); + + /// Unbinds a resource from UAV slots. + /// \note The function only unbinds the resource from d3d11 device + /// context. All shader bindings are retained. + void UnbindResourceFromUAV(IDeviceObject* pResource, ID3D11Resource* pd3d11Resource); + + /// Unbinds a texture from render target slots. + void UnbindTextureFromRenderTarget(TextureBaseD3D11* pResource); + + /// Unbinds a texture from depth-stencil. + void UnbindTextureFromDepthStencil(TextureBaseD3D11* pTexD3D11); + + /// Prepares for a draw command + __forceinline void PrepareForDraw(DRAW_FLAGS Flags); + + /// Prepares for an indexed draw command + __forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType); + + + template + void TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates); + + void ClearStateCache(); + + CComPtr m_pd3d11DeviceContext; ///< D3D11 device context + + // clang-format off + + /// An array of D3D11 constant buffers committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Buffer* m_CommittedD3D11CBs [NumShaderTypes][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {}; + + /// An array of D3D11 shader resource views committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11ShaderResourceView* m_CommittedD3D11SRVs [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; + + /// An array of D3D11 samplers committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11SamplerState* m_CommittedD3D11Samplers[NumShaderTypes][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {}; + + /// An array of D3D11 UAVs committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11UnorderedAccessView* m_CommittedD3D11UAVs [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; + + /// An array of D3D11 resources commited as SRV to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Resource* m_CommittedD3D11SRVResources [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; + + /// An array of D3D11 resources commited as UAV to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Resource* m_CommittedD3D11UAVResources [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; + + Uint8 m_NumCommittedCBs [NumShaderTypes] = {}; + Uint8 m_NumCommittedSRVs [NumShaderTypes] = {}; + Uint8 m_NumCommittedSamplers[NumShaderTypes] = {}; + Uint8 m_NumCommittedUAVs [NumShaderTypes] = {}; + + // clang-format on + + /// An array of D3D11 vertex buffers committed to D3D device context. + /// There is no need to keep strong references because D3D11 device context + /// already does. Buffers cannot be destroyed while bound to the context. + /// We only mirror all bindings. + ID3D11Buffer* m_CommittedD3D11VertexBuffers[MAX_BUFFER_SLOTS] = {}; + /// An array of strides of committed vertex buffers + UINT m_CommittedD3D11VBStrides[MAX_BUFFER_SLOTS] = {}; + /// An array of offsets of committed vertex buffers + UINT m_CommittedD3D11VBOffsets[MAX_BUFFER_SLOTS] = {}; + /// Number committed vertex buffers + UINT m_NumCommittedD3D11VBs = 0; + /// Flag indicating if currently committed D3D11 vertex buffers are up to date + bool m_bCommittedD3D11VBsUpToDate = false; + + /// D3D11 input layout committed to device context. + /// The context keeps the layout alive, so there is no need + /// to keep strong reference. + ID3D11InputLayout* m_CommittedD3D11InputLayout = nullptr; + + /// Strong reference to D3D11 buffer committed as index buffer + /// to D3D device context. + CComPtr m_CommittedD3D11IndexBuffer; + /// Format of the committed D3D11 index buffer + VALUE_TYPE m_CommittedIBFormat = VT_UNDEFINED; + /// Offset of the committed D3D11 index buffer + Uint32 m_CommittedD3D11IndexDataStartOffset = 0; + /// Flag indicating if currently committed D3D11 index buffer is up to date + bool m_bCommittedD3D11IBUpToDate = false; + + D3D11_PRIMITIVE_TOPOLOGY m_CommittedD3D11PrimTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + PRIMITIVE_TOPOLOGY m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED; + + /// Strong references to committed D3D11 shaders + CComPtr m_CommittedD3DShaders[NumShaderTypes]; + + const Uint32 m_DebugFlags; + + FixedBlockMemoryAllocator m_CmdListAllocator; + + DisjointQueryPool m_DisjointQueryPool; + std::shared_ptr m_ActiveDisjointQuery; + +#ifdef VERIFY_CONTEXT_BINDINGS + + /// Helper template function used to facilitate context verification + template + void dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], + Uint8 NumCommittedResourcesArr[], + TGetD3D11ResourcesType GetD3D11ResMethods[], + const Char* ResourceName, + SHADER_TYPE ShaderType); + + /// Helper template function used to facilitate validation of SRV and UAV consistency with D3D11 resources + template + void dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], + ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources], + Uint8 NumCommittedResourcesArr[], + const Char* ResourceName, + SHADER_TYPE ShaderType); + + /// Debug function that verifies that SRVs cached in m_CommittedD3D11SRVs + /// array comply with resources actually committed to D3D11 device context + void dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + + /// Debug function that verifies that UAVs cached in m_CommittedD3D11UAVs + /// array comply with resources actually committed to D3D11 device context + void dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + + /// Debug function that verifies that samplers cached in m_CommittedD3D11Samplers + /// array comply with resources actually committed to D3D11 device context + void dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + + /// Debug function that verifies that constant buffers cached in m_CommittedD3D11CBs + /// array comply with buffers actually committed to D3D11 device context + void dbgVerifyCommittedCBs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + + /// Debug function that verifies that index buffer cached in + /// m_CommittedD3D11IndexBuffer is the buffer actually committed to D3D11 + /// device context + void dbgVerifyCommittedIndexBuffer(); + + /// Debug function that verifies that vertex buffers cached in + /// m_CommittedD3D11VertexBuffers are the buffers actually committed to D3D11 + /// device context + void dbgVerifyCommittedVertexBuffers(); + + /// Debug function that verifies that shaders cached in + /// m_CommittedD3DShaders are the shaders actually committed to D3D11 + /// device context + void dbgVerifyCommittedShaders(); + +#else +# define dbgVerifyRenderTargetFormats(...) +# define dbgVerifyCommittedSRVs(...) +# define dbgVerifyCommittedUAVs(...) +# define dbgVerifyCommittedSamplers(...) +# define dbgVerifyCommittedCBs(...) +# define dbgVerifyCommittedIndexBuffer(...) +# define dbgVerifyCommittedVertexBuffers(...) +# define dbgVerifyCommittedShaders(...) +#endif // VERIFY_CONTEXT_BINDINGS +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.h b/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.h deleted file mode 100644 index c9d259ab..00000000 --- a/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::DisjointQueryPool class - -#include - -namespace Diligent -{ - -class DisjointQueryPool final -{ -public: - struct DisjointQueryWrapper - { - DisjointQueryPool& Pool; - CComPtr pd3d11Query; - bool IsEnded = false; - - DisjointQueryWrapper(DisjointQueryPool& _Pool, - CComPtr&& _pd3d11Query) : - Pool(_Pool), - pd3d11Query(std::move(_pd3d11Query)) - { - } - - ~DisjointQueryWrapper() - { - Pool.m_AvailableQueries.emplace_back(std::move(pd3d11Query)); - } - - DisjointQueryWrapper(DisjointQueryWrapper&&) = default; - - DisjointQueryWrapper(const DisjointQueryWrapper&) = delete; - DisjointQueryWrapper& operator=(const DisjointQueryWrapper&) = delete; - DisjointQueryWrapper& operator=(DisjointQueryWrapper&&) = delete; - }; - - std::shared_ptr GetDisjointQuery(ID3D11Device* pd3d11Device) - { - CComPtr pd3d11Query; - if (!m_AvailableQueries.empty()) - { - pd3d11Query = std::move(m_AvailableQueries.back()); - m_AvailableQueries.pop_back(); - } - else - { - pd3d11Query = CreateQuery(pd3d11Device); - } - return std::shared_ptr{new DisjointQueryWrapper{*this, std::move(pd3d11Query)}}; - } - - ~DisjointQueryPool() - { - LOG_INFO_MESSAGE("Disjoint query pool: created ", m_NumQueriesCreated, (m_NumQueriesCreated == 1 ? " query" : " queries")); - } - -private: - CComPtr CreateQuery(ID3D11Device* pd3d11Device) - { - D3D11_QUERY_DESC QueryDesc = {D3D11_QUERY_TIMESTAMP_DISJOINT, 0}; - - CComPtr pd3d11Query; - pd3d11Device->CreateQuery(&QueryDesc, &pd3d11Query); - DEV_CHECK_ERR(pd3d11Query, "Failed to create D3D11 disjoint query"); - ++m_NumQueriesCreated; - return pd3d11Query; - } - std::vector> m_AvailableQueries; - - Uint32 m_NumQueriesCreated = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.hpp b/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.hpp new file mode 100644 index 00000000..c9d259ab --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/DisjointQueryPool.hpp @@ -0,0 +1,102 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::DisjointQueryPool class + +#include + +namespace Diligent +{ + +class DisjointQueryPool final +{ +public: + struct DisjointQueryWrapper + { + DisjointQueryPool& Pool; + CComPtr pd3d11Query; + bool IsEnded = false; + + DisjointQueryWrapper(DisjointQueryPool& _Pool, + CComPtr&& _pd3d11Query) : + Pool(_Pool), + pd3d11Query(std::move(_pd3d11Query)) + { + } + + ~DisjointQueryWrapper() + { + Pool.m_AvailableQueries.emplace_back(std::move(pd3d11Query)); + } + + DisjointQueryWrapper(DisjointQueryWrapper&&) = default; + + DisjointQueryWrapper(const DisjointQueryWrapper&) = delete; + DisjointQueryWrapper& operator=(const DisjointQueryWrapper&) = delete; + DisjointQueryWrapper& operator=(DisjointQueryWrapper&&) = delete; + }; + + std::shared_ptr GetDisjointQuery(ID3D11Device* pd3d11Device) + { + CComPtr pd3d11Query; + if (!m_AvailableQueries.empty()) + { + pd3d11Query = std::move(m_AvailableQueries.back()); + m_AvailableQueries.pop_back(); + } + else + { + pd3d11Query = CreateQuery(pd3d11Device); + } + return std::shared_ptr{new DisjointQueryWrapper{*this, std::move(pd3d11Query)}}; + } + + ~DisjointQueryPool() + { + LOG_INFO_MESSAGE("Disjoint query pool: created ", m_NumQueriesCreated, (m_NumQueriesCreated == 1 ? " query" : " queries")); + } + +private: + CComPtr CreateQuery(ID3D11Device* pd3d11Device) + { + D3D11_QUERY_DESC QueryDesc = {D3D11_QUERY_TIMESTAMP_DISJOINT, 0}; + + CComPtr pd3d11Query; + pd3d11Device->CreateQuery(&QueryDesc, &pd3d11Query); + DEV_CHECK_ERR(pd3d11Query, "Failed to create D3D11 disjoint query"); + ++m_NumQueriesCreated; + return pd3d11Query; + } + std::vector> m_AvailableQueries; + + Uint32 m_NumQueriesCreated = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h deleted file mode 100644 index e4f923de..00000000 --- a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::FenceD3D11Impl class - -#include -#include "FenceD3D11.h" -#include "RenderDeviceD3D11.h" -#include "FenceBase.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Fence implementation in Direct3D11 backend. -class FenceD3D11Impl final : public FenceBase -{ -public: - using TFenceBase = FenceBase; - - FenceD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pDevice, - const FenceDesc& Desc); - ~FenceD3D11Impl(); - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_FenceD3D11, TFenceBase); - - /// Implementation of IFence::GetCompletedValue() in Direct3D11 backend. - virtual Uint64 GetCompletedValue() override final; - - /// Implementation of IFence::Reset() in Direct3D11 backend. - virtual void Reset(Uint64 Value) override final; - - void AddPendingQuery(CComPtr pCtx, CComPtr pQuery, Uint64 Value) - { - m_PendingQueries.emplace_back(std::move(pCtx), std::move(pQuery), Value); - } - - void Wait(Uint64 Value, bool FlushCommands); - -private: - struct PendingFenceData - { - CComPtr pd3d11Ctx; - CComPtr pd3d11Query; - Uint64 Value; - - PendingFenceData(CComPtr pCtx, CComPtr pQuery, Uint64 _Value) : - // clang-format off - pd3d11Ctx {std::move(pCtx)}, - pd3d11Query{std::move(pQuery)}, - Value {_Value} - // clang-format on - {} - }; - std::deque m_PendingQueries; - volatile Uint64 m_LastCompletedFenceValue = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp new file mode 100644 index 00000000..3b08400a --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp @@ -0,0 +1,89 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::FenceD3D11Impl class + +#include +#include "FenceD3D11.h" +#include "RenderDeviceD3D11.h" +#include "FenceBase.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Fence implementation in Direct3D11 backend. +class FenceD3D11Impl final : public FenceBase +{ +public: + using TFenceBase = FenceBase; + + FenceD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + const FenceDesc& Desc); + ~FenceD3D11Impl(); + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_FenceD3D11, TFenceBase); + + /// Implementation of IFence::GetCompletedValue() in Direct3D11 backend. + virtual Uint64 GetCompletedValue() override final; + + /// Implementation of IFence::Reset() in Direct3D11 backend. + virtual void Reset(Uint64 Value) override final; + + void AddPendingQuery(CComPtr pCtx, CComPtr pQuery, Uint64 Value) + { + m_PendingQueries.emplace_back(std::move(pCtx), std::move(pQuery), Value); + } + + void Wait(Uint64 Value, bool FlushCommands); + +private: + struct PendingFenceData + { + CComPtr pd3d11Ctx; + CComPtr pd3d11Query; + Uint64 Value; + + PendingFenceData(CComPtr pCtx, CComPtr pQuery, Uint64 _Value) : + // clang-format off + pd3d11Ctx {std::move(pCtx)}, + pd3d11Query{std::move(pQuery)}, + Value {_Value} + // clang-format on + {} + }; + std::deque m_PendingQueries; + volatile Uint64 m_LastCompletedFenceValue = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.h deleted file mode 100644 index 0a2c9805..00000000 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::PipelineStateD3D11Impl class - -#include "PipelineStateD3D11.h" -#include "RenderDeviceD3D11.h" -#include "PipelineStateBase.h" -#include "ShaderD3D11Impl.h" -#include "SRBMemoryAllocator.hpp" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Pipeline state object implementation in Direct3D11 backend. -class PipelineStateD3D11Impl final : public PipelineStateBase -{ -public: - using TPipelineStateBase = PipelineStateBase; - - PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const PipelineStateDesc& PipelineDesc); - ~PipelineStateD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IPipelineState::BindStaticResources() in Direct3D11 backend. - virtual void BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final; - - /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D11 backend. - virtual Uint32 GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; - - /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D11 backend. - virtual IShaderResourceVariable* GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final; - - /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D11 backend. - virtual IShaderResourceVariable* GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; - - /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D11 backend. - virtual void CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final; - - /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D11 backend. - virtual bool IsCompatibleWith(const IPipelineState* pPSO) const override final; - - - /// Implementation of IPipelineStateD3D11::GetD3D11BlendState() method. - virtual ID3D11BlendState* GetD3D11BlendState() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11RasterizerState() method. - virtual ID3D11RasterizerState* GetD3D11RasterizerState() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11DepthStencilState() method. - virtual ID3D11DepthStencilState* GetD3D11DepthStencilState() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11InputLayout() method. - virtual ID3D11InputLayout* GetD3D11InputLayout() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11VertexShader() method. - virtual ID3D11VertexShader* GetD3D11VertexShader() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11PixelShader() method. - virtual ID3D11PixelShader* GetD3D11PixelShader() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11GeometryShader() method. - virtual ID3D11GeometryShader* GetD3D11GeometryShader() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11DomainShader() method. - virtual ID3D11DomainShader* GetD3D11DomainShader() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11HullShader() method. - virtual ID3D11HullShader* GetD3D11HullShader() override final; - - /// Implementation of IPipelineStateD3D11::GetD3D11ComputeShader() method. - virtual ID3D11ComputeShader* GetD3D11ComputeShader() override final; - - - SRBMemoryAllocator& GetSRBMemoryAllocator() - { - return m_SRBMemAllocator; - } - - const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const - { - VERIFY_EXPR(s < m_NumShaders); - return m_pStaticResourceLayouts[s]; - } - - ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s) - { - VERIFY_EXPR(s < m_NumShaders); - return m_pStaticResourceCaches[s]; - } - - void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; - -private: - CComPtr m_pd3d11BlendState; - CComPtr m_pd3d11RasterizerState; - CComPtr m_pd3d11DepthStencilState; - CComPtr m_pd3d11InputLayout; - - // The caches are indexed by the shader order in the PSO, not shader index - ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr; - ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; - - // SRB memory allocator must be defined before the default shader res binding - SRBMemoryAllocator m_SRBMemAllocator; - - Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; - - Uint16 m_StaticSamplerOffsets[MAX_SHADERS_IN_PIPELINE + 1] = {}; - struct StaticSamplerInfo - { - const D3DShaderResourceAttribs& Attribs; - RefCntAutoPtr pSampler; - StaticSamplerInfo(const D3DShaderResourceAttribs& _Attribs, - RefCntAutoPtr _pSampler) : - // clang-format off - Attribs {_Attribs}, - pSampler {std::move(_pSampler)} - // clang-format on - {} - }; - std::vector> m_StaticSamplers; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp new file mode 100644 index 00000000..59c7b0e8 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -0,0 +1,158 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::PipelineStateD3D11Impl class + +#include "PipelineStateD3D11.h" +#include "RenderDeviceD3D11.h" +#include "PipelineStateBase.hpp" +#include "ShaderD3D11Impl.hpp" +#include "SRBMemoryAllocator.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Pipeline state object implementation in Direct3D11 backend. +class PipelineStateD3D11Impl final : public PipelineStateBase +{ +public: + using TPipelineStateBase = PipelineStateBase; + + PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const PipelineStateDesc& PipelineDesc); + ~PipelineStateD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IPipelineState::BindStaticResources() in Direct3D11 backend. + virtual void BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final; + + /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D11 backend. + virtual Uint32 GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; + + /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D11 backend. + virtual IShaderResourceVariable* GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final; + + /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D11 backend. + virtual IShaderResourceVariable* GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; + + /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D11 backend. + virtual void CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final; + + /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D11 backend. + virtual bool IsCompatibleWith(const IPipelineState* pPSO) const override final; + + + /// Implementation of IPipelineStateD3D11::GetD3D11BlendState() method. + virtual ID3D11BlendState* GetD3D11BlendState() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11RasterizerState() method. + virtual ID3D11RasterizerState* GetD3D11RasterizerState() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11DepthStencilState() method. + virtual ID3D11DepthStencilState* GetD3D11DepthStencilState() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11InputLayout() method. + virtual ID3D11InputLayout* GetD3D11InputLayout() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11VertexShader() method. + virtual ID3D11VertexShader* GetD3D11VertexShader() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11PixelShader() method. + virtual ID3D11PixelShader* GetD3D11PixelShader() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11GeometryShader() method. + virtual ID3D11GeometryShader* GetD3D11GeometryShader() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11DomainShader() method. + virtual ID3D11DomainShader* GetD3D11DomainShader() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11HullShader() method. + virtual ID3D11HullShader* GetD3D11HullShader() override final; + + /// Implementation of IPipelineStateD3D11::GetD3D11ComputeShader() method. + virtual ID3D11ComputeShader* GetD3D11ComputeShader() override final; + + + SRBMemoryAllocator& GetSRBMemoryAllocator() + { + return m_SRBMemAllocator; + } + + const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const + { + VERIFY_EXPR(s < m_NumShaders); + return m_pStaticResourceLayouts[s]; + } + + ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s) + { + VERIFY_EXPR(s < m_NumShaders); + return m_pStaticResourceCaches[s]; + } + + void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; + +private: + CComPtr m_pd3d11BlendState; + CComPtr m_pd3d11RasterizerState; + CComPtr m_pd3d11DepthStencilState; + CComPtr m_pd3d11InputLayout; + + // The caches are indexed by the shader order in the PSO, not shader index + ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr; + ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; + + // SRB memory allocator must be defined before the default shader res binding + SRBMemoryAllocator m_SRBMemAllocator; + + Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; + + Uint16 m_StaticSamplerOffsets[MAX_SHADERS_IN_PIPELINE + 1] = {}; + struct StaticSamplerInfo + { + const D3DShaderResourceAttribs& Attribs; + RefCntAutoPtr pSampler; + StaticSamplerInfo(const D3DShaderResourceAttribs& _Attribs, + RefCntAutoPtr _pSampler) : + // clang-format off + Attribs {_Attribs}, + pSampler {std::move(_pSampler)} + // clang-format on + {} + }; + std::vector> m_StaticSamplers; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.h deleted file mode 100644 index c8611ec0..00000000 --- a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::QueryD3D11Impl class - -#include - -#include "QueryD3D11.h" -#include "QueryBase.h" -#include "RenderDeviceD3D11Impl.h" -#include "DisjointQueryPool.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Query implementation in Direct3D11 backend. -class QueryD3D11Impl final : public QueryBase -{ -public: - using TQueryBase = QueryBase; - - QueryD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pDevice, - const QueryDesc& Desc); - ~QueryD3D11Impl(); - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_QueryD3D11, TQueryBase); - - /// Implementation of IQuery::GetData(). - virtual bool GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) override final; - - /// Implementation of IQuery::Invalidate(). - virtual void Invalidate() override final - { - m_DisjointQuery.reset(); - TQueryBase::Invalidate(); - } - - /// Implementation of IQueryD3D11::GetD3D11Query(). - virtual ID3D11Query* GetD3D11Query() override final - { - return m_pd3d11Query; - } - - void SetDisjointQuery(std::shared_ptr DisjointQuery) - { - m_DisjointQuery = DisjointQuery; - } - -private: - CComPtr m_pd3d11Query; - - std::shared_ptr m_DisjointQuery; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp new file mode 100644 index 00000000..c95ddcd9 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp @@ -0,0 +1,85 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::QueryD3D11Impl class + +#include + +#include "QueryD3D11.h" +#include "QueryBase.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "DisjointQueryPool.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Query implementation in Direct3D11 backend. +class QueryD3D11Impl final : public QueryBase +{ +public: + using TQueryBase = QueryBase; + + QueryD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + const QueryDesc& Desc); + ~QueryD3D11Impl(); + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_QueryD3D11, TQueryBase); + + /// Implementation of IQuery::GetData(). + virtual bool GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) override final; + + /// Implementation of IQuery::Invalidate(). + virtual void Invalidate() override final + { + m_DisjointQuery.reset(); + TQueryBase::Invalidate(); + } + + /// Implementation of IQueryD3D11::GetD3D11Query(). + virtual ID3D11Query* GetD3D11Query() override final + { + return m_pd3d11Query; + } + + void SetDisjointQuery(std::shared_ptr DisjointQuery) + { + m_DisjointQuery = DisjointQuery; + } + +private: + CComPtr m_pd3d11Query; + + std::shared_ptr m_DisjointQuery; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.h deleted file mode 100644 index 17285244..00000000 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::RenderDeviceD3D11Impl class - -#include "RenderDeviceD3D11.h" -#include "RenderDeviceD3DBase.h" -#include "DeviceContextD3D11.h" - -namespace Diligent -{ - -/// Render device implementation in Direct3D11 backend. -class RenderDeviceD3D11Impl final : public RenderDeviceD3DBase -{ -public: - using TRenderDeviceBase = RenderDeviceD3DBase; - - RenderDeviceD3D11Impl(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - IEngineFactory* pEngineFactory, - const EngineD3D11CreateInfo& EngineAttribs, - ID3D11Device* pd3d11Device, - Uint32 NumDeferredContexts); - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IRenderDevice::CreateBuffer() in Direct3D11 backend. - virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer) override final; - - /// Implementation of IRenderDevice::CreateShader() in Direct3D11 backend. - virtual void CreateShader(const ShaderCreateInfo& ShaderCI, IShader** ppShader) override final; - - /// Implementation of IRenderDevice::CreateTexture() in Direct3D11 backend. - virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture) override final; - - /// Implementation of IRenderDevice::CreateSampler() in Direct3D11 backend. - virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; - - /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D11 backend. - virtual void CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState) override final; - - /// Implementation of IRenderDevice::CreateFence() in Direct3D11 backend. - virtual void CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; - - /// Implementation of IRenderDevice::CreateQuery() in Direct3D11 backend. - virtual void CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) override final; - - /// Implementation of IRenderDeviceD3D11::GetD3D11Device() in Direct3D11 backend. - ID3D11Device* GetD3D11Device() override final { return m_pd3d11Device; } - - /// Implementation of IRenderDeviceD3D11::CreateBufferFromD3DResource() in Direct3D11 backend. - virtual void CreateBufferFromD3DResource(ID3D11Buffer* pd3d11Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) override final; - - /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 1D textures in Direct3D11 backend. - virtual void CreateTextureFromD3DResource(ID3D11Texture1D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; - - /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 2D textures in Direct3D11 backend. - virtual void CreateTextureFromD3DResource(ID3D11Texture2D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; - - /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 3D textures in Direct3D11 backend. - virtual void CreateTextureFromD3DResource(ID3D11Texture3D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; - - /// Implementation of IRenderDevice::ReleaseStaleResources() in Direct3D11 backend. - virtual void ReleaseStaleResources(bool ForceRelease = false) override final {} - - /// Implementation of IRenderDevice::IdleGPU() in Direct3D11 backend. - virtual void IdleGPU() override final; - - size_t GetCommandQueueCount() const { return 1; } - Uint64 GetCommandQueueMask() const { return Uint64{1}; } - -private: - virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; - - EngineD3D11CreateInfo m_EngineAttribs; - - /// D3D11 device - CComPtr m_pd3d11Device; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp new file mode 100644 index 00000000..2c23841c --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -0,0 +1,108 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::RenderDeviceD3D11Impl class + +#include "RenderDeviceD3D11.h" +#include "RenderDeviceD3DBase.hpp" +#include "DeviceContextD3D11.h" + +namespace Diligent +{ + +/// Render device implementation in Direct3D11 backend. +class RenderDeviceD3D11Impl final : public RenderDeviceD3DBase +{ +public: + using TRenderDeviceBase = RenderDeviceD3DBase; + + RenderDeviceD3D11Impl(IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + IEngineFactory* pEngineFactory, + const EngineD3D11CreateInfo& EngineAttribs, + ID3D11Device* pd3d11Device, + Uint32 NumDeferredContexts); + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IRenderDevice::CreateBuffer() in Direct3D11 backend. + virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer) override final; + + /// Implementation of IRenderDevice::CreateShader() in Direct3D11 backend. + virtual void CreateShader(const ShaderCreateInfo& ShaderCI, IShader** ppShader) override final; + + /// Implementation of IRenderDevice::CreateTexture() in Direct3D11 backend. + virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture) override final; + + /// Implementation of IRenderDevice::CreateSampler() in Direct3D11 backend. + virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; + + /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D11 backend. + virtual void CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateFence() in Direct3D11 backend. + virtual void CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; + + /// Implementation of IRenderDevice::CreateQuery() in Direct3D11 backend. + virtual void CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) override final; + + /// Implementation of IRenderDeviceD3D11::GetD3D11Device() in Direct3D11 backend. + ID3D11Device* GetD3D11Device() override final { return m_pd3d11Device; } + + /// Implementation of IRenderDeviceD3D11::CreateBufferFromD3DResource() in Direct3D11 backend. + virtual void CreateBufferFromD3DResource(ID3D11Buffer* pd3d11Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) override final; + + /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 1D textures in Direct3D11 backend. + virtual void CreateTextureFromD3DResource(ID3D11Texture1D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; + + /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 2D textures in Direct3D11 backend. + virtual void CreateTextureFromD3DResource(ID3D11Texture2D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; + + /// Implementation of IRenderDeviceD3D11::CreateTextureFromD3DResource() for 3D textures in Direct3D11 backend. + virtual void CreateTextureFromD3DResource(ID3D11Texture3D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; + + /// Implementation of IRenderDevice::ReleaseStaleResources() in Direct3D11 backend. + virtual void ReleaseStaleResources(bool ForceRelease = false) override final {} + + /// Implementation of IRenderDevice::IdleGPU() in Direct3D11 backend. + virtual void IdleGPU() override final; + + size_t GetCommandQueueCount() const { return 1; } + Uint64 GetCommandQueueMask() const { return Uint64{1}; } + +private: + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; + + EngineD3D11CreateInfo m_EngineAttribs; + + /// D3D11 device + CComPtr m_pd3d11Device; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.h deleted file mode 100644 index 6d5d8936..00000000 --- a/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::SamplerD3D11Impl class - -#include "SamplerD3D11.h" -#include "RenderDeviceD3D11.h" -#include "SamplerBase.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Sampler implementation in Direct3D11 backend. -class SamplerD3D11Impl final : public SamplerBase -{ -public: - using TSamplerBase = SamplerBase; - - SamplerD3D11Impl(IReferenceCounters* pRefCounters, - class RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const SamplerDesc& SamplerDesc); - ~SamplerD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ISamplerD3D11::ISamplerD3D11() method. - virtual ID3D11SamplerState* GetD3D11SamplerState() override final { return m_pd3dSampler; } - -private: - /// D3D11 sampler - CComPtr m_pd3dSampler; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp new file mode 100644 index 00000000..6ad866f0 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::SamplerD3D11Impl class + +#include "SamplerD3D11.h" +#include "RenderDeviceD3D11.h" +#include "SamplerBase.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Sampler implementation in Direct3D11 backend. +class SamplerD3D11Impl final : public SamplerBase +{ +public: + using TSamplerBase = SamplerBase; + + SamplerD3D11Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const SamplerDesc& SamplerDesc); + ~SamplerD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ISamplerD3D11::ISamplerD3D11() method. + virtual ID3D11SamplerState* GetD3D11SamplerState() override final { return m_pd3dSampler; } + +private: + /// D3D11 sampler + CComPtr m_pd3dSampler; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.h deleted file mode 100644 index aaaae904..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderD3D11Impl class - -#include "ShaderD3D11.h" -#include "RenderDeviceD3D11.h" -#include "ShaderBase.h" -#include "ShaderD3DBase.h" -#include "ShaderResourceLayoutD3D11.h" -#include "ShaderResourceCacheD3D11.h" -#include "EngineD3D11Defines.h" -#include "ShaderResourcesD3D11.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; -class ResourceMapping; - -/// Shader implementation in Direct3D11 backend. -class ShaderD3D11Impl final : public ShaderBase, public ShaderD3DBase -{ -public: - using TShaderBase = ShaderBase; - - ShaderD3D11Impl(IReferenceCounters* pRefCounters, - class RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const ShaderCreateInfo& ShaderCI); - ~ShaderD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IShader::GetResourceCount() in Direct3D11 backend. - virtual Uint32 GetResourceCount() const override final - { - return m_pShaderResources->GetTotalResources(); - } - - /// Implementation of IShader::GetResource() in Direct3D11 backend. - virtual void GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final - { - ResourceDesc = GetHLSLResource(Index); - } - - /// Implementation of IShaderD3D::GetHLSLResource() method. - virtual HLSLShaderResourceDesc GetHLSLResource(Uint32 Index) const override final - { - return m_pShaderResources->GetHLSLShaderResourceDesc(Index); - } - - /// Implementation of IShaderD3D11::GetD3D11Shader() method. - virtual ID3D11DeviceChild* GetD3D11Shader() override final - { - return m_pShader; - } - - ID3DBlob* GetBytecode() { return m_pShaderByteCode; } - - const std::shared_ptr& GetD3D11Resources() const { return m_pShaderResources; } - -private: - /// D3D11 shader - CComPtr m_pShader; - - // ShaderResources class instance must be referenced through the shared pointer, because - // it is referenced by ShaderResourceLayoutD3D11 class instances - std::shared_ptr m_pShaderResources; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp new file mode 100644 index 00000000..214bedca --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp @@ -0,0 +1,99 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderD3D11Impl class + +#include "ShaderD3D11.h" +#include "RenderDeviceD3D11.h" +#include "ShaderBase.hpp" +#include "ShaderD3DBase.hpp" +#include "ShaderResourceLayoutD3D11.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "EngineD3D11Defines.h" +#include "ShaderResourcesD3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; +class ResourceMapping; + +/// Shader implementation in Direct3D11 backend. +class ShaderD3D11Impl final : public ShaderBase, public ShaderD3DBase +{ +public: + using TShaderBase = ShaderBase; + + ShaderD3D11Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const ShaderCreateInfo& ShaderCI); + ~ShaderD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IShader::GetResourceCount() in Direct3D11 backend. + virtual Uint32 GetResourceCount() const override final + { + return m_pShaderResources->GetTotalResources(); + } + + /// Implementation of IShader::GetResource() in Direct3D11 backend. + virtual void GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final + { + ResourceDesc = GetHLSLResource(Index); + } + + /// Implementation of IShaderD3D::GetHLSLResource() method. + virtual HLSLShaderResourceDesc GetHLSLResource(Uint32 Index) const override final + { + return m_pShaderResources->GetHLSLShaderResourceDesc(Index); + } + + /// Implementation of IShaderD3D11::GetD3D11Shader() method. + virtual ID3D11DeviceChild* GetD3D11Shader() override final + { + return m_pShader; + } + + ID3DBlob* GetBytecode() { return m_pShaderByteCode; } + + const std::shared_ptr& GetD3D11Resources() const { return m_pShaderResources; } + +private: + /// D3D11 shader + CComPtr m_pShader; + + // ShaderResources class instance must be referenced through the shared pointer, because + // it is referenced by ShaderResourceLayoutD3D11 class instances + std::shared_ptr m_pShaderResources; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.h deleted file mode 100755 index bc14042d..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceBindingD3D11Impl class - -#include "ShaderResourceBindingD3D11.h" -#include "RenderDeviceD3D11.h" -#include "ShaderResourceBindingBase.h" -#include "ShaderResourceCacheD3D11.h" -#include "ShaderResourceLayoutD3D11.h" -#include "STDAllocator.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Implementation of shader resource binding object in Direct3D11 backend. -class ShaderResourceBindingD3D11Impl final : public ShaderResourceBindingBase -{ -public: - using TBase = ShaderResourceBindingBase; - - ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, - class PipelineStateD3D11Impl* pPSO, - bool IsInternal); - ~ShaderResourceBindingD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IShaderResourceBinding::BindResources() in Direct3D11 backend. - virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) override final; - - /// Implementation of IShaderResourceBinding::GetVariableByName() in Direct3D11 backend. - virtual IShaderResourceVariable* GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override final; - - /// Implementation of IShaderResourceBinding::GetVariableCount() in Direct3D11 backend. - virtual Uint32 GetVariableCount(SHADER_TYPE ShaderType) const override final; - - /// Implementation of IShaderResourceBinding::GetVariableByIndex() in Direct3D11 backend. - virtual IShaderResourceVariable* GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; - - /// Implementation of IShaderResourceBinding::InitializeStaticResources() in Direct3D11 backend. - virtual void InitializeStaticResources(const IPipelineState* pPipelineState) override final; - - ShaderResourceCacheD3D11& GetResourceCache(Uint32 Ind) - { - VERIFY_EXPR(Ind < m_NumActiveShaders); - return m_pBoundResourceCaches[Ind]; - } - - ShaderResourceLayoutD3D11& GetResourceLayout(Uint32 Ind) - { - VERIFY_EXPR(Ind < m_NumActiveShaders); - return m_pResourceLayouts[Ind]; - } - - inline bool IsStaticResourcesBound() { return m_bIsStaticResourcesBound; } - - Uint32 GetNumActiveShaders() - { - return static_cast(m_NumActiveShaders); - } - - Int32 GetActiveShaderTypeIndex(Uint32 s) { return m_ShaderTypeIndex[s]; } - -private: - // The caches are indexed by the shader order in the PSO, not shader index - ShaderResourceCacheD3D11* m_pBoundResourceCaches = nullptr; - ShaderResourceLayoutD3D11* m_pResourceLayouts = nullptr; - - Int8 m_ShaderTypeIndex[6] = {}; - - // Resource layout index in m_ResourceLayouts[] array for every shader stage - Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; - Uint8 m_NumActiveShaders = 0; - - bool m_bIsStaticResourcesBound = false; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp new file mode 100644 index 00000000..55a6ca2d --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp @@ -0,0 +1,108 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceBindingD3D11Impl class + +#include "ShaderResourceBindingD3D11.h" +#include "RenderDeviceD3D11.h" +#include "ShaderResourceBindingBase.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "ShaderResourceLayoutD3D11.hpp" +#include "STDAllocator.h" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Implementation of shader resource binding object in Direct3D11 backend. +class ShaderResourceBindingD3D11Impl final : public ShaderResourceBindingBase +{ +public: + using TBase = ShaderResourceBindingBase; + + ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, + class PipelineStateD3D11Impl* pPSO, + bool IsInternal); + ~ShaderResourceBindingD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IShaderResourceBinding::BindResources() in Direct3D11 backend. + virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) override final; + + /// Implementation of IShaderResourceBinding::GetVariableByName() in Direct3D11 backend. + virtual IShaderResourceVariable* GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override final; + + /// Implementation of IShaderResourceBinding::GetVariableCount() in Direct3D11 backend. + virtual Uint32 GetVariableCount(SHADER_TYPE ShaderType) const override final; + + /// Implementation of IShaderResourceBinding::GetVariableByIndex() in Direct3D11 backend. + virtual IShaderResourceVariable* GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; + + /// Implementation of IShaderResourceBinding::InitializeStaticResources() in Direct3D11 backend. + virtual void InitializeStaticResources(const IPipelineState* pPipelineState) override final; + + ShaderResourceCacheD3D11& GetResourceCache(Uint32 Ind) + { + VERIFY_EXPR(Ind < m_NumActiveShaders); + return m_pBoundResourceCaches[Ind]; + } + + ShaderResourceLayoutD3D11& GetResourceLayout(Uint32 Ind) + { + VERIFY_EXPR(Ind < m_NumActiveShaders); + return m_pResourceLayouts[Ind]; + } + + inline bool IsStaticResourcesBound() { return m_bIsStaticResourcesBound; } + + Uint32 GetNumActiveShaders() + { + return static_cast(m_NumActiveShaders); + } + + Int32 GetActiveShaderTypeIndex(Uint32 s) { return m_ShaderTypeIndex[s]; } + +private: + // The caches are indexed by the shader order in the PSO, not shader index + ShaderResourceCacheD3D11* m_pBoundResourceCaches = nullptr; + ShaderResourceLayoutD3D11* m_pResourceLayouts = nullptr; + + Int8 m_ShaderTypeIndex[6] = {}; + + // Resource layout index in m_ResourceLayouts[] array for every shader stage + Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; + Uint8 m_NumActiveShaders = 0; + + bool m_bIsStaticResourcesBound = false; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.h deleted file mode 100755 index 2623b5c3..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceCacheD3D11 class - -#include "TextureBaseD3D11.h" -#include "BufferD3D11Impl.h" -#include "SamplerD3D11Impl.h" - -namespace Diligent -{ - -/// The class implements a cache that holds resources bound to a specific shader stage -// All resources are stored in the continuous memory using the following layout: -// -// | CachedCB | ID3D11Buffer* || CachedResource | ID3D11ShaderResourceView* || CachedSampler | ID3D11SamplerState* || CachedResource | ID3D11UnorderedAccessView*|| -// |---------------------------------------------------||--------------------------|---------------------------||------------------------------|-----------------------------||-------------------------|---------------------------|| -// | 0 | 1 | ... | CBCount-1 | 0 | 1 | ...| CBCount-1 || 0 | 1 | ... | SRVCount-1 | 0 | 1 | ... | SRVCount-1 || 0 | 1 | ... | SamplerCount-1 | 0 | 1 | ...| SamplerCount-1 ||0 | 1 | ... | UAVCount-1 | 0 | 1 | ... | UAVCount-1 || -// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -// -// -// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache/ -class ShaderResourceCacheD3D11 -{ -public: - ShaderResourceCacheD3D11() - {} - - ~ShaderResourceCacheD3D11(); - - // clang-format off - ShaderResourceCacheD3D11 (const ShaderResourceCacheD3D11&) = delete; - ShaderResourceCacheD3D11& operator = (const ShaderResourceCacheD3D11&) = delete; - ShaderResourceCacheD3D11 (ShaderResourceCacheD3D11&&) = delete; - ShaderResourceCacheD3D11& operator = (ShaderResourceCacheD3D11&&) = delete; - // clang-format on - - /// Describes a resource associated with a cached constant buffer - struct CachedCB - { - /// Strong reference to the buffer - RefCntAutoPtr pBuff; - - __forceinline void Set(RefCntAutoPtr&& _pBuff) - { - pBuff = std::move(_pBuff); - } - }; - - /// Describes a resource associated with a cached sampler - struct CachedSampler - { - /// Strong reference to the sampler - RefCntAutoPtr pSampler; - - __forceinline void Set(SamplerD3D11Impl* pSam) - { - pSampler = pSam; - } - }; - - /// Describes a resource associated with a cached SRV or a UAV - struct CachedResource - { - /// Wee keep strong reference to the view instead of the reference - /// to the texture or buffer because this is more efficient from - /// performance point of view: this avoids one pair of - /// AddStrongRef()/ReleaseStrongRef(). The view holds strong reference - /// to the texture or the buffer, so it makes no difference. - RefCntAutoPtr pView; - - TextureBaseD3D11* pTexture = nullptr; - BufferD3D11Impl* pBuffer = nullptr; - - // There is no need to keep strong reference to D3D11 resource as - // it is already kept by either pTexture or pBuffer - ID3D11Resource* pd3d11Resource = nullptr; - - CachedResource() noexcept {} - - __forceinline void Set(RefCntAutoPtr&& pTexView) - { - pBuffer = nullptr; - // Avoid unnecessary virtual function calls - pTexture = pTexView ? ValidatedCast(pTexView->TextureViewD3D11Impl::GetTexture()) : nullptr; - pView.Attach(pTexView.Detach()); - pd3d11Resource = pTexture ? pTexture->TextureBaseD3D11::GetD3D11Texture() : nullptr; - } - - __forceinline void Set(RefCntAutoPtr&& pBufView) - { - pTexture = nullptr; - // Avoid unnecessary virtual function calls - pBuffer = pBufView ? ValidatedCast(pBufView->BufferViewD3D11Impl::GetBuffer()) : nullptr; - pView.Attach(pBufView.Detach()); - pd3d11Resource = pBuffer ? pBuffer->BufferD3D11Impl::GetD3D11Buffer() : nullptr; - } - }; - - static size_t GetRequriedMemorySize(const class ShaderResourcesD3D11& Resources); - - void Initialize(const class ShaderResourcesD3D11& Resources, class IMemoryAllocator& MemAllocator); - void Initialize(Uint32 CBCount, Uint32 SRVCount, Uint32 SamplerCount, Uint32 UAVCount, class IMemoryAllocator& MemAllocator); - void Destroy(class IMemoryAllocator& MemAllocator); - - - __forceinline void SetCB(Uint32 Slot, RefCntAutoPtr&& pBuffD3D11Impl) - { - auto* pd3d11Buff = pBuffD3D11Impl ? pBuffD3D11Impl->BufferD3D11Impl::GetD3D11Buffer() : nullptr; - SetD3D11ResourceInternal(Slot, GetCBCount(), &ShaderResourceCacheD3D11::GetCBArrays, std::move(pBuffD3D11Impl), pd3d11Buff); - } - - __forceinline void SetTexSRV(Uint32 Slot, RefCntAutoPtr&& pTexView) - { - auto* pd3d11SRV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pTexView), pd3d11SRV); - } - - __forceinline void SetBufSRV(Uint32 Slot, RefCntAutoPtr&& pBuffView) - { - auto* pd3d11SRV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pBuffView), pd3d11SRV); - } - - __forceinline void SetTexUAV(Uint32 Slot, RefCntAutoPtr&& pTexView) - { - auto* pd3d11UAV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pTexView), pd3d11UAV); - } - - __forceinline void SetBufUAV(Uint32 Slot, RefCntAutoPtr&& pBuffView) - { - auto* pd3d11UAV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pBuffView), pd3d11UAV); - } - - __forceinline void SetSampler(Uint32 Slot, SamplerD3D11Impl* pSampler) - { - auto* pd3d11Sampler = pSampler ? pSampler->SamplerD3D11Impl::GetD3D11SamplerState() : nullptr; - SetD3D11ResourceInternal(Slot, GetSamplerCount(), &ShaderResourceCacheD3D11::GetSamplerArrays, pSampler, pd3d11Sampler); - } - - - - __forceinline CachedCB& GetCB(Uint32 Slot) - { - VERIFY(Slot < GetCBCount(), "CB slot is out of range"); - ShaderResourceCacheD3D11::CachedCB* CBs; - ID3D11Buffer** pd3d11CBs; - GetCBArrays(CBs, pd3d11CBs); - return CBs[Slot]; - } - - __forceinline CachedResource& GetSRV(Uint32 Slot) - { - VERIFY(Slot < GetSRVCount(), "SRV slot is out of range"); - ShaderResourceCacheD3D11::CachedResource* SRVResources; - ID3D11ShaderResourceView** pd3d11SRVs; - GetSRVArrays(SRVResources, pd3d11SRVs); - return SRVResources[Slot]; - } - - __forceinline CachedResource& GetUAV(Uint32 Slot) - { - VERIFY(Slot < GetUAVCount(), "UAV slot is out of range"); - ShaderResourceCacheD3D11::CachedResource* UAVResources; - ID3D11UnorderedAccessView** pd3d11UAVs; - GetUAVArrays(UAVResources, pd3d11UAVs); - return UAVResources[Slot]; - } - - __forceinline CachedSampler& GetSampler(Uint32 Slot) - { - VERIFY(Slot < GetSamplerCount(), "Sampler slot is out of range"); - ShaderResourceCacheD3D11::CachedSampler* Samplers; - ID3D11SamplerState** pd3d11Samplers; - GetSamplerArrays(Samplers, pd3d11Samplers); - return Samplers[Slot]; - } - - - __forceinline bool IsCBBound(Uint32 Slot) const - { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - const_cast(this)->GetCBArrays(CBs, d3d11CBs); - if (Slot < GetCBCount() && d3d11CBs[Slot] != nullptr) - { - VERIFY(CBs[Slot].pBuff != nullptr, "No relevant buffer resource"); - return true; - } - return false; - } - - __forceinline bool IsSRVBound(Uint32 Slot, bool dbgIsTextureView) const - { - CachedResource* SRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - const_cast(this)->GetSRVArrays(SRVResources, d3d11SRVs); - if (Slot < GetSRVCount() && d3d11SRVs[Slot] != nullptr) - { - VERIFY((dbgIsTextureView && SRVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && SRVResources[Slot].pBuffer != nullptr), - "No relevant resource"); - return true; - } - return false; - } - - __forceinline bool IsUAVBound(Uint32 Slot, bool dbgIsTextureView) const - { - CachedResource* UAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - const_cast(this)->GetUAVArrays(UAVResources, d3d11UAVs); - if (Slot < GetUAVCount() && d3d11UAVs[Slot] != nullptr) - { - VERIFY((dbgIsTextureView && UAVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && UAVResources[Slot].pBuffer != nullptr), - "No relevant resource"); - return true; - } - return false; - } - - __forceinline bool IsSamplerBound(Uint32 Slot) const - { - CachedSampler* Samplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - const_cast(this)->GetSamplerArrays(Samplers, d3d11Samplers); - if (Slot < GetSamplerCount() && d3d11Samplers[Slot] != nullptr) - { - VERIFY(Samplers[Slot].pSampler != nullptr, "No relevant sampler"); - return true; - } - return false; - } - - void dbgVerifyCacheConsistency(); - - // clang-format off - __forceinline Uint32 GetCBCount() const { return (m_SRVOffset - m_CBOffset) / (sizeof(CachedCB) + sizeof(ID3D11Buffer*)); } - __forceinline Uint32 GetSRVCount() const { return (m_SamplerOffset - m_SRVOffset) / (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)); } - __forceinline Uint32 GetSamplerCount() const { return (m_UAVOffset - m_SamplerOffset) / (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)); } - __forceinline Uint32 GetUAVCount() const { return (m_MemoryEndOffset - m_UAVOffset) / (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*)); } - // clang-format on - - __forceinline void GetCBArrays(CachedCB*& CBs, ID3D11Buffer**& pd3d11CBs) - { - CBs = reinterpret_cast(m_pResourceData + m_CBOffset); - pd3d11CBs = reinterpret_cast(CBs + GetCBCount()); - } - - __forceinline void GetSRVArrays(CachedResource*& SRVResources, ID3D11ShaderResourceView**& d3d11SRVs) - { - SRVResources = reinterpret_cast(m_pResourceData + m_SRVOffset); - d3d11SRVs = reinterpret_cast(SRVResources + GetSRVCount()); - } - - __forceinline void GetSamplerArrays(CachedSampler*& Samplers, ID3D11SamplerState**& pd3d11Samplers) - { - Samplers = reinterpret_cast(m_pResourceData + m_SamplerOffset); - pd3d11Samplers = reinterpret_cast(Samplers + GetSamplerCount()); - } - - __forceinline void GetUAVArrays(CachedResource*& UAVResources, ID3D11UnorderedAccessView**& pd3d11UAVs) - { - UAVResources = reinterpret_cast(m_pResourceData + m_UAVOffset); - pd3d11UAVs = reinterpret_cast(UAVResources + GetUAVCount()); - } - - __forceinline bool IsInitialized() const - { - return m_MemoryEndOffset != InvalidResourceOffset; - } - -private: - template - __forceinline void SetD3D11ResourceInternal(Uint32 Slot, Uint32 Size, TGetResourceArraysFunc GetArrays, TSrcResourceType&& pResource, TD3D11ResourceType* pd3d11Resource) - { - VERIFY(Slot < Size, "Resource cache is not big enough"); - VERIFY(pResource != nullptr && pd3d11Resource != nullptr || pResource == nullptr && pd3d11Resource == nullptr, - "Resource and D3D11 resource must be set/unset atomically"); - TCachedResourceType* Resources; - TD3D11ResourceType** d3d11ResArr; - (this->*GetArrays)(Resources, d3d11ResArr); - Resources[Slot].Set(std::forward(pResource)); - d3d11ResArr[Slot] = pd3d11Resource; - } - - static constexpr const Uint16 InvalidResourceOffset = 0xFFFF; - // Resource limits in D3D11: - // Max CB count: 14 - // Max SRV count: 128 - // Max Sampler count: 16 - // Max UAV count: 8 - static constexpr const Uint16 m_CBOffset = 0; - Uint16 m_SRVOffset = InvalidResourceOffset; - Uint16 m_SamplerOffset = InvalidResourceOffset; - Uint16 m_UAVOffset = InvalidResourceOffset; - Uint16 m_MemoryEndOffset = InvalidResourceOffset; - - Uint8* m_pResourceData = nullptr; - -#ifdef _DEBUG - IMemoryAllocator* m_pdbgMemoryAllocator = nullptr; -#endif -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp new file mode 100644 index 00000000..ef18f9f0 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp @@ -0,0 +1,334 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceCacheD3D11 class + +#include "TextureBaseD3D11.hpp" +#include "BufferD3D11Impl.hpp" +#include "SamplerD3D11Impl.hpp" + +namespace Diligent +{ + +/// The class implements a cache that holds resources bound to a specific shader stage +// All resources are stored in the continuous memory using the following layout: +// +// | CachedCB | ID3D11Buffer* || CachedResource | ID3D11ShaderResourceView* || CachedSampler | ID3D11SamplerState* || CachedResource | ID3D11UnorderedAccessView*|| +// |---------------------------------------------------||--------------------------|---------------------------||------------------------------|-----------------------------||-------------------------|---------------------------|| +// | 0 | 1 | ... | CBCount-1 | 0 | 1 | ...| CBCount-1 || 0 | 1 | ... | SRVCount-1 | 0 | 1 | ... | SRVCount-1 || 0 | 1 | ... | SamplerCount-1 | 0 | 1 | ...| SamplerCount-1 ||0 | 1 | ... | UAVCount-1 | 0 | 1 | ... | UAVCount-1 || +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// +// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache/ +class ShaderResourceCacheD3D11 +{ +public: + ShaderResourceCacheD3D11() + {} + + ~ShaderResourceCacheD3D11(); + + // clang-format off + ShaderResourceCacheD3D11 (const ShaderResourceCacheD3D11&) = delete; + ShaderResourceCacheD3D11& operator = (const ShaderResourceCacheD3D11&) = delete; + ShaderResourceCacheD3D11 (ShaderResourceCacheD3D11&&) = delete; + ShaderResourceCacheD3D11& operator = (ShaderResourceCacheD3D11&&) = delete; + // clang-format on + + /// Describes a resource associated with a cached constant buffer + struct CachedCB + { + /// Strong reference to the buffer + RefCntAutoPtr pBuff; + + __forceinline void Set(RefCntAutoPtr&& _pBuff) + { + pBuff = std::move(_pBuff); + } + }; + + /// Describes a resource associated with a cached sampler + struct CachedSampler + { + /// Strong reference to the sampler + RefCntAutoPtr pSampler; + + __forceinline void Set(SamplerD3D11Impl* pSam) + { + pSampler = pSam; + } + }; + + /// Describes a resource associated with a cached SRV or a UAV + struct CachedResource + { + /// Wee keep strong reference to the view instead of the reference + /// to the texture or buffer because this is more efficient from + /// performance point of view: this avoids one pair of + /// AddStrongRef()/ReleaseStrongRef(). The view holds strong reference + /// to the texture or the buffer, so it makes no difference. + RefCntAutoPtr pView; + + TextureBaseD3D11* pTexture = nullptr; + BufferD3D11Impl* pBuffer = nullptr; + + // There is no need to keep strong reference to D3D11 resource as + // it is already kept by either pTexture or pBuffer + ID3D11Resource* pd3d11Resource = nullptr; + + CachedResource() noexcept {} + + __forceinline void Set(RefCntAutoPtr&& pTexView) + { + pBuffer = nullptr; + // Avoid unnecessary virtual function calls + pTexture = pTexView ? ValidatedCast(pTexView->TextureViewD3D11Impl::GetTexture()) : nullptr; + pView.Attach(pTexView.Detach()); + pd3d11Resource = pTexture ? pTexture->TextureBaseD3D11::GetD3D11Texture() : nullptr; + } + + __forceinline void Set(RefCntAutoPtr&& pBufView) + { + pTexture = nullptr; + // Avoid unnecessary virtual function calls + pBuffer = pBufView ? ValidatedCast(pBufView->BufferViewD3D11Impl::GetBuffer()) : nullptr; + pView.Attach(pBufView.Detach()); + pd3d11Resource = pBuffer ? pBuffer->BufferD3D11Impl::GetD3D11Buffer() : nullptr; + } + }; + + static size_t GetRequriedMemorySize(const class ShaderResourcesD3D11& Resources); + + void Initialize(const class ShaderResourcesD3D11& Resources, class IMemoryAllocator& MemAllocator); + void Initialize(Uint32 CBCount, Uint32 SRVCount, Uint32 SamplerCount, Uint32 UAVCount, class IMemoryAllocator& MemAllocator); + void Destroy(class IMemoryAllocator& MemAllocator); + + + __forceinline void SetCB(Uint32 Slot, RefCntAutoPtr&& pBuffD3D11Impl) + { + auto* pd3d11Buff = pBuffD3D11Impl ? pBuffD3D11Impl->BufferD3D11Impl::GetD3D11Buffer() : nullptr; + SetD3D11ResourceInternal(Slot, GetCBCount(), &ShaderResourceCacheD3D11::GetCBArrays, std::move(pBuffD3D11Impl), pd3d11Buff); + } + + __forceinline void SetTexSRV(Uint32 Slot, RefCntAutoPtr&& pTexView) + { + auto* pd3d11SRV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; + SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pTexView), pd3d11SRV); + } + + __forceinline void SetBufSRV(Uint32 Slot, RefCntAutoPtr&& pBuffView) + { + auto* pd3d11SRV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; + SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pBuffView), pd3d11SRV); + } + + __forceinline void SetTexUAV(Uint32 Slot, RefCntAutoPtr&& pTexView) + { + auto* pd3d11UAV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; + SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pTexView), pd3d11UAV); + } + + __forceinline void SetBufUAV(Uint32 Slot, RefCntAutoPtr&& pBuffView) + { + auto* pd3d11UAV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; + SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pBuffView), pd3d11UAV); + } + + __forceinline void SetSampler(Uint32 Slot, SamplerD3D11Impl* pSampler) + { + auto* pd3d11Sampler = pSampler ? pSampler->SamplerD3D11Impl::GetD3D11SamplerState() : nullptr; + SetD3D11ResourceInternal(Slot, GetSamplerCount(), &ShaderResourceCacheD3D11::GetSamplerArrays, pSampler, pd3d11Sampler); + } + + + + __forceinline CachedCB& GetCB(Uint32 Slot) + { + VERIFY(Slot < GetCBCount(), "CB slot is out of range"); + ShaderResourceCacheD3D11::CachedCB* CBs; + ID3D11Buffer** pd3d11CBs; + GetCBArrays(CBs, pd3d11CBs); + return CBs[Slot]; + } + + __forceinline CachedResource& GetSRV(Uint32 Slot) + { + VERIFY(Slot < GetSRVCount(), "SRV slot is out of range"); + ShaderResourceCacheD3D11::CachedResource* SRVResources; + ID3D11ShaderResourceView** pd3d11SRVs; + GetSRVArrays(SRVResources, pd3d11SRVs); + return SRVResources[Slot]; + } + + __forceinline CachedResource& GetUAV(Uint32 Slot) + { + VERIFY(Slot < GetUAVCount(), "UAV slot is out of range"); + ShaderResourceCacheD3D11::CachedResource* UAVResources; + ID3D11UnorderedAccessView** pd3d11UAVs; + GetUAVArrays(UAVResources, pd3d11UAVs); + return UAVResources[Slot]; + } + + __forceinline CachedSampler& GetSampler(Uint32 Slot) + { + VERIFY(Slot < GetSamplerCount(), "Sampler slot is out of range"); + ShaderResourceCacheD3D11::CachedSampler* Samplers; + ID3D11SamplerState** pd3d11Samplers; + GetSamplerArrays(Samplers, pd3d11Samplers); + return Samplers[Slot]; + } + + + __forceinline bool IsCBBound(Uint32 Slot) const + { + CachedCB* CBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + const_cast(this)->GetCBArrays(CBs, d3d11CBs); + if (Slot < GetCBCount() && d3d11CBs[Slot] != nullptr) + { + VERIFY(CBs[Slot].pBuff != nullptr, "No relevant buffer resource"); + return true; + } + return false; + } + + __forceinline bool IsSRVBound(Uint32 Slot, bool dbgIsTextureView) const + { + CachedResource* SRVResources = nullptr; + ID3D11ShaderResourceView** d3d11SRVs = nullptr; + const_cast(this)->GetSRVArrays(SRVResources, d3d11SRVs); + if (Slot < GetSRVCount() && d3d11SRVs[Slot] != nullptr) + { + VERIFY((dbgIsTextureView && SRVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && SRVResources[Slot].pBuffer != nullptr), + "No relevant resource"); + return true; + } + return false; + } + + __forceinline bool IsUAVBound(Uint32 Slot, bool dbgIsTextureView) const + { + CachedResource* UAVResources = nullptr; + ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + const_cast(this)->GetUAVArrays(UAVResources, d3d11UAVs); + if (Slot < GetUAVCount() && d3d11UAVs[Slot] != nullptr) + { + VERIFY((dbgIsTextureView && UAVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && UAVResources[Slot].pBuffer != nullptr), + "No relevant resource"); + return true; + } + return false; + } + + __forceinline bool IsSamplerBound(Uint32 Slot) const + { + CachedSampler* Samplers = nullptr; + ID3D11SamplerState** d3d11Samplers = nullptr; + const_cast(this)->GetSamplerArrays(Samplers, d3d11Samplers); + if (Slot < GetSamplerCount() && d3d11Samplers[Slot] != nullptr) + { + VERIFY(Samplers[Slot].pSampler != nullptr, "No relevant sampler"); + return true; + } + return false; + } + + void dbgVerifyCacheConsistency(); + + // clang-format off + __forceinline Uint32 GetCBCount() const { return (m_SRVOffset - m_CBOffset) / (sizeof(CachedCB) + sizeof(ID3D11Buffer*)); } + __forceinline Uint32 GetSRVCount() const { return (m_SamplerOffset - m_SRVOffset) / (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)); } + __forceinline Uint32 GetSamplerCount() const { return (m_UAVOffset - m_SamplerOffset) / (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)); } + __forceinline Uint32 GetUAVCount() const { return (m_MemoryEndOffset - m_UAVOffset) / (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*)); } + // clang-format on + + __forceinline void GetCBArrays(CachedCB*& CBs, ID3D11Buffer**& pd3d11CBs) + { + CBs = reinterpret_cast(m_pResourceData + m_CBOffset); + pd3d11CBs = reinterpret_cast(CBs + GetCBCount()); + } + + __forceinline void GetSRVArrays(CachedResource*& SRVResources, ID3D11ShaderResourceView**& d3d11SRVs) + { + SRVResources = reinterpret_cast(m_pResourceData + m_SRVOffset); + d3d11SRVs = reinterpret_cast(SRVResources + GetSRVCount()); + } + + __forceinline void GetSamplerArrays(CachedSampler*& Samplers, ID3D11SamplerState**& pd3d11Samplers) + { + Samplers = reinterpret_cast(m_pResourceData + m_SamplerOffset); + pd3d11Samplers = reinterpret_cast(Samplers + GetSamplerCount()); + } + + __forceinline void GetUAVArrays(CachedResource*& UAVResources, ID3D11UnorderedAccessView**& pd3d11UAVs) + { + UAVResources = reinterpret_cast(m_pResourceData + m_UAVOffset); + pd3d11UAVs = reinterpret_cast(UAVResources + GetUAVCount()); + } + + __forceinline bool IsInitialized() const + { + return m_MemoryEndOffset != InvalidResourceOffset; + } + +private: + template + __forceinline void SetD3D11ResourceInternal(Uint32 Slot, Uint32 Size, TGetResourceArraysFunc GetArrays, TSrcResourceType&& pResource, TD3D11ResourceType* pd3d11Resource) + { + VERIFY(Slot < Size, "Resource cache is not big enough"); + VERIFY(pResource != nullptr && pd3d11Resource != nullptr || pResource == nullptr && pd3d11Resource == nullptr, + "Resource and D3D11 resource must be set/unset atomically"); + TCachedResourceType* Resources; + TD3D11ResourceType** d3d11ResArr; + (this->*GetArrays)(Resources, d3d11ResArr); + Resources[Slot].Set(std::forward(pResource)); + d3d11ResArr[Slot] = pd3d11Resource; + } + + static constexpr const Uint16 InvalidResourceOffset = 0xFFFF; + // Resource limits in D3D11: + // Max CB count: 14 + // Max SRV count: 128 + // Max Sampler count: 16 + // Max UAV count: 8 + static constexpr const Uint16 m_CBOffset = 0; + Uint16 m_SRVOffset = InvalidResourceOffset; + Uint16 m_SamplerOffset = InvalidResourceOffset; + Uint16 m_UAVOffset = InvalidResourceOffset; + Uint16 m_MemoryEndOffset = InvalidResourceOffset; + + Uint8* m_pResourceData = nullptr; + +#ifdef _DEBUG + IMemoryAllocator* m_pdbgMemoryAllocator = nullptr; +#endif +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h deleted file mode 100644 index 3c42624e..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceLayoutD3D11 class - -#include "ShaderResources.h" -#include "ShaderBase.h" -#include "ShaderResourceCacheD3D11.h" -#include "EngineD3D11Defines.h" -#include "STDAllocator.h" -#include "ShaderVariableD3DBase.h" -#include "ShaderResourcesD3D11.h" - -namespace Diligent -{ - -class IMemoryAllocator; - -/// Diligent::ShaderResourceLayoutD3D11 class -/// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout/ -// sizeof(ShaderResourceLayoutD3D11) == 64 (x64) -class ShaderResourceLayoutD3D11 -{ -public: - ShaderResourceLayoutD3D11(IObject& Owner, - std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - ShaderResourceCacheD3D11& ResourceCache, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator); - ~ShaderResourceLayoutD3D11(); - - // clang-format off - // No copies, only moves are allowed - ShaderResourceLayoutD3D11 (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11& operator = (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11 ( ShaderResourceLayoutD3D11&&) = default; - ShaderResourceLayoutD3D11& operator = ( ShaderResourceLayoutD3D11&&) = delete; - // clang-format on - - static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes); - - void CopyResources(ShaderResourceCacheD3D11& DstCache) const; - - using ShaderVariableD3D11Base = ShaderVariableD3DBase; - - struct ConstBuffBindInfo final : ShaderVariableD3D11Base - { - ConstBuffBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsCBBound(m_Attribs.BindPoint + ArrayIndex); - } - }; - - struct TexSRVBindInfo final : ShaderVariableD3D11Base - { - TexSRVBindInfo(const D3DShaderResourceAttribs& _TextureAttribs, - Uint32 _SamplerIndex, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, _TextureAttribs, VariableType}, - SamplerIndex{_SamplerIndex} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, true); - } - - - bool ValidSamplerAssigned() const { return SamplerIndex != InvalidSamplerIndex; } - - static constexpr Uint32 InvalidSamplerIndex = static_cast(-1); - const Uint32 SamplerIndex; - }; - - struct TexUAVBindInfo final : ShaderVariableD3D11Base - { - TexUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base(ParentResLayout, ResourceAttribs, VariableType) - {} - - // Provide non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - __forceinline virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, true); - } - }; - - struct BuffUAVBindInfo final : ShaderVariableD3D11Base - { - BuffUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, false); - } - }; - - struct BuffSRVBindInfo final : ShaderVariableD3D11Base - { - BuffSRVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, false); - } - }; - - struct SamplerBindInfo final : ShaderVariableD3D11Base - { - SamplerBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSamplerBound(m_Attribs.BindPoint + ArrayIndex); - } - }; - - // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive - // while Layout is alive - void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D11& dbgResourceCache); - -#ifdef DEVELOPMENT - bool dvpVerifyBindings() const; -#endif - - IShaderResourceVariable* GetShaderVariable(const Char* Name); - IShaderResourceVariable* GetShaderVariable(Uint32 Index); - __forceinline SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } - - IObject& GetOwner() { return m_Owner; } - - Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable) const; - Uint32 GetTotalResourceCount() const - { - auto ResourceCount = GetNumCBs() + GetNumTexSRVs() + GetNumTexUAVs() + GetNumBufUAVs() + GetNumBufSRVs(); - // Do not expose sampler variables when using combined texture samplers - if (!m_pResources->IsUsingCombinedTextureSamplers()) - ResourceCount += GetNumSamplers(); - return ResourceCount; - } - - // clang-format off - Uint32 GetNumCBs() const { return (m_TexSRVsOffset - 0 ) / sizeof(ConstBuffBindInfo);} - Uint32 GetNumTexSRVs() const { return (m_TexUAVsOffset - m_TexSRVsOffset ) / sizeof(TexSRVBindInfo); } - Uint32 GetNumTexUAVs() const { return (m_BuffSRVsOffset - m_TexUAVsOffset ) / sizeof(TexUAVBindInfo) ; } - Uint32 GetNumBufSRVs() const { return (m_BuffUAVsOffset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo); } - Uint32 GetNumBufUAVs() const { return (m_SamplerOffset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo); } - Uint32 GetNumSamplers() const { return (m_MemorySize - m_SamplerOffset ) / sizeof(SamplerBindInfo); } - - template Uint32 GetNumResources()const; - template<> Uint32 GetNumResources() const { return GetNumCBs(); } - template<> Uint32 GetNumResources () const { return GetNumTexSRVs(); } - template<> Uint32 GetNumResources () const { return GetNumTexUAVs(); } - template<> Uint32 GetNumResources () const { return GetNumBufSRVs(); } - template<> Uint32 GetNumResources () const { return GetNumBufUAVs(); } - template<> Uint32 GetNumResources () const { return GetNumSamplers(); } - // clang-format on - - const Char* GetShaderName() const - { - return m_pResources->GetShaderName(); - } - -private: - // clang-format off - -/* 0 */ IObject& m_Owner; -/* 8 */ std::shared_ptr m_pResources; - - // No need to use shared pointer, as the resource cache is either part of the same - // ShaderD3D11Impl object, or ShaderResourceBindingD3D11Impl object -/*24*/ ShaderResourceCacheD3D11& m_ResourceCache; - -/*32*/ std::unique_ptr > m_ResourceBuffer; - - // Offsets in bytes - using OffsetType = Uint16; -/*48*/ OffsetType m_TexSRVsOffset = 0; -/*50*/ OffsetType m_TexUAVsOffset = 0; -/*52*/ OffsetType m_BuffSRVsOffset = 0; -/*54*/ OffsetType m_BuffUAVsOffset = 0; -/*56*/ OffsetType m_SamplerOffset = 0; -/*58*/ OffsetType m_MemorySize = 0; -/*60 - 64*/ -/*64*/ // End of data - - - template OffsetType GetResourceOffset()const; - template<> OffsetType GetResourceOffset() const { return 0; } - template<> OffsetType GetResourceOffset () const { return m_TexSRVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_TexUAVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_BuffSRVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_BuffUAVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_SamplerOffset; } - - // clang-format on - - template - ResourceType& GetResource(Uint32 ResIndex) - { - VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); - auto Offset = GetResourceOffset(); - return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; - } - - template - const ResourceType& GetConstResource(Uint32 ResIndex) const - { - VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); - auto Offset = GetResourceOffset(); - return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; - } - - template - IShaderResourceVariable* GetResourceByName(const Char* Name); - - template - void HandleResources(THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV, - THandleSampler HandleSampler) - { - for (Uint32 cb = 0; cb < GetNumResources(); ++cb) - HandleCB(GetResource(cb)); - - for (Uint32 t = 0; t < GetNumResources(); ++t) - HandleTexSRV(GetResource(t)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleTexUAV(GetResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleBufSRV(GetResource(s)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleBufUAV(GetResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleSampler(GetResource(s)); - } - - template - void HandleConstResources(THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV, - THandleSampler HandleSampler) const - { - for (Uint32 cb = 0; cb < GetNumResources(); ++cb) - HandleCB(GetConstResource(cb)); - - for (Uint32 t = 0; t < GetNumResources(); ++t) - HandleTexSRV(GetConstResource(t)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleTexUAV(GetConstResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleBufSRV(GetConstResource(s)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleBufUAV(GetConstResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleSampler(GetConstResource(s)); - } - - friend class ShaderVariableIndexLocator; - friend class ShaderVariableLocator; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp new file mode 100644 index 00000000..9b58ea3c --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp @@ -0,0 +1,415 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceLayoutD3D11 class + +#include "ShaderResources.hpp" +#include "ShaderBase.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "EngineD3D11Defines.h" +#include "STDAllocator.h" +#include "ShaderVariableD3DBase.hpp" +#include "ShaderResourcesD3D11.hpp" + +namespace Diligent +{ + +class IMemoryAllocator; + +/// Diligent::ShaderResourceLayoutD3D11 class +/// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout/ +// sizeof(ShaderResourceLayoutD3D11) == 64 (x64) +class ShaderResourceLayoutD3D11 +{ +public: + ShaderResourceLayoutD3D11(IObject& Owner, + std::shared_ptr pSrcResources, + const PipelineResourceLayoutDesc& ResourceLayout, + const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, + Uint32 NumVarTypes, + ShaderResourceCacheD3D11& ResourceCache, + IMemoryAllocator& ResCacheDataAllocator, + IMemoryAllocator& ResLayoutDataAllocator); + ~ShaderResourceLayoutD3D11(); + + // clang-format off + // No copies, only moves are allowed + ShaderResourceLayoutD3D11 (const ShaderResourceLayoutD3D11&) = delete; + ShaderResourceLayoutD3D11& operator = (const ShaderResourceLayoutD3D11&) = delete; + ShaderResourceLayoutD3D11 ( ShaderResourceLayoutD3D11&&) = default; + ShaderResourceLayoutD3D11& operator = ( ShaderResourceLayoutD3D11&&) = delete; + // clang-format on + + static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, + const PipelineResourceLayoutDesc& ResourceLayout, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); + + void CopyResources(ShaderResourceCacheD3D11& DstCache) const; + + using ShaderVariableD3D11Base = ShaderVariableD3DBase; + + struct ConstBuffBindInfo final : ShaderVariableD3D11Base + { + ConstBuffBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} + {} + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsCBBound(m_Attribs.BindPoint + ArrayIndex); + } + }; + + struct TexSRVBindInfo final : ShaderVariableD3D11Base + { + TexSRVBindInfo(const D3DShaderResourceAttribs& _TextureAttribs, + Uint32 _SamplerIndex, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base{ParentResLayout, _TextureAttribs, VariableType}, + SamplerIndex{_SamplerIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, true); + } + + + bool ValidSamplerAssigned() const { return SamplerIndex != InvalidSamplerIndex; } + + static constexpr Uint32 InvalidSamplerIndex = static_cast(-1); + const Uint32 SamplerIndex; + }; + + struct TexUAVBindInfo final : ShaderVariableD3D11Base + { + TexUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base(ParentResLayout, ResourceAttribs, VariableType) + {} + + // Provide non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + __forceinline virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, true); + } + }; + + struct BuffUAVBindInfo final : ShaderVariableD3D11Base + { + BuffUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, false); + } + }; + + struct BuffSRVBindInfo final : ShaderVariableD3D11Base + { + BuffSRVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, false); + } + }; + + struct SamplerBindInfo final : ShaderVariableD3D11Base + { + SamplerBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, + ShaderResourceLayoutD3D11& ParentResLayout, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); + return m_ParentResLayout.m_ResourceCache.IsSamplerBound(m_Attribs.BindPoint + ArrayIndex); + } + }; + + // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive + // while Layout is alive + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D11& dbgResourceCache); + +#ifdef DEVELOPMENT + bool dvpVerifyBindings() const; +#endif + + IShaderResourceVariable* GetShaderVariable(const Char* Name); + IShaderResourceVariable* GetShaderVariable(Uint32 Index); + __forceinline SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } + + IObject& GetOwner() { return m_Owner; } + + Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable) const; + Uint32 GetTotalResourceCount() const + { + auto ResourceCount = GetNumCBs() + GetNumTexSRVs() + GetNumTexUAVs() + GetNumBufUAVs() + GetNumBufSRVs(); + // Do not expose sampler variables when using combined texture samplers + if (!m_pResources->IsUsingCombinedTextureSamplers()) + ResourceCount += GetNumSamplers(); + return ResourceCount; + } + + // clang-format off + Uint32 GetNumCBs() const { return (m_TexSRVsOffset - 0 ) / sizeof(ConstBuffBindInfo);} + Uint32 GetNumTexSRVs() const { return (m_TexUAVsOffset - m_TexSRVsOffset ) / sizeof(TexSRVBindInfo); } + Uint32 GetNumTexUAVs() const { return (m_BuffSRVsOffset - m_TexUAVsOffset ) / sizeof(TexUAVBindInfo) ; } + Uint32 GetNumBufSRVs() const { return (m_BuffUAVsOffset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo); } + Uint32 GetNumBufUAVs() const { return (m_SamplerOffset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo); } + Uint32 GetNumSamplers() const { return (m_MemorySize - m_SamplerOffset ) / sizeof(SamplerBindInfo); } + + template Uint32 GetNumResources()const; + template<> Uint32 GetNumResources() const { return GetNumCBs(); } + template<> Uint32 GetNumResources () const { return GetNumTexSRVs(); } + template<> Uint32 GetNumResources () const { return GetNumTexUAVs(); } + template<> Uint32 GetNumResources () const { return GetNumBufSRVs(); } + template<> Uint32 GetNumResources () const { return GetNumBufUAVs(); } + template<> Uint32 GetNumResources () const { return GetNumSamplers(); } + // clang-format on + + const Char* GetShaderName() const + { + return m_pResources->GetShaderName(); + } + +private: + // clang-format off + +/* 0 */ IObject& m_Owner; +/* 8 */ std::shared_ptr m_pResources; + + // No need to use shared pointer, as the resource cache is either part of the same + // ShaderD3D11Impl object, or ShaderResourceBindingD3D11Impl object +/*24*/ ShaderResourceCacheD3D11& m_ResourceCache; + +/*32*/ std::unique_ptr > m_ResourceBuffer; + + // Offsets in bytes + using OffsetType = Uint16; +/*48*/ OffsetType m_TexSRVsOffset = 0; +/*50*/ OffsetType m_TexUAVsOffset = 0; +/*52*/ OffsetType m_BuffSRVsOffset = 0; +/*54*/ OffsetType m_BuffUAVsOffset = 0; +/*56*/ OffsetType m_SamplerOffset = 0; +/*58*/ OffsetType m_MemorySize = 0; +/*60 - 64*/ +/*64*/ // End of data + + + template OffsetType GetResourceOffset()const; + template<> OffsetType GetResourceOffset() const { return 0; } + template<> OffsetType GetResourceOffset () const { return m_TexSRVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_TexUAVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_BuffSRVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_BuffUAVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_SamplerOffset; } + + // clang-format on + + template + ResourceType& GetResource(Uint32 ResIndex) + { + VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); + auto Offset = GetResourceOffset(); + return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; + } + + template + const ResourceType& GetConstResource(Uint32 ResIndex) const + { + VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); + auto Offset = GetResourceOffset(); + return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; + } + + template + IShaderResourceVariable* GetResourceByName(const Char* Name); + + template + void HandleResources(THandleCB HandleCB, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleSampler HandleSampler) + { + for (Uint32 cb = 0; cb < GetNumResources(); ++cb) + HandleCB(GetResource(cb)); + + for (Uint32 t = 0; t < GetNumResources(); ++t) + HandleTexSRV(GetResource(t)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleTexUAV(GetResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleBufSRV(GetResource(s)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleBufUAV(GetResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleSampler(GetResource(s)); + } + + template + void HandleConstResources(THandleCB HandleCB, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleSampler HandleSampler) const + { + for (Uint32 cb = 0; cb < GetNumResources(); ++cb) + HandleCB(GetConstResource(cb)); + + for (Uint32 t = 0; t < GetNumResources(); ++t) + HandleTexSRV(GetConstResource(t)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleTexUAV(GetConstResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleBufSRV(GetConstResource(s)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleBufUAV(GetConstResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleSampler(GetConstResource(s)); + } + + friend class ShaderVariableIndexLocator; + friend class ShaderVariableLocator; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h deleted file mode 100644 index 5e3ac600..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourcesD3D11 class - - -// ShaderResourcesD3D11 are created by ShaderD3D11Impl instances. They are then referenced by ShaderResourceLayoutD3D11 objects, which are in turn -// created by instances of ShaderResourceBindingsD3D11Impl and PipelineStateD3D11Impl -// -// _________________ -// | | -// | ShaderD3D11Impl | -// |_________________| -// | -// |shared_ptr -// ________V_____________ _____________________________________________________________________ -// | | unique_ptr | | | | | | | -// | ShaderResourcesD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | -// |______________________| |________|___________|___________|___________|___________|____________| -// A A A A A A A -// | \ \ \ \ \ \ -// |shared_ptr Ref Ref Ref Ref Ref Ref -// ________|__________________ ____\_________\__________\__________\___________\_______ ___\______ -// | | unique_ptr | | | | | | | -// | ShaderResourceLayoutD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | -// |___________________________| |________|___________|___________|___________|___________|__________| -// | A -// |_________________SamplerIndex_________________| -// -// -// One ShaderResourcesD3D11 instance can be referenced by multiple objects -// -// -// _______ ________________________________ -// | | | | -// ----| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | -// | |___________________________| |________________________________| -// | -// | -// _________________ ______________________ | _______ ________________________________ -// | | shared_ptr | | shared_ptr| | | | | -// | ShaderD3D11Impl |--------------->| ShaderResourcesD3D11 |<---------------| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | -// |_________________| |______________________| | |___________________________| |________________________________| -// A | -// | | -// __________ | | _______ ________________________________ -// | | shared_ptr | | | | | | -// | ShaderResourceLayoutD3D11 |------------------- ----| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | -// |___________________________| |___________________________| |________________________________| -// A -// ___________|______________ -// | | -// | PipelineStateD3D11Impl | -// |__________________________| -// - -#include - -#include "ShaderResources.h" - -namespace Diligent -{ - -/// Diligent::ShaderResourcesD3D11 class -class ShaderResourcesD3D11 : public ShaderResources -{ -public: - // Loads shader resources from the compiled shader bytecode - ShaderResourcesD3D11(class RenderDeviceD3D11Impl* pDeviceD3D11Impl, - ID3DBlob* pShaderBytecode, - const ShaderDesc& ShdrDesc, - const char* CombinedSamplerSuffix); - ~ShaderResourcesD3D11(); - - // clang-format off - ShaderResourcesD3D11 (const ShaderResourcesD3D11&) = delete; - ShaderResourcesD3D11 ( ShaderResourcesD3D11&&) = delete; - ShaderResourcesD3D11& operator = (const ShaderResourcesD3D11&) = delete; - ShaderResourcesD3D11& operator = ( ShaderResourcesD3D11&&) = delete; - - __forceinline Int32 GetMaxCBBindPoint() const { return m_MaxCBBindPoint; } - __forceinline Int32 GetMaxSRVBindPoint() const { return m_MaxSRVBindPoint; } - __forceinline Int32 GetMaxSamplerBindPoint()const { return m_MaxSamplerBindPoint; } - __forceinline Int32 GetMaxUAVBindPoint() const { return m_MaxUAVBindPoint; } - // clang-format on - -#ifdef DEVELOPMENT - void dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], - ID3D11ShaderResourceView* CommittedD3D11SRVs[], - ID3D11Resource* CommittedD3D11SRVResources[], - ID3D11SamplerState* CommittedD3D11Samplers[], - ID3D11UnorderedAccessView* CommittedD3D11UAVs[], - ID3D11Resource* CommittedD3D11UAVResources[], - class ShaderResourceCacheD3D11& ResourceCache) const; -#endif - - -private: - using MaxBindPointType = Int8; - - // clang-format off - MaxBindPointType m_MaxCBBindPoint = -1; // Max == 13 - MaxBindPointType m_MaxSRVBindPoint = -1; // Max == 127 - MaxBindPointType m_MaxSamplerBindPoint = -1; // Max == 15 - MaxBindPointType m_MaxUAVBindPoint = -1; // Max == 7 - - static constexpr UINT MaxAllowedBindPoint = std::numeric_limits::max(); - static_assert(D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max CB slot" ); - static_assert(D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max SRV slot"); - static_assert(D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max Sampler slot"); - static_assert(D3D11_PS_CS_UAV_REGISTER_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max UAV slot"); - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.hpp new file mode 100644 index 00000000..6fe91203 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourcesD3D11.hpp @@ -0,0 +1,142 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourcesD3D11 class + + +// ShaderResourcesD3D11 are created by ShaderD3D11Impl instances. They are then referenced by ShaderResourceLayoutD3D11 objects, which are in turn +// created by instances of ShaderResourceBindingsD3D11Impl and PipelineStateD3D11Impl +// +// _________________ +// | | +// | ShaderD3D11Impl | +// |_________________| +// | +// |shared_ptr +// ________V_____________ _____________________________________________________________________ +// | | unique_ptr | | | | | | | +// | ShaderResourcesD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |______________________| |________|___________|___________|___________|___________|____________| +// A A A A A A A +// | \ \ \ \ \ \ +// |shared_ptr Ref Ref Ref Ref Ref Ref +// ________|__________________ ____\_________\__________\__________\___________\_______ ___\______ +// | | unique_ptr | | | | | | | +// | ShaderResourceLayoutD3D11 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |___________________________| |________|___________|___________|___________|___________|__________| +// | A +// |_________________SamplerIndex_________________| +// +// +// One ShaderResourcesD3D11 instance can be referenced by multiple objects +// +// +// _______ ________________________________ +// | | | | +// ----| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | +// | |___________________________| |________________________________| +// | +// | +// _________________ ______________________ | _______ ________________________________ +// | | shared_ptr | | shared_ptr| | | | | +// | ShaderD3D11Impl |--------------->| ShaderResourcesD3D11 |<---------------| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | +// |_________________| |______________________| | |___________________________| |________________________________| +// A | +// | | +// __________ | | _______ ________________________________ +// | | shared_ptr | | | | | | +// | ShaderResourceLayoutD3D11 |------------------- ----| ShaderResourceLayoutD3D11 |<-----| ShaderResourceBindingD3D11Impl | +// |___________________________| |___________________________| |________________________________| +// A +// ___________|______________ +// | | +// | PipelineStateD3D11Impl | +// |__________________________| +// + +#include + +#include "ShaderResources.hpp" + +namespace Diligent +{ + +/// Diligent::ShaderResourcesD3D11 class +class ShaderResourcesD3D11 : public ShaderResources +{ +public: + // Loads shader resources from the compiled shader bytecode + ShaderResourcesD3D11(class RenderDeviceD3D11Impl* pDeviceD3D11Impl, + ID3DBlob* pShaderBytecode, + const ShaderDesc& ShdrDesc, + const char* CombinedSamplerSuffix); + ~ShaderResourcesD3D11(); + + // clang-format off + ShaderResourcesD3D11 (const ShaderResourcesD3D11&) = delete; + ShaderResourcesD3D11 ( ShaderResourcesD3D11&&) = delete; + ShaderResourcesD3D11& operator = (const ShaderResourcesD3D11&) = delete; + ShaderResourcesD3D11& operator = ( ShaderResourcesD3D11&&) = delete; + + __forceinline Int32 GetMaxCBBindPoint() const { return m_MaxCBBindPoint; } + __forceinline Int32 GetMaxSRVBindPoint() const { return m_MaxSRVBindPoint; } + __forceinline Int32 GetMaxSamplerBindPoint()const { return m_MaxSamplerBindPoint; } + __forceinline Int32 GetMaxUAVBindPoint() const { return m_MaxUAVBindPoint; } + // clang-format on + +#ifdef DEVELOPMENT + void dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[], + ID3D11ShaderResourceView* CommittedD3D11SRVs[], + ID3D11Resource* CommittedD3D11SRVResources[], + ID3D11SamplerState* CommittedD3D11Samplers[], + ID3D11UnorderedAccessView* CommittedD3D11UAVs[], + ID3D11Resource* CommittedD3D11UAVResources[], + class ShaderResourceCacheD3D11& ResourceCache) const; +#endif + + +private: + using MaxBindPointType = Int8; + + // clang-format off + MaxBindPointType m_MaxCBBindPoint = -1; // Max == 13 + MaxBindPointType m_MaxSRVBindPoint = -1; // Max == 127 + MaxBindPointType m_MaxSamplerBindPoint = -1; // Max == 15 + MaxBindPointType m_MaxUAVBindPoint = -1; // Max == 7 + + static constexpr UINT MaxAllowedBindPoint = std::numeric_limits::max(); + static_assert(D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max CB slot" ); + static_assert(D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max SRV slot"); + static_assert(D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max Sampler slot"); + static_assert(D3D11_PS_CS_UAV_REGISTER_COUNT-1 <= MaxAllowedBindPoint, "Not enough bits to represent max UAV slot"); + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h deleted file mode 100644 index 3997f1c7..00000000 --- a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::SwapChainD3D11Impl class - -#include "SwapChainD3D11.h" -#include "SwapChainD3DBase.h" - -namespace Diligent -{ - -class IMemoryAllocator; - -/// Swap chain implementation in Direct3D11 backend. -class SwapChainD3D11Impl final : public SwapChainD3DBase -{ -public: - using TSwapChainBase = SwapChainD3DBase; - - SwapChainD3D11Impl(IReferenceCounters* pRefCounters, - const SwapChainDesc& SCDesc, - const FullScreenModeDesc& FSDesc, - class RenderDeviceD3D11Impl* pRenderDeviceD3D11, - class DeviceContextD3D11Impl* pDeviceContextD3D11, - void* pNativeWndHandle); - ~SwapChainD3D11Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ISwapChain::Present() in Direct3D11 backend. - virtual void Present(Uint32 SyncInterval) override final; - - /// Implementation of ISwapChain::Resize() in Direct3D11 backend. - virtual void Resize(Uint32 NewWidth, Uint32 NewHeight) override final; - - /// Implementation of ISwapChainD3D11::GetDXGISwapChain() in Direct3D11 backend. - virtual IDXGISwapChain* GetDXGISwapChain() override final { return m_pSwapChain; } - - /// Implementation of ISwapChainD3D11::GetCurrentBackBufferRTV() in Direct3D11 backend. - virtual ITextureViewD3D11* GetCurrentBackBufferRTV() override final { return m_pRenderTargetView; } - - /// Implementation of ISwapChainD3D11::GetDepthBufferDSV() in Direct3D11 backend. - virtual ITextureViewD3D11* GetDepthBufferDSV() override final { return m_pDepthStencilView; } - -private: - virtual void UpdateSwapChain(bool CreateNew) override final; - void CreateRTVandDSV(); - - RefCntAutoPtr m_pRenderTargetView; - RefCntAutoPtr m_pDepthStencilView; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp new file mode 100644 index 00000000..f40b4b9b --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/SwapChainD3D11Impl.hpp @@ -0,0 +1,80 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::SwapChainD3D11Impl class + +#include "SwapChainD3D11.h" +#include "SwapChainD3DBase.hpp" + +namespace Diligent +{ + +class IMemoryAllocator; + +/// Swap chain implementation in Direct3D11 backend. +class SwapChainD3D11Impl final : public SwapChainD3DBase +{ +public: + using TSwapChainBase = SwapChainD3DBase; + + SwapChainD3D11Impl(IReferenceCounters* pRefCounters, + const SwapChainDesc& SCDesc, + const FullScreenModeDesc& FSDesc, + class RenderDeviceD3D11Impl* pRenderDeviceD3D11, + class DeviceContextD3D11Impl* pDeviceContextD3D11, + void* pNativeWndHandle); + ~SwapChainD3D11Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ISwapChain::Present() in Direct3D11 backend. + virtual void Present(Uint32 SyncInterval) override final; + + /// Implementation of ISwapChain::Resize() in Direct3D11 backend. + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + + /// Implementation of ISwapChainD3D11::GetDXGISwapChain() in Direct3D11 backend. + virtual IDXGISwapChain* GetDXGISwapChain() override final { return m_pSwapChain; } + + /// Implementation of ISwapChainD3D11::GetCurrentBackBufferRTV() in Direct3D11 backend. + virtual ITextureViewD3D11* GetCurrentBackBufferRTV() override final { return m_pRenderTargetView; } + + /// Implementation of ISwapChainD3D11::GetDepthBufferDSV() in Direct3D11 backend. + virtual ITextureViewD3D11* GetDepthBufferDSV() override final { return m_pDepthStencilView; } + +private: + virtual void UpdateSwapChain(bool CreateNew) override final; + void CreateRTVandDSV(); + + RefCntAutoPtr m_pRenderTargetView; + RefCntAutoPtr m_pDepthStencilView; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.h b/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.h deleted file mode 100644 index 0be21f90..00000000 --- a/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::Texture1D_D3D11 class - -#include "TextureBaseD3D11.h" - -namespace Diligent -{ - -/// Implementation of a 1D texture in Direct3D11 backend. -class Texture1D_D3D11 final : public TextureBaseD3D11 -{ -public: - Texture1D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const TextureDesc& TexDesc, - const TextureData* pInitData = nullptr); - - Texture1D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - RESOURCE_STATE InitialState, - ID3D11Texture1D* pd3d11Texture); - ~Texture1D_D3D11(); - -protected: - // clang-format off - virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; - virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; - virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; - virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.hpp b/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.hpp new file mode 100644 index 00000000..7ffcb7ba --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/Texture1D_D3D11.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::Texture1D_D3D11 class + +#include "TextureBaseD3D11.hpp" + +namespace Diligent +{ + +/// Implementation of a 1D texture in Direct3D11 backend. +class Texture1D_D3D11 final : public TextureBaseD3D11 +{ +public: + Texture1D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const TextureDesc& TexDesc, + const TextureData* pInitData = nullptr); + + Texture1D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + RESOURCE_STATE InitialState, + ID3D11Texture1D* pd3d11Texture); + ~Texture1D_D3D11(); + +protected: + // clang-format off + virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; + virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; + virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; + virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.h b/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.h deleted file mode 100644 index 6c8d41f0..00000000 --- a/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::Texture2D_D3D11 class - -#include "TextureBaseD3D11.h" - -namespace Diligent -{ - -/// Implementation of a 2D texture in Direct3D11 backend. -class Texture2D_D3D11 final : public TextureBaseD3D11 -{ -public: - Texture2D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const TextureDesc& TexDesc, - const TextureData* pInitData = nullptr); - - Texture2D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - RESOURCE_STATE InitialState, - ID3D11Texture2D* pd3d11Texture); - ~Texture2D_D3D11(); - -protected: - // clang-format off - virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; - virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; - virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; - virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.hpp b/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.hpp new file mode 100644 index 00000000..5df66c0c --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/Texture2D_D3D11.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::Texture2D_D3D11 class + +#include "TextureBaseD3D11.hpp" + +namespace Diligent +{ + +/// Implementation of a 2D texture in Direct3D11 backend. +class Texture2D_D3D11 final : public TextureBaseD3D11 +{ +public: + Texture2D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const TextureDesc& TexDesc, + const TextureData* pInitData = nullptr); + + Texture2D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + RESOURCE_STATE InitialState, + ID3D11Texture2D* pd3d11Texture); + ~Texture2D_D3D11(); + +protected: + // clang-format off + virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; + virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; + virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; + virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.h b/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.h deleted file mode 100644 index 9ae638a1..00000000 --- a/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::Texture3D_D3D11 class - -#include "TextureBaseD3D11.h" - -namespace Diligent -{ - -/// Implementation of a 3D texture in Direct3D11 backend. -class Texture3D_D3D11 final : public TextureBaseD3D11 -{ -public: - Texture3D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const TextureDesc& TexDesc, - const TextureData* pInitData = nullptr); - - Texture3D_D3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - RESOURCE_STATE InitialState, - ID3D11Texture3D* pd3d11Texture); - ~Texture3D_D3D11(); - -protected: - // clang-format off - virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; - virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; - virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; - virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.hpp b/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.hpp new file mode 100644 index 00000000..b7e1710f --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/Texture3D_D3D11.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::Texture3D_D3D11 class + +#include "TextureBaseD3D11.hpp" + +namespace Diligent +{ + +/// Implementation of a 3D texture in Direct3D11 backend. +class Texture3D_D3D11 final : public TextureBaseD3D11 +{ +public: + Texture3D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const TextureDesc& TexDesc, + const TextureData* pInitData = nullptr); + + Texture3D_D3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + RESOURCE_STATE InitialState, + ID3D11Texture3D* pd3d11Texture); + ~Texture3D_D3D11(); + +protected: + // clang-format off + virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) override final; + virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) override final; + virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) override final; + virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) override final; + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h deleted file mode 100644 index ece4e088..00000000 --- a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::TextureBaseD3D11 class - -#include "TextureD3D11.h" -#include "RenderDeviceD3D11.h" -#include "TextureBase.h" -#include "TextureViewD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Base implementation of a texture object in Direct3D11 backend. -class TextureBaseD3D11 : public TextureBase -{ -public: - using TTextureBase = TextureBase; - using ViewImplType = TextureViewD3D11Impl; - - TextureBaseD3D11(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const TextureDesc& TexDesc, - const TextureData* pInitData = nullptr); - ~TextureBaseD3D11(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ITextureD3D11::GetD3D11Texture(). - virtual ID3D11Resource* GetD3D11Texture() override final { return m_pd3d11Texture; } - - /// Implementation of ITexture::GetNativeHandle(). - virtual void* GetNativeHandle() override final { return GetD3D11Texture(); } - - void AddState(RESOURCE_STATE State) - { - m_State = static_cast(m_State & ~static_cast(RESOURCE_STATE_UNDEFINED)); - m_State = static_cast(m_State | State); - } - - void ClearState(RESOURCE_STATE State) - { - VERIFY_EXPR(IsInKnownState()); - m_State = static_cast(m_State & ~static_cast(State)); - if (m_State == RESOURCE_STATE_UNKNOWN) - m_State = RESOURCE_STATE_UNDEFINED; - } - -protected: - void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override final; - void PrepareD3D11InitData(const TextureData* pInitData, - Uint32 NumSubresources, - std::vector>& D3D11InitData); - - // clang-format off - virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) = 0; - virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) = 0; - virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) = 0; - virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) = 0; - // clang-format on - - friend class RenderDeviceD3D11Impl; - /// D3D11 texture - CComPtr m_pd3d11Texture; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp new file mode 100644 index 00000000..c954f844 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp @@ -0,0 +1,98 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::TextureBaseD3D11 class + +#include "TextureD3D11.h" +#include "RenderDeviceD3D11.h" +#include "TextureBase.hpp" +#include "TextureViewD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Base implementation of a texture object in Direct3D11 backend. +class TextureBaseD3D11 : public TextureBase +{ +public: + using TTextureBase = TextureBase; + using ViewImplType = TextureViewD3D11Impl; + + TextureBaseD3D11(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const TextureDesc& TexDesc, + const TextureData* pInitData = nullptr); + ~TextureBaseD3D11(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ITextureD3D11::GetD3D11Texture(). + virtual ID3D11Resource* GetD3D11Texture() override final { return m_pd3d11Texture; } + + /// Implementation of ITexture::GetNativeHandle(). + virtual void* GetNativeHandle() override final { return GetD3D11Texture(); } + + void AddState(RESOURCE_STATE State) + { + m_State = static_cast(m_State & ~static_cast(RESOURCE_STATE_UNDEFINED)); + m_State = static_cast(m_State | State); + } + + void ClearState(RESOURCE_STATE State) + { + VERIFY_EXPR(IsInKnownState()); + m_State = static_cast(m_State & ~static_cast(State)); + if (m_State == RESOURCE_STATE_UNKNOWN) + m_State = RESOURCE_STATE_UNDEFINED; + } + +protected: + void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override final; + void PrepareD3D11InitData(const TextureData* pInitData, + Uint32 NumSubresources, + std::vector>& D3D11InitData); + + // clang-format off + virtual void CreateSRV(TextureViewDesc& SRVDesc, ID3D11ShaderResourceView** ppD3D11SRV) = 0; + virtual void CreateRTV(TextureViewDesc& RTVDesc, ID3D11RenderTargetView** ppD3D11RTV) = 0; + virtual void CreateDSV(TextureViewDesc& DSVDesc, ID3D11DepthStencilView** ppD3D11DSV) = 0; + virtual void CreateUAV(TextureViewDesc& UAVDesc, ID3D11UnorderedAccessView** ppD3D11UAV) = 0; + // clang-format on + + friend class RenderDeviceD3D11Impl; + /// D3D11 texture + CComPtr m_pd3d11Texture; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.h b/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.h deleted file mode 100644 index 0b104597..00000000 --- a/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::TextureViewD3D11Impl class - -#include "TextureViewD3D11.h" -#include "RenderDeviceD3D11.h" -#include "TextureViewBase.h" -#include "RenderDeviceD3D11Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Texture view implementation in Direct3D11 backend. -class TextureViewD3D11Impl final : public TextureViewBase -{ -public: - using TTextureViewBase = TextureViewBase; - - TextureViewD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pDevice, - const TextureViewDesc& ViewDesc, - class ITexture* pTexture, - ID3D11View* pD3D11View, - bool bIsDefaultView); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ITextureViewD3D11::GetD3D11View(). - virtual ID3D11View* GetD3D11View() override final - { - return m_pD3D11View; - } - -private: - /// D3D11 view - CComPtr m_pD3D11View; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp new file mode 100644 index 00000000..20c2afbf --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp @@ -0,0 +1,69 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::TextureViewD3D11Impl class + +#include "TextureViewD3D11.h" +#include "RenderDeviceD3D11.h" +#include "TextureViewBase.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Texture view implementation in Direct3D11 backend. +class TextureViewD3D11Impl final : public TextureViewBase +{ +public: + using TTextureViewBase = TextureViewBase; + + TextureViewD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + const TextureViewDesc& ViewDesc, + class ITexture* pTexture, + ID3D11View* pD3D11View, + bool bIsDefaultView); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ITextureViewD3D11::GetD3D11View(). + virtual ID3D11View* GetD3D11View() override final + { + return m_pD3D11View; + } + +private: + /// D3D11 view + CComPtr m_pD3D11View; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/pch.h b/Graphics/GraphicsEngineD3D11/include/pch.h index bbc00ae1..ea2eab2f 100644 --- a/Graphics/GraphicsEngineD3D11/include/pch.h +++ b/Graphics/GraphicsEngineD3D11/include/pch.h @@ -74,8 +74,8 @@ #include "Errors.h" #include "RefCntAutoPtr.h" #include "DebugUtilities.h" -#include "D3DErrors.h" -#include "RenderDeviceBase.h" +#include "D3DErrors.hpp" +#include "RenderDeviceBase.hpp" #include "D3D11TypeConversions.h" #include "ValidatedCast.h" #include diff --git a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp index 02235237..2d2d10b5 100644 --- a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp @@ -28,11 +28,11 @@ #include "pch.h" #include -#include "BufferD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" +#include "BufferD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" #include "D3D11TypeConversions.h" -#include "BufferViewD3D11Impl.h" +#include "BufferViewD3D11Impl.hpp" #include "GraphicsAccessories.hpp" #include "EngineMemory.h" diff --git a/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp index ff78e3dc..e02bd8ff 100644 --- a/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp @@ -26,7 +26,7 @@ */ #include "pch.h" -#include "BufferViewD3D11Impl.h" +#include "BufferViewD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/CommandListD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/CommandListD3D11Impl.cpp index 27981375..39eb87bd 100644 --- a/Graphics/GraphicsEngineD3D11/src/CommandListD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/CommandListD3D11Impl.cpp @@ -28,7 +28,7 @@ #include "pch.h" #include -#include "CommandListD3D11Impl.h" +#include "CommandListD3D11Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/D3D11TypeConversions.cpp b/Graphics/GraphicsEngineD3D11/src/D3D11TypeConversions.cpp index 59a937b5..0d76db58 100644 --- a/Graphics/GraphicsEngineD3D11/src/D3D11TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D11/src/D3D11TypeConversions.cpp @@ -29,8 +29,8 @@ #include "D3D11TypeConversions.h" #include "D3D11TypeDefinitions.h" -#include "D3DTypeConversionImpl.h" -#include "D3DViewDescConversionImpl.h" +#include "D3DTypeConversionImpl.hpp" +#include "D3DViewDescConversionImpl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 78f08bf4..0c19756c 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -26,22 +26,22 @@ */ #include "pch.h" -#include "DeviceContextD3D11Impl.h" -#include "BufferD3D11Impl.h" -#include "ShaderD3D11Impl.h" -#include "Texture1D_D3D11.h" -#include "Texture2D_D3D11.h" -#include "Texture3D_D3D11.h" -#include "SamplerD3D11Impl.h" +#include "DeviceContextD3D11Impl.hpp" +#include "BufferD3D11Impl.hpp" +#include "ShaderD3D11Impl.hpp" +#include "Texture1D_D3D11.hpp" +#include "Texture2D_D3D11.hpp" +#include "Texture3D_D3D11.hpp" +#include "SamplerD3D11Impl.hpp" #include "D3D11TypeConversions.h" -#include "TextureViewD3D11Impl.h" -#include "PipelineStateD3D11Impl.h" -#include "ShaderResourceBindingD3D11Impl.h" +#include "TextureViewD3D11Impl.hpp" +#include "PipelineStateD3D11Impl.hpp" +#include "ShaderResourceBindingD3D11Impl.hpp" #include "EngineD3D11Defines.h" -#include "CommandListD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" -#include "FenceD3D11Impl.h" -#include "QueryD3D11Impl.h" +#include "CommandListD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "FenceD3D11Impl.hpp" +#include "QueryD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp index 623dde46..252697bd 100644 --- a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp @@ -30,12 +30,12 @@ #include "pch.h" #include "EngineFactoryD3D11.h" -#include "RenderDeviceD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" -#include "SwapChainD3D11Impl.h" +#include "RenderDeviceD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" +#include "SwapChainD3D11Impl.hpp" #include "D3D11TypeConversions.h" #include "EngineMemory.h" -#include "EngineFactoryD3DBase.h" +#include "EngineFactoryD3DBase.hpp" #include #include diff --git a/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp index 9a651121..3cb1b91e 100644 --- a/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/FenceD3D11Impl.cpp @@ -28,7 +28,7 @@ #include "pch.h" #include -#include "FenceD3D11Impl.h" +#include "FenceD3D11Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 7cc5313d..02f0dac8 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -27,11 +27,11 @@ #include "pch.h" #include -#include "PipelineStateD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" -#include "ShaderResourceBindingD3D11Impl.h" +#include "PipelineStateD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "ShaderResourceBindingD3D11Impl.hpp" #include "EngineMemory.h" -#include "ShaderD3D11Impl.h" +#include "ShaderD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp index 751810de..bf70dfc1 100644 --- a/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp @@ -27,8 +27,8 @@ #include "pch.h" -#include "QueryD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" +#include "QueryD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index b7e7a0bc..bcd9bec6 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -26,20 +26,20 @@ */ #include "pch.h" -#include "RenderDeviceD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" -#include "BufferD3D11Impl.h" -#include "ShaderD3D11Impl.h" -#include "Texture1D_D3D11.h" -#include "Texture2D_D3D11.h" -#include "Texture3D_D3D11.h" -#include "SamplerD3D11Impl.h" +#include "RenderDeviceD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" +#include "BufferD3D11Impl.hpp" +#include "ShaderD3D11Impl.hpp" +#include "Texture1D_D3D11.hpp" +#include "Texture2D_D3D11.hpp" +#include "Texture3D_D3D11.hpp" +#include "SamplerD3D11Impl.hpp" #include "D3D11TypeConversions.h" -#include "TextureViewD3D11Impl.h" -#include "PipelineStateD3D11Impl.h" -#include "ShaderResourceBindingD3D11Impl.h" -#include "FenceD3D11Impl.h" -#include "QueryD3D11Impl.h" +#include "TextureViewD3D11Impl.hpp" +#include "PipelineStateD3D11Impl.hpp" +#include "ShaderResourceBindingD3D11Impl.hpp" +#include "FenceD3D11Impl.hpp" +#include "QueryD3D11Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/SamplerD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SamplerD3D11Impl.cpp index c5166c27..6d23f951 100644 --- a/Graphics/GraphicsEngineD3D11/src/SamplerD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SamplerD3D11Impl.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "SamplerD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" +#include "SamplerD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" #include "D3D11TypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp index 8cf31521..b5b0194f 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp @@ -27,8 +27,8 @@ #include "pch.h" -#include "ShaderD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" +#include "ShaderD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" #include "ResourceMapping.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 96acdd01..7af06af3 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -26,10 +26,10 @@ */ #include "pch.h" -#include "ShaderResourceBindingD3D11Impl.h" -#include "PipelineStateD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" +#include "ShaderResourceBindingD3D11Impl.hpp" +#include "PipelineStateD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp index a98653eb..2286d65e 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp @@ -27,11 +27,11 @@ #include "pch.h" -#include "ShaderResourceCacheD3D11.h" -#include "ShaderResourceLayoutD3D11.h" -#include "TextureBaseD3D11.h" -#include "BufferD3D11Impl.h" -#include "SamplerD3D11Impl.h" +#include "ShaderResourceCacheD3D11.hpp" +#include "ShaderResourceLayoutD3D11.hpp" +#include "TextureBaseD3D11.hpp" +#include "BufferD3D11Impl.hpp" +#include "SamplerD3D11Impl.hpp" #include "MemoryAllocator.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index c13f6fd8..741b5692 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -29,15 +29,15 @@ #include -#include "ShaderResourceLayoutD3D11.h" -#include "ShaderResourceCacheD3D11.h" -#include "BufferD3D11Impl.h" -#include "BufferViewD3D11Impl.h" -#include "TextureBaseD3D11.h" +#include "ShaderResourceLayoutD3D11.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "BufferD3D11Impl.hpp" +#include "BufferViewD3D11Impl.hpp" +#include "TextureBaseD3D11.hpp" #include "TextureViewD3D11.h" -#include "SamplerD3D11Impl.h" -#include "ShaderD3D11Impl.h" -#include "ShaderResourceVariableBase.h" +#include "SamplerD3D11Impl.hpp" +#include "ShaderD3D11Impl.hpp" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp index 6ca61897..e39830aa 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp @@ -28,10 +28,10 @@ #include "pch.h" #include -#include "ShaderResourcesD3D11.h" -#include "ShaderBase.h" -#include "ShaderResourceCacheD3D11.h" -#include "RenderDeviceD3D11Impl.h" +#include "ShaderResourcesD3D11.hpp" +#include "ShaderBase.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp index 537064e5..0beb5eb8 100644 --- a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp @@ -26,9 +26,9 @@ */ #include "pch.h" -#include "SwapChainD3D11Impl.h" -#include "RenderDeviceD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" +#include "SwapChainD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" #include namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/Texture1D_D3D11.cpp b/Graphics/GraphicsEngineD3D11/src/Texture1D_D3D11.cpp index 7f7b63cc..89104a55 100644 --- a/Graphics/GraphicsEngineD3D11/src/Texture1D_D3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/Texture1D_D3D11.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "Texture1D_D3D11.h" -#include "RenderDeviceD3D11Impl.h" +#include "Texture1D_D3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" #include "D3D11TypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/Texture2D_D3D11.cpp b/Graphics/GraphicsEngineD3D11/src/Texture2D_D3D11.cpp index 2deb84cc..cc36b713 100644 --- a/Graphics/GraphicsEngineD3D11/src/Texture2D_D3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/Texture2D_D3D11.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "Texture2D_D3D11.h" -#include "RenderDeviceD3D11Impl.h" +#include "Texture2D_D3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" #include "D3D11TypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/Texture3D_D3D11.cpp b/Graphics/GraphicsEngineD3D11/src/Texture3D_D3D11.cpp index 37ad78a9..322043e8 100644 --- a/Graphics/GraphicsEngineD3D11/src/Texture3D_D3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/Texture3D_D3D11.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "Texture3D_D3D11.h" -#include "RenderDeviceD3D11Impl.h" +#include "Texture3D_D3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" #include "D3D11TypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp index add54b6b..39918856 100644 --- a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp @@ -26,11 +26,11 @@ */ #include "pch.h" -#include "TextureBaseD3D11.h" -#include "RenderDeviceD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" +#include "TextureBaseD3D11.hpp" +#include "RenderDeviceD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" #include "D3D11TypeConversions.h" -#include "TextureViewD3D11Impl.h" +#include "TextureViewD3D11Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/TextureViewD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/TextureViewD3D11Impl.cpp index 6dc63f6a..f6c2d982 100644 --- a/Graphics/GraphicsEngineD3D11/src/TextureViewD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/TextureViewD3D11Impl.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "TextureViewD3D11Impl.h" -#include "DeviceContextD3D11Impl.h" +#include "TextureViewD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index a8b744e8..fa3b4b70 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -3,38 +3,38 @@ cmake_minimum_required (VERSION 3.10) project(Diligent-GraphicsEngineD3D12 CXX) set(INCLUDE - include/BufferD3D12Impl.h - include/BufferViewD3D12Impl.h - include/CommandContext.h - include/CommandListD3D12Impl.h - include/CommandListManager.h - include/CommandQueueD3D12Impl.h - include/D3D12ResourceBase.h + include/BufferD3D12Impl.hpp + include/BufferViewD3D12Impl.hpp + include/CommandContext.hpp + include/CommandListD3D12Impl.hpp + include/CommandListManager.hpp + include/CommandQueueD3D12Impl.hpp + include/D3D12ResourceBase.hpp include/D3D12TypeConversions.h include/D3D12TypeDefinitions.h include/D3D12Utils.h include/d3dx12_win.h - include/DescriptorHeap.h - include/DeviceContextD3D12Impl.h - include/D3D12DynamicHeap.h - include/FenceD3D12Impl.h - include/GenerateMips.h + include/DescriptorHeap.hpp + include/DeviceContextD3D12Impl.hpp + include/D3D12DynamicHeap.hpp + include/FenceD3D12Impl.hpp + include/GenerateMips.hpp include/pch.h - include/PipelineStateD3D12Impl.h - include/QueryD3D12Impl.h - include/QueryManagerD3D12.h - include/RenderDeviceD3D12Impl.h - include/RootSignature.h - include/SamplerD3D12Impl.h - include/ShaderD3D12Impl.h - include/ShaderResourceBindingD3D12Impl.h - include/ShaderResourceCacheD3D12.h - include/ShaderResourceLayoutD3D12.h - include/ShaderResourcesD3D12.h - include/ShaderVariableD3D12.h - include/SwapChainD3D12Impl.h - include/TextureD3D12Impl.h - include/TextureViewD3D12Impl.h + include/PipelineStateD3D12Impl.hpp + include/QueryD3D12Impl.hpp + include/QueryManagerD3D12.hpp + include/RenderDeviceD3D12Impl.hpp + include/RootSignature.hpp + include/SamplerD3D12Impl.hpp + include/ShaderD3D12Impl.hpp + include/ShaderResourceBindingD3D12Impl.hpp + include/ShaderResourceCacheD3D12.hpp + include/ShaderResourceLayoutD3D12.hpp + include/ShaderResourcesD3D12.hpp + include/ShaderVariableD3D12.hpp + include/SwapChainD3D12Impl.hpp + include/TextureD3D12Impl.hpp + include/TextureViewD3D12Impl.hpp ) set(INTERFACE @@ -88,7 +88,7 @@ set(SRC ) if(PLATFORM_WIN32) - list(APPEND INCLUDE include/D3D12Loader.h) + list(APPEND INCLUDE include/D3D12Loader.hpp) list(APPEND SRC src/D3D12Loader.cpp) set(USE_D3D12_LOADER 1) else() diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h deleted file mode 100644 index adb24766..00000000 --- a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::BufferD3D12Impl class - -#include "BufferD3D12.h" -#include "RenderDeviceD3D12.h" -#include "BufferBase.h" -#include "BufferViewD3D12Impl.h" -#include "D3D12ResourceBase.h" -#include "D3D12DynamicHeap.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Buffer object implementation in Direct3D12 backend. -class BufferD3D12Impl final : public BufferBase, public D3D12ResourceBase -{ -public: - using TBufferBase = BufferBase; - - BufferD3D12Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& BuffViewObjMemAllocator, - class RenderDeviceD3D12Impl* pDeviceD3D12, - const BufferDesc& BuffDesc, - const BufferData* pBuffData = nullptr); - - BufferD3D12Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& BuffViewObjMemAllocator, - class RenderDeviceD3D12Impl* pDeviceD3D12, - const BufferDesc& BuffDesc, - RESOURCE_STATE InitialState, - ID3D12Resource* pd3d12Buffer); - ~BufferD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - -#ifdef DEVELOPMENT - void DvpVerifyDynamicAllocation(class DeviceContextD3D12Impl* pCtx) const; -#endif - - /// Implementation of IBufferD3D12::GetD3D12Buffer(). - virtual ID3D12Resource* GetD3D12Buffer(Uint64& DataStartByteOffset, IDeviceContext* pContext) override final; - - /// Implementation of IBuffer::GetNativeHandle(). - virtual void* GetNativeHandle() override final - { - VERIFY(GetD3D12Resource() != nullptr, "The buffer is dynamic and has no pointer to D3D12 resource"); - Uint64 DataStartByteOffset = 0; - auto* pd3d12Buffer = GetD3D12Buffer(DataStartByteOffset, 0); - VERIFY(DataStartByteOffset == 0, "0 offset expected"); - return pd3d12Buffer; - } - - /// Implementation of IBufferD3D12::SetD3D12ResourceState(). - virtual void SetD3D12ResourceState(D3D12_RESOURCE_STATES state) override final; - - /// Implementation of IBufferD3D12::GetD3D12ResourceState(). - virtual D3D12_RESOURCE_STATES GetD3D12ResourceState() const override final; - - __forceinline D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint32 ContextId, class DeviceContextD3D12Impl* pCtx) - { - if (m_Desc.Usage == USAGE_DYNAMIC) - { -#ifdef DEVELOPMENT - DvpVerifyDynamicAllocation(pCtx); -#endif - return m_DynamicData[ContextId].GPUAddress; - } - else - { - return GetD3D12Resource()->GetGPUVirtualAddress(); - } - } - - D3D12_CPU_DESCRIPTOR_HANDLE GetCBVHandle() { return m_CBVDescriptorAllocation.GetCpuHandle(); } - -private: - virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) override; - - void CreateUAV(struct BufferViewDesc& UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVDescriptor); - void CreateSRV(struct BufferViewDesc& SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVDescriptor); - void CreateCBV(D3D12_CPU_DESCRIPTOR_HANDLE CBVDescriptor); - - DescriptorHeapAllocation m_CBVDescriptorAllocation; - - friend class DeviceContextD3D12Impl; - // Array of dynamic allocations for every device context - // sizeof(D3D12DynamicAllocation) == 40 (x64) - std::vector> m_DynamicData; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp new file mode 100644 index 00000000..70513071 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp @@ -0,0 +1,123 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::BufferD3D12Impl class + +#include "BufferD3D12.h" +#include "RenderDeviceD3D12.h" +#include "BufferBase.hpp" +#include "BufferViewD3D12Impl.hpp" +#include "D3D12ResourceBase.hpp" +#include "D3D12DynamicHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Buffer object implementation in Direct3D12 backend. +class BufferD3D12Impl final : public BufferBase, public D3D12ResourceBase +{ +public: + using TBufferBase = BufferBase; + + BufferD3D12Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& BuffViewObjMemAllocator, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const BufferDesc& BuffDesc, + const BufferData* pBuffData = nullptr); + + BufferD3D12Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& BuffViewObjMemAllocator, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const BufferDesc& BuffDesc, + RESOURCE_STATE InitialState, + ID3D12Resource* pd3d12Buffer); + ~BufferD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + +#ifdef DEVELOPMENT + void DvpVerifyDynamicAllocation(class DeviceContextD3D12Impl* pCtx) const; +#endif + + /// Implementation of IBufferD3D12::GetD3D12Buffer(). + virtual ID3D12Resource* GetD3D12Buffer(Uint64& DataStartByteOffset, IDeviceContext* pContext) override final; + + /// Implementation of IBuffer::GetNativeHandle(). + virtual void* GetNativeHandle() override final + { + VERIFY(GetD3D12Resource() != nullptr, "The buffer is dynamic and has no pointer to D3D12 resource"); + Uint64 DataStartByteOffset = 0; + auto* pd3d12Buffer = GetD3D12Buffer(DataStartByteOffset, 0); + VERIFY(DataStartByteOffset == 0, "0 offset expected"); + return pd3d12Buffer; + } + + /// Implementation of IBufferD3D12::SetD3D12ResourceState(). + virtual void SetD3D12ResourceState(D3D12_RESOURCE_STATES state) override final; + + /// Implementation of IBufferD3D12::GetD3D12ResourceState(). + virtual D3D12_RESOURCE_STATES GetD3D12ResourceState() const override final; + + __forceinline D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint32 ContextId, class DeviceContextD3D12Impl* pCtx) + { + if (m_Desc.Usage == USAGE_DYNAMIC) + { +#ifdef DEVELOPMENT + DvpVerifyDynamicAllocation(pCtx); +#endif + return m_DynamicData[ContextId].GPUAddress; + } + else + { + return GetD3D12Resource()->GetGPUVirtualAddress(); + } + } + + D3D12_CPU_DESCRIPTOR_HANDLE GetCBVHandle() { return m_CBVDescriptorAllocation.GetCpuHandle(); } + +private: + virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) override; + + void CreateUAV(struct BufferViewDesc& UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVDescriptor); + void CreateSRV(struct BufferViewDesc& SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVDescriptor); + void CreateCBV(D3D12_CPU_DESCRIPTOR_HANDLE CBVDescriptor); + + DescriptorHeapAllocation m_CBVDescriptorAllocation; + + friend class DeviceContextD3D12Impl; + // Array of dynamic allocations for every device context + // sizeof(D3D12DynamicAllocation) == 40 (x64) + std::vector> m_DynamicData; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h deleted file mode 100644 index abf715eb..00000000 --- a/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::BufferViewD3D12Impl class - -#include "BufferViewD3D12.h" -#include "RenderDeviceD3D12.h" -#include "BufferViewBase.h" -#include "DescriptorHeap.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Buffer view implementation in Direct3D12 backend. -class BufferViewD3D12Impl final : public BufferViewBase -{ -public: - using TBufferViewBase = BufferViewBase; - - BufferViewD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - const BufferViewDesc& ViewDesc, - class IBuffer* pBuffer, - DescriptorHeapAllocation&& HandleAlloc, - bool bIsDefaultView); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IBufferViewD3D12::GetCPUDescriptorHandle(). - virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override final { return m_DescriptorHandle.GetCpuHandle(); } - -protected: - // Allocation in a CPU-only descriptor heap - DescriptorHeapAllocation m_DescriptorHandle; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.hpp new file mode 100644 index 00000000..62cb6294 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/BufferViewD3D12Impl.hpp @@ -0,0 +1,67 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::BufferViewD3D12Impl class + +#include "BufferViewD3D12.h" +#include "RenderDeviceD3D12.h" +#include "BufferViewBase.hpp" +#include "DescriptorHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Buffer view implementation in Direct3D12 backend. +class BufferViewD3D12Impl final : public BufferViewBase +{ +public: + using TBufferViewBase = BufferViewBase; + + BufferViewD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + const BufferViewDesc& ViewDesc, + class IBuffer* pBuffer, + DescriptorHeapAllocation&& HandleAlloc, + bool bIsDefaultView); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IBufferViewD3D12::GetCPUDescriptorHandle(). + virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override final { return m_DescriptorHandle.GetCpuHandle(); } + +protected: + // Allocation in a CPU-only descriptor heap + DescriptorHeapAllocation m_DescriptorHandle; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.h b/Graphics/GraphicsEngineD3D12/include/CommandContext.h deleted file mode 100644 index ed8824c5..00000000 --- a/Graphics/GraphicsEngineD3D12/include/CommandContext.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include - -#include "D3D12ResourceBase.h" -#include "TextureViewD3D12.h" -#include "TextureD3D12.h" -#include "BufferD3D12.h" -#include "DescriptorHeap.h" - -namespace Diligent -{ - - -struct DWParam -{ - // clang-format off - DWParam( FLOAT f ) : Float{f} {} - DWParam( UINT u ) : Uint {u} {} - DWParam( INT i ) : Int {i} {} - - void operator= ( FLOAT f ) { Float = f; } - void operator= ( UINT u ) { Uint = u; } - void operator= ( INT i ) { Int = i; } - // clang-format on - - union - { - FLOAT Float; - UINT Uint; - INT Int; - }; -}; - - -class CommandContext -{ -public: - CommandContext(class CommandListManager& CmdListManager); - - // clang-format off - CommandContext (const CommandContext&) = delete; - CommandContext& operator = (const CommandContext&) = delete; - CommandContext ( CommandContext&&) = delete; - CommandContext& operator = ( CommandContext&&) = delete; - // clang-format on - - ~CommandContext(); - - // Submit the command buffer and reset it. This is encouraged to keep the GPU busy and reduce latency. - // Taking too long to build command lists and submit them can idle the GPU. - ID3D12GraphicsCommandList* Close(CComPtr& pAllocator); - void Reset(CommandListManager& CmdListManager); - - class GraphicsContext& AsGraphicsContext(); - class ComputeContext& AsComputeContext(); - - void ClearUAVFloat(D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, - D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, - ID3D12Resource* pd3d12Resource, - const float* Color) - { - FlushResourceBarriers(); - m_pCommandList->ClearUnorderedAccessViewFloat(GpuHandle, CpuHandle, pd3d12Resource, Color, 0, nullptr); - } - - void ClearUAVUint(D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, - D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, - ID3D12Resource* pd3d12Resource, - const UINT* Color) - { - FlushResourceBarriers(); - m_pCommandList->ClearUnorderedAccessViewUint(GpuHandle, CpuHandle, pd3d12Resource, Color, 0, nullptr); - } - - void CopyResource(ID3D12Resource* pDstRes, ID3D12Resource* pSrcRes) - { - m_pCommandList->CopyResource(pDstRes, pSrcRes); - } - - void TransitionResource(ITextureD3D12* pTexture, RESOURCE_STATE NewState); - void TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE NewState); - void TransitionResource(const StateTransitionDesc& Barrier); - //void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false); - - void ResolveSubresource(ID3D12Resource* pDstResource, - UINT DstSubresource, - ID3D12Resource* pSrcResource, - UINT SrcSubresource, - DXGI_FORMAT Format) - { - FlushResourceBarriers(); - m_pCommandList->ResolveSubresource(pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format); - } - - void FlushResourceBarriers() - { - if (!m_PendingResourceBarriers.empty()) - { - m_pCommandList->ResourceBarrier(static_cast(m_PendingResourceBarriers.size()), m_PendingResourceBarriers.data()); - m_PendingResourceBarriers.clear(); - } - } - - - struct ShaderDescriptorHeaps - { - ID3D12DescriptorHeap* pSrvCbvUavHeap; - ID3D12DescriptorHeap* pSamplerHeap; - ShaderDescriptorHeaps(ID3D12DescriptorHeap* _pSrvCbvUavHeap = nullptr, ID3D12DescriptorHeap* _pSamplerHeap = nullptr) : - pSrvCbvUavHeap{_pSrvCbvUavHeap}, - pSamplerHeap{_pSamplerHeap} - {} - bool operator==(const ShaderDescriptorHeaps& rhs) const - { - return pSrvCbvUavHeap == rhs.pSrvCbvUavHeap && pSamplerHeap == rhs.pSamplerHeap; - } - operator bool() const - { - return pSrvCbvUavHeap != nullptr || pSamplerHeap != nullptr; - } - }; - void SetDescriptorHeaps(ShaderDescriptorHeaps& Heaps); - - void ExecuteIndirect(ID3D12CommandSignature* pCmdSignature, ID3D12Resource* pBuff, Uint64 ArgsOffset) - { - FlushResourceBarriers(); - m_pCommandList->ExecuteIndirect(pCmdSignature, 1, pBuff, ArgsOffset, nullptr, 0); - } - - void SetID(const Char* ID) { m_ID = ID; } - ID3D12GraphicsCommandList* GetCommandList() { return m_pCommandList; } - - DescriptorHeapAllocation AllocateDynamicGPUVisibleDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1) - { - VERIFY(m_DynamicGPUDescriptorAllocators != nullptr, "Dynamic GPU descriptor llocators have not been initialized. Did you forget to call SetDynamicGPUDescriptorAllocators() after resetting the context?"); - VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type"); - return m_DynamicGPUDescriptorAllocators[Type].Allocate(Count); - } - - void InsertUAVBarrier(ID3D12Resource* pd3d12Resource); - - void SetPipelineState(ID3D12PipelineState* pPSO) - { - if (pPSO != m_pCurPipelineState) - { - m_pCommandList->SetPipelineState(m_pCurPipelineState = pPSO); - } - } - - void SetDynamicGPUDescriptorAllocators(DynamicSuballocationsManager* Allocators) - { - m_DynamicGPUDescriptorAllocators = Allocators; - } - - void BeginQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index) - { - m_pCommandList->BeginQuery(pQueryHeap, Type, Index); - } - - void EndQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index) - { - m_pCommandList->EndQuery(pQueryHeap, Type, Index); - } - - void ResolveQueryData(ID3D12QueryHeap* pQueryHeap, - D3D12_QUERY_TYPE Type, - UINT StartIndex, - UINT NumQueries, - ID3D12Resource* pDestinationBuffer, - UINT64 AlignedDestinationBufferOffset) - { - m_pCommandList->ResolveQueryData(pQueryHeap, Type, StartIndex, NumQueries, pDestinationBuffer, AlignedDestinationBufferOffset); - } - -protected: - void InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, bool FlushImmediate = false); - - CComPtr m_pCommandList; - CComPtr m_pCurrentAllocator; - - ID3D12PipelineState* m_pCurPipelineState = nullptr; - ID3D12RootSignature* m_pCurGraphicsRootSignature = nullptr; - ID3D12RootSignature* m_pCurComputeRootSignature = nullptr; - - static constexpr int MaxPendingBarriers = 16; - - std::vector> m_PendingResourceBarriers; - - ShaderDescriptorHeaps m_BoundDescriptorHeaps; - - DynamicSuballocationsManager* m_DynamicGPUDescriptorAllocators = nullptr; - - String m_ID; - - D3D12_PRIMITIVE_TOPOLOGY m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -}; - - -class GraphicsContext : public CommandContext -{ -public: - void ClearRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV, const float* Color) - { - FlushResourceBarriers(); - m_pCommandList->ClearRenderTargetView(RTV, Color, 0, nullptr); - } - - void ClearDepthStencil(D3D12_CPU_DESCRIPTOR_HANDLE DSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil) - { - FlushResourceBarriers(); - m_pCommandList->ClearDepthStencilView(DSV, ClearFlags, Depth, Stencil, 0, nullptr); - } - - void SetRootSignature(ID3D12RootSignature* pRootSig) - { - if (pRootSig != m_pCurGraphicsRootSignature) - { - m_pCommandList->SetGraphicsRootSignature(m_pCurGraphicsRootSignature = pRootSig); - } - } - - void SetViewports(UINT NumVPs, const D3D12_VIEWPORT* pVPs) - { - m_pCommandList->RSSetViewports(NumVPs, pVPs); - } - - void SetScissorRects(UINT NumRects, const D3D12_RECT* pRects) - { - m_pCommandList->RSSetScissorRects(NumRects, pRects); - } - - void SetStencilRef(UINT StencilRef) - { - m_pCommandList->OMSetStencilRef(StencilRef); - } - - void SetBlendFactor(const float* BlendFactor) - { - m_pCommandList->OMSetBlendFactor(BlendFactor); - } - - void SetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY Topology) - { - if (m_PrimitiveTopology != Topology) - { - m_PrimitiveTopology = Topology; - m_pCommandList->IASetPrimitiveTopology(Topology); - } - } - - void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) - { - m_pCommandList->SetGraphicsRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); - } - - void SetConstants(UINT RootIndex, DWParam X) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, W.Uint, 3); - } - - void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) - { - m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV); - } - - void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) - { - m_pCommandList->SetGraphicsRootDescriptorTable(RootIndex, FirstHandle); - } - - void SetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW& IBView) - { - m_pCommandList->IASetIndexBuffer(&IBView); - } - - void SetVertexBuffers(UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[]) - { - m_pCommandList->IASetVertexBuffers(StartSlot, Count, VBViews); - } - - void Draw(UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation) - { - FlushResourceBarriers(); - m_pCommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); - } - - void DrawIndexed(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation) - { - FlushResourceBarriers(); - m_pCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); - } -}; - -class ComputeContext : public CommandContext -{ -public: - void SetRootSignature(ID3D12RootSignature* pRootSig) - { - if (pRootSig != m_pCurComputeRootSignature) - { - m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig); - } - } - - void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) - { - m_pCommandList->SetComputeRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); - } - - void SetConstants(UINT RootIndex, DWParam X) - { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y) - { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) - { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) - { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, W.Uint, 3); - } - - - void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) - { - m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV); - } - - void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) - { - m_pCommandList->SetComputeRootDescriptorTable(RootIndex, FirstHandle); - } - - void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1) - { - FlushResourceBarriers(); - m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ); - } -}; - -inline GraphicsContext& CommandContext::AsGraphicsContext() -{ - return static_cast(*this); -} - -inline ComputeContext& CommandContext::AsComputeContext() -{ - return static_cast(*this); -} - -inline void CommandContext::SetDescriptorHeaps(ShaderDescriptorHeaps& Heaps) -{ -#ifdef _DEBUG - VERIFY(Heaps.pSrvCbvUavHeap != nullptr || Heaps.pSamplerHeap != nullptr, "At least one heap is expected to be set"); - VERIFY(Heaps.pSrvCbvUavHeap == nullptr || Heaps.pSrvCbvUavHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, "Invalid heap type provided in pSrvCbvUavHeap"); - VERIFY(Heaps.pSamplerHeap == nullptr || Heaps.pSamplerHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type provided in pSamplerHeap"); -#endif - - if (!(Heaps == m_BoundDescriptorHeaps)) - { - m_BoundDescriptorHeaps = Heaps; - - ID3D12DescriptorHeap** ppHeaps = reinterpret_cast(&Heaps); - UINT NumHeaps = (ppHeaps[0] != nullptr ? 1 : 0) + (ppHeaps[1] != nullptr ? 1 : 0); - if (ppHeaps[0] == nullptr) - ++ppHeaps; - - m_pCommandList->SetDescriptorHeaps(NumHeaps, ppHeaps); - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp new file mode 100644 index 00000000..30134445 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp @@ -0,0 +1,435 @@ +/* + * Copyright 2019-2020 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 + +#include + +#include "D3D12ResourceBase.hpp" +#include "TextureViewD3D12.h" +#include "TextureD3D12.h" +#include "BufferD3D12.h" +#include "DescriptorHeap.hpp" + +namespace Diligent +{ + + +struct DWParam +{ + // clang-format off + DWParam( FLOAT f ) : Float{f} {} + DWParam( UINT u ) : Uint {u} {} + DWParam( INT i ) : Int {i} {} + + void operator= ( FLOAT f ) { Float = f; } + void operator= ( UINT u ) { Uint = u; } + void operator= ( INT i ) { Int = i; } + // clang-format on + + union + { + FLOAT Float; + UINT Uint; + INT Int; + }; +}; + + +class CommandContext +{ +public: + CommandContext(class CommandListManager& CmdListManager); + + // clang-format off + CommandContext (const CommandContext&) = delete; + CommandContext& operator = (const CommandContext&) = delete; + CommandContext ( CommandContext&&) = delete; + CommandContext& operator = ( CommandContext&&) = delete; + // clang-format on + + ~CommandContext(); + + // Submit the command buffer and reset it. This is encouraged to keep the GPU busy and reduce latency. + // Taking too long to build command lists and submit them can idle the GPU. + ID3D12GraphicsCommandList* Close(CComPtr& pAllocator); + void Reset(CommandListManager& CmdListManager); + + class GraphicsContext& AsGraphicsContext(); + class ComputeContext& AsComputeContext(); + + void ClearUAVFloat(D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, + D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, + ID3D12Resource* pd3d12Resource, + const float* Color) + { + FlushResourceBarriers(); + m_pCommandList->ClearUnorderedAccessViewFloat(GpuHandle, CpuHandle, pd3d12Resource, Color, 0, nullptr); + } + + void ClearUAVUint(D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, + D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, + ID3D12Resource* pd3d12Resource, + const UINT* Color) + { + FlushResourceBarriers(); + m_pCommandList->ClearUnorderedAccessViewUint(GpuHandle, CpuHandle, pd3d12Resource, Color, 0, nullptr); + } + + void CopyResource(ID3D12Resource* pDstRes, ID3D12Resource* pSrcRes) + { + m_pCommandList->CopyResource(pDstRes, pSrcRes); + } + + void TransitionResource(ITextureD3D12* pTexture, RESOURCE_STATE NewState); + void TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE NewState); + void TransitionResource(const StateTransitionDesc& Barrier); + //void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false); + + void ResolveSubresource(ID3D12Resource* pDstResource, + UINT DstSubresource, + ID3D12Resource* pSrcResource, + UINT SrcSubresource, + DXGI_FORMAT Format) + { + FlushResourceBarriers(); + m_pCommandList->ResolveSubresource(pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format); + } + + void FlushResourceBarriers() + { + if (!m_PendingResourceBarriers.empty()) + { + m_pCommandList->ResourceBarrier(static_cast(m_PendingResourceBarriers.size()), m_PendingResourceBarriers.data()); + m_PendingResourceBarriers.clear(); + } + } + + + struct ShaderDescriptorHeaps + { + ID3D12DescriptorHeap* pSrvCbvUavHeap; + ID3D12DescriptorHeap* pSamplerHeap; + ShaderDescriptorHeaps(ID3D12DescriptorHeap* _pSrvCbvUavHeap = nullptr, ID3D12DescriptorHeap* _pSamplerHeap = nullptr) : + pSrvCbvUavHeap{_pSrvCbvUavHeap}, + pSamplerHeap{_pSamplerHeap} + {} + bool operator==(const ShaderDescriptorHeaps& rhs) const + { + return pSrvCbvUavHeap == rhs.pSrvCbvUavHeap && pSamplerHeap == rhs.pSamplerHeap; + } + operator bool() const + { + return pSrvCbvUavHeap != nullptr || pSamplerHeap != nullptr; + } + }; + void SetDescriptorHeaps(ShaderDescriptorHeaps& Heaps); + + void ExecuteIndirect(ID3D12CommandSignature* pCmdSignature, ID3D12Resource* pBuff, Uint64 ArgsOffset) + { + FlushResourceBarriers(); + m_pCommandList->ExecuteIndirect(pCmdSignature, 1, pBuff, ArgsOffset, nullptr, 0); + } + + void SetID(const Char* ID) { m_ID = ID; } + ID3D12GraphicsCommandList* GetCommandList() { return m_pCommandList; } + + DescriptorHeapAllocation AllocateDynamicGPUVisibleDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1) + { + VERIFY(m_DynamicGPUDescriptorAllocators != nullptr, "Dynamic GPU descriptor llocators have not been initialized. Did you forget to call SetDynamicGPUDescriptorAllocators() after resetting the context?"); + VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type"); + return m_DynamicGPUDescriptorAllocators[Type].Allocate(Count); + } + + void InsertUAVBarrier(ID3D12Resource* pd3d12Resource); + + void SetPipelineState(ID3D12PipelineState* pPSO) + { + if (pPSO != m_pCurPipelineState) + { + m_pCommandList->SetPipelineState(m_pCurPipelineState = pPSO); + } + } + + void SetDynamicGPUDescriptorAllocators(DynamicSuballocationsManager* Allocators) + { + m_DynamicGPUDescriptorAllocators = Allocators; + } + + void BeginQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index) + { + m_pCommandList->BeginQuery(pQueryHeap, Type, Index); + } + + void EndQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index) + { + m_pCommandList->EndQuery(pQueryHeap, Type, Index); + } + + void ResolveQueryData(ID3D12QueryHeap* pQueryHeap, + D3D12_QUERY_TYPE Type, + UINT StartIndex, + UINT NumQueries, + ID3D12Resource* pDestinationBuffer, + UINT64 AlignedDestinationBufferOffset) + { + m_pCommandList->ResolveQueryData(pQueryHeap, Type, StartIndex, NumQueries, pDestinationBuffer, AlignedDestinationBufferOffset); + } + +protected: + void InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, bool FlushImmediate = false); + + CComPtr m_pCommandList; + CComPtr m_pCurrentAllocator; + + ID3D12PipelineState* m_pCurPipelineState = nullptr; + ID3D12RootSignature* m_pCurGraphicsRootSignature = nullptr; + ID3D12RootSignature* m_pCurComputeRootSignature = nullptr; + + static constexpr int MaxPendingBarriers = 16; + + std::vector> m_PendingResourceBarriers; + + ShaderDescriptorHeaps m_BoundDescriptorHeaps; + + DynamicSuballocationsManager* m_DynamicGPUDescriptorAllocators = nullptr; + + String m_ID; + + D3D12_PRIMITIVE_TOPOLOGY m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +}; + + +class GraphicsContext : public CommandContext +{ +public: + void ClearRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV, const float* Color) + { + FlushResourceBarriers(); + m_pCommandList->ClearRenderTargetView(RTV, Color, 0, nullptr); + } + + void ClearDepthStencil(D3D12_CPU_DESCRIPTOR_HANDLE DSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil) + { + FlushResourceBarriers(); + m_pCommandList->ClearDepthStencilView(DSV, ClearFlags, Depth, Stencil, 0, nullptr); + } + + void SetRootSignature(ID3D12RootSignature* pRootSig) + { + if (pRootSig != m_pCurGraphicsRootSignature) + { + m_pCommandList->SetGraphicsRootSignature(m_pCurGraphicsRootSignature = pRootSig); + } + } + + void SetViewports(UINT NumVPs, const D3D12_VIEWPORT* pVPs) + { + m_pCommandList->RSSetViewports(NumVPs, pVPs); + } + + void SetScissorRects(UINT NumRects, const D3D12_RECT* pRects) + { + m_pCommandList->RSSetScissorRects(NumRects, pRects); + } + + void SetStencilRef(UINT StencilRef) + { + m_pCommandList->OMSetStencilRef(StencilRef); + } + + void SetBlendFactor(const float* BlendFactor) + { + m_pCommandList->OMSetBlendFactor(BlendFactor); + } + + void SetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY Topology) + { + if (m_PrimitiveTopology != Topology) + { + m_PrimitiveTopology = Topology; + m_pCommandList->IASetPrimitiveTopology(Topology); + } + } + + void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) + { + m_pCommandList->SetGraphicsRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); + } + + void SetConstants(UINT RootIndex, DWParam X) + { + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y) + { + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) + { + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) + { + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); + m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, W.Uint, 3); + } + + void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) + { + m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV); + } + + void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) + { + m_pCommandList->SetGraphicsRootDescriptorTable(RootIndex, FirstHandle); + } + + void SetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW& IBView) + { + m_pCommandList->IASetIndexBuffer(&IBView); + } + + void SetVertexBuffers(UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[]) + { + m_pCommandList->IASetVertexBuffers(StartSlot, Count, VBViews); + } + + void Draw(UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation) + { + FlushResourceBarriers(); + m_pCommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); + } + + void DrawIndexed(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation) + { + FlushResourceBarriers(); + m_pCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); + } +}; + +class ComputeContext : public CommandContext +{ +public: + void SetRootSignature(ID3D12RootSignature* pRootSig) + { + if (pRootSig != m_pCurComputeRootSignature) + { + m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig); + } + } + + void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) + { + m_pCommandList->SetComputeRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); + } + + void SetConstants(UINT RootIndex, DWParam X) + { + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y) + { + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) + { + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); + } + + void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) + { + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); + m_pCommandList->SetComputeRoot32BitConstant(RootIndex, W.Uint, 3); + } + + + void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) + { + m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV); + } + + void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) + { + m_pCommandList->SetComputeRootDescriptorTable(RootIndex, FirstHandle); + } + + void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1) + { + FlushResourceBarriers(); + m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ); + } +}; + +inline GraphicsContext& CommandContext::AsGraphicsContext() +{ + return static_cast(*this); +} + +inline ComputeContext& CommandContext::AsComputeContext() +{ + return static_cast(*this); +} + +inline void CommandContext::SetDescriptorHeaps(ShaderDescriptorHeaps& Heaps) +{ +#ifdef _DEBUG + VERIFY(Heaps.pSrvCbvUavHeap != nullptr || Heaps.pSamplerHeap != nullptr, "At least one heap is expected to be set"); + VERIFY(Heaps.pSrvCbvUavHeap == nullptr || Heaps.pSrvCbvUavHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, "Invalid heap type provided in pSrvCbvUavHeap"); + VERIFY(Heaps.pSamplerHeap == nullptr || Heaps.pSamplerHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type provided in pSamplerHeap"); +#endif + + if (!(Heaps == m_BoundDescriptorHeaps)) + { + m_BoundDescriptorHeaps = Heaps; + + ID3D12DescriptorHeap** ppHeaps = reinterpret_cast(&Heaps); + UINT NumHeaps = (ppHeaps[0] != nullptr ? 1 : 0) + (ppHeaps[1] != nullptr ? 1 : 0); + if (ppHeaps[0] == nullptr) + ++ppHeaps; + + m_pCommandList->SetDescriptorHeaps(NumHeaps, ppHeaps); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h deleted file mode 100644 index 4066dc63..00000000 --- a/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::CommandListD3D12Impl class - -#include "CommandListBase.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class DeviceContextD3D12Impl; -class CommandContext; - -/// Command list implementation in Direct3D12 backend. -class CommandListD3D12Impl final : public CommandListBase -{ -public: - using TCommandListBase = CommandListBase; - - CommandListD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - DeviceContextD3D12Impl* pDeferredCtx, - RenderDeviceD3D12Impl::PooledCommandContext&& pCmdContext) : - // clang-format off - TCommandListBase - { - pRefCounters, - pDevice - }, - m_pDeferredCtx {pDeferredCtx }, - m_pCmdContext {std::move(pCmdContext)} - // clang-format on - { - } - - ~CommandListD3D12Impl() - { - if (m_pCmdContext != nullptr) - { - LOG_WARNING_MESSAGE("Destroying command list that has not been executed"); - m_pDevice->DisposeCommandContext(std::move(m_pCmdContext)); - } - else - { - VERIFY_EXPR(m_pDeferredCtx == nullptr); - } - } - - RenderDeviceD3D12Impl::PooledCommandContext Close(RefCntAutoPtr& pDeferredCtx) - { - pDeferredCtx = std::move(m_pDeferredCtx); - return std::move(m_pCmdContext); - } - -private: - RefCntAutoPtr m_pDeferredCtx; - RenderDeviceD3D12Impl::PooledCommandContext m_pCmdContext; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.hpp new file mode 100644 index 00000000..47319ded --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/CommandListD3D12Impl.hpp @@ -0,0 +1,88 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::CommandListD3D12Impl class + +#include "CommandListBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class DeviceContextD3D12Impl; +class CommandContext; + +/// Command list implementation in Direct3D12 backend. +class CommandListD3D12Impl final : public CommandListBase +{ +public: + using TCommandListBase = CommandListBase; + + CommandListD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + DeviceContextD3D12Impl* pDeferredCtx, + RenderDeviceD3D12Impl::PooledCommandContext&& pCmdContext) : + // clang-format off + TCommandListBase + { + pRefCounters, + pDevice + }, + m_pDeferredCtx {pDeferredCtx }, + m_pCmdContext {std::move(pCmdContext)} + // clang-format on + { + } + + ~CommandListD3D12Impl() + { + if (m_pCmdContext != nullptr) + { + LOG_WARNING_MESSAGE("Destroying command list that has not been executed"); + m_pDevice->DisposeCommandContext(std::move(m_pCmdContext)); + } + else + { + VERIFY_EXPR(m_pDeferredCtx == nullptr); + } + } + + RenderDeviceD3D12Impl::PooledCommandContext Close(RefCntAutoPtr& pDeferredCtx) + { + pDeferredCtx = std::move(m_pDeferredCtx); + return std::move(m_pCmdContext); + } + +private: + RefCntAutoPtr m_pDeferredCtx; + RenderDeviceD3D12Impl::PooledCommandContext m_pCmdContext; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListManager.h b/Graphics/GraphicsEngineD3D12/include/CommandListManager.h deleted file mode 100644 index 6548a637..00000000 --- a/Graphics/GraphicsEngineD3D12/include/CommandListManager.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include -#include -#include - -namespace Diligent -{ - -class RenderDeviceD3D12Impl; - -class CommandListManager -{ -public: - CommandListManager(RenderDeviceD3D12Impl& DeviceD3D12Impl); - ~CommandListManager(); - - // clang-format off - CommandListManager (const CommandListManager&) = delete; - CommandListManager ( CommandListManager&&) = delete; - CommandListManager& operator = (const CommandListManager&) = delete; - CommandListManager& operator = ( CommandListManager&&) = delete; - // clang-format on - - void CreateNewCommandList(ID3D12GraphicsCommandList** ppList, ID3D12CommandAllocator** ppAllocator); - - void RequestAllocator(ID3D12CommandAllocator** ppAllocator); - void ReleaseAllocator(CComPtr&& Allocator, Uint32 CmdQueue, Uint64 FenceValue); - - // Returns allocator to the list of available allocators. The GPU must have finished using the - // allocator - void FreeAllocator(CComPtr&& Allocator); - -#ifdef DEVELOPMENT - Atomics::Long GetAllocatorCounter() const - { - return m_AllocatorCounter; - } -#endif - -private: - std::mutex m_AllocatorMutex; - std::vector, STDAllocatorRawMem>> m_FreeAllocators; - - RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - - Atomics::AtomicLong m_NumAllocators = 0; // For debug purposes only - -#ifdef DEVELOPMENT - Atomics::AtomicLong m_AllocatorCounter = 0; -#endif -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandListManager.hpp b/Graphics/GraphicsEngineD3D12/include/CommandListManager.hpp new file mode 100644 index 00000000..6548a637 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/CommandListManager.hpp @@ -0,0 +1,81 @@ +/* + * Copyright 2019-2020 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 + +#include +#include +#include + +namespace Diligent +{ + +class RenderDeviceD3D12Impl; + +class CommandListManager +{ +public: + CommandListManager(RenderDeviceD3D12Impl& DeviceD3D12Impl); + ~CommandListManager(); + + // clang-format off + CommandListManager (const CommandListManager&) = delete; + CommandListManager ( CommandListManager&&) = delete; + CommandListManager& operator = (const CommandListManager&) = delete; + CommandListManager& operator = ( CommandListManager&&) = delete; + // clang-format on + + void CreateNewCommandList(ID3D12GraphicsCommandList** ppList, ID3D12CommandAllocator** ppAllocator); + + void RequestAllocator(ID3D12CommandAllocator** ppAllocator); + void ReleaseAllocator(CComPtr&& Allocator, Uint32 CmdQueue, Uint64 FenceValue); + + // Returns allocator to the list of available allocators. The GPU must have finished using the + // allocator + void FreeAllocator(CComPtr&& Allocator); + +#ifdef DEVELOPMENT + Atomics::Long GetAllocatorCounter() const + { + return m_AllocatorCounter; + } +#endif + +private: + std::mutex m_AllocatorMutex; + std::vector, STDAllocatorRawMem>> m_FreeAllocators; + + RenderDeviceD3D12Impl& m_DeviceD3D12Impl; + + Atomics::AtomicLong m_NumAllocators = 0; // For debug purposes only + +#ifdef DEVELOPMENT + Atomics::AtomicLong m_AllocatorCounter = 0; +#endif +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h deleted file mode 100644 index 478f5139..00000000 --- a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::CommandQueueD3D12Impl class - -#include "CommandQueueD3D12.h" -#include "ObjectBase.h" -#include - -namespace Diligent -{ - -/// Implementation of the Diligent::ICommandQueueD3D12 interface -class CommandQueueD3D12Impl final : public ObjectBase -{ -public: - using TBase = ObjectBase; - - CommandQueueD3D12Impl(IReferenceCounters* pRefCounters, ID3D12CommandQueue* pd3d12NativeCmdQueue, ID3D12Fence* pd3d12Fence); - ~CommandQueueD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - // Implementation of ICommandQueueD3D12::GetNextFenceValue(). - virtual Uint64 GetNextFenceValue() const override final { return m_NextFenceValue; } - - // Implementation of ICommandQueueD3D12::Submit(). - virtual Uint64 Submit(ID3D12GraphicsCommandList* commandList) override final; - - // Implementation of ICommandQueueD3D12::GetD3D12CommandQueue(). - virtual ID3D12CommandQueue* GetD3D12CommandQueue() override final { return m_pd3d12CmdQueue; } - - // Implementation of ICommandQueueD3D12::WaitForIdle(). - virtual Uint64 WaitForIdle() override final; - - // Implementation of ICommandQueueD3D12::GetCompletedFenceValue(). - virtual Uint64 GetCompletedFenceValue() override final; - - // Implementation of ICommandQueueD3D12::SignalFence(). - virtual void SignalFence(ID3D12Fence* pFence, Uint64 Value) override final; - -private: - // A value that will be signaled by the command queue next - Atomics::AtomicInt64 m_NextFenceValue; - - // Last fence value completed by the GPU - volatile Uint64 m_LastCompletedFenceValue = 0; - - std::mutex m_QueueMtx; - CComPtr m_pd3d12CmdQueue; - - // The fence is signaled right after the command list has been - // submitted to the command queue for execution. - // All command lists with fence value less or equal to the signaled value - // are guaranteed to be finished by the GPU - CComPtr m_d3d12Fence; - - HANDLE m_WaitForGPUEventHandle = {}; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp new file mode 100644 index 00000000..478f5139 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/CommandQueueD3D12Impl.hpp @@ -0,0 +1,88 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::CommandQueueD3D12Impl class + +#include "CommandQueueD3D12.h" +#include "ObjectBase.h" +#include + +namespace Diligent +{ + +/// Implementation of the Diligent::ICommandQueueD3D12 interface +class CommandQueueD3D12Impl final : public ObjectBase +{ +public: + using TBase = ObjectBase; + + CommandQueueD3D12Impl(IReferenceCounters* pRefCounters, ID3D12CommandQueue* pd3d12NativeCmdQueue, ID3D12Fence* pd3d12Fence); + ~CommandQueueD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + // Implementation of ICommandQueueD3D12::GetNextFenceValue(). + virtual Uint64 GetNextFenceValue() const override final { return m_NextFenceValue; } + + // Implementation of ICommandQueueD3D12::Submit(). + virtual Uint64 Submit(ID3D12GraphicsCommandList* commandList) override final; + + // Implementation of ICommandQueueD3D12::GetD3D12CommandQueue(). + virtual ID3D12CommandQueue* GetD3D12CommandQueue() override final { return m_pd3d12CmdQueue; } + + // Implementation of ICommandQueueD3D12::WaitForIdle(). + virtual Uint64 WaitForIdle() override final; + + // Implementation of ICommandQueueD3D12::GetCompletedFenceValue(). + virtual Uint64 GetCompletedFenceValue() override final; + + // Implementation of ICommandQueueD3D12::SignalFence(). + virtual void SignalFence(ID3D12Fence* pFence, Uint64 Value) override final; + +private: + // A value that will be signaled by the command queue next + Atomics::AtomicInt64 m_NextFenceValue; + + // Last fence value completed by the GPU + volatile Uint64 m_LastCompletedFenceValue = 0; + + std::mutex m_QueueMtx; + CComPtr m_pd3d12CmdQueue; + + // The fence is signaled right after the command list has been + // submitted to the command queue for execution. + // All command lists with fence value less or equal to the signaled value + // are guaranteed to be finished by the GPU + CComPtr m_d3d12Fence; + + HANDLE m_WaitForGPUEventHandle = {}; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h b/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h deleted file mode 100644 index cc0b1a9e..00000000 --- a/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include -#include -#include -#include - -namespace Diligent -{ - -class RenderDeviceD3D12Impl; - -struct D3D12DynamicAllocation -{ - D3D12DynamicAllocation() noexcept {} - D3D12DynamicAllocation(ID3D12Resource* pBuff, - Uint64 _Offset, - Uint64 _Size, - void* _CPUAddress, - D3D12_GPU_VIRTUAL_ADDRESS _GPUAddress -#ifdef DEVELOPMENT - , - Uint64 _DvpCtxFrameNumber -#endif - ) noexcept : - // clang-format off - pBuffer {pBuff }, - Offset {_Offset }, - Size {_Size }, - CPUAddress {_CPUAddress }, - GPUAddress {_GPUAddress } -#ifdef DEVELOPMENT - , DvpCtxFrameNumber(_DvpCtxFrameNumber) -#endif - // clang-format on - {} - - ID3D12Resource* pBuffer = nullptr; // The D3D buffer associated with this memory. - Uint64 Offset = 0; // Offset from start of buffer resource - Uint64 Size = 0; // Reserved size of this allocation - void* CPUAddress = nullptr; // The CPU-writeable address - D3D12_GPU_VIRTUAL_ADDRESS GPUAddress = 0; // The GPU-visible address -#ifdef DEVELOPMENT - Uint64 DvpCtxFrameNumber = static_cast(-1); -#endif -}; - - -class D3D12DynamicPage -{ -public: - D3D12DynamicPage(ID3D12Device* pd3d12Device, Uint64 Size); - - // clang-format off - D3D12DynamicPage (const D3D12DynamicPage&) = delete; - D3D12DynamicPage ( D3D12DynamicPage&&) = default; - D3D12DynamicPage& operator= (const D3D12DynamicPage&) = delete; - D3D12DynamicPage& operator= ( D3D12DynamicPage&&) = delete; - // clang-format on - - void* GetCPUAddress(Uint64 Offset) - { - VERIFY_EXPR(m_pd3d12Buffer); - VERIFY(Offset < GetSize(), "Offset (", Offset, ") exceeds buffer size (", GetSize(), ")"); - return reinterpret_cast(m_CPUVirtualAddress) + Offset; - } - - D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint64 Offset) - { - VERIFY_EXPR(m_pd3d12Buffer); - VERIFY(Offset < GetSize(), "Offset (", Offset, ") exceeds buffer size (", GetSize(), ")"); - return m_GPUVirtualAddress + Offset; - } - - ID3D12Resource* GetD3D12Buffer() - { - return m_pd3d12Buffer; - } - - Uint64 GetSize() const - { - VERIFY_EXPR(m_pd3d12Buffer); - return m_pd3d12Buffer->GetDesc().Width; - } - - bool IsValid() const { return m_pd3d12Buffer != nullptr; } - -private: - CComPtr m_pd3d12Buffer; - void* m_CPUVirtualAddress = nullptr; // The CPU-writeable address - D3D12_GPU_VIRTUAL_ADDRESS m_GPUVirtualAddress = 0; // The GPU-visible address -}; - - -class D3D12DynamicMemoryManager -{ -public: - D3D12DynamicMemoryManager(IMemoryAllocator& Allocator, - RenderDeviceD3D12Impl& DeviceD3D12Impl, - Uint32 NumPagesToReserve, - Uint64 PageSize); - ~D3D12DynamicMemoryManager(); - - // clang-format off - D3D12DynamicMemoryManager (const D3D12DynamicMemoryManager&) = delete; - D3D12DynamicMemoryManager ( D3D12DynamicMemoryManager&&) = delete; - D3D12DynamicMemoryManager& operator= (const D3D12DynamicMemoryManager&) = delete; - D3D12DynamicMemoryManager& operator= ( D3D12DynamicMemoryManager&&) = delete; - // clang-format on - - void ReleasePages(std::vector& Pages, Uint64 QueueMask); - - void Destroy(); - - D3D12DynamicPage AllocatePage(Uint64 SizeInBytes); - -#ifdef DEVELOPMENT - int32_t GetAllocatedPageCounter() const - { - return m_AllocatedPageCounter; - } -#endif - -private: - RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - - std::mutex m_AvailablePagesMtx; - using AvailablePagesMapElemType = std::pair; - std::multimap, STDAllocatorRawMem> m_AvailablePages; - -#ifdef DEVELOPMENT - std::atomic_int32_t m_AllocatedPageCounter = 0; -#endif -}; - - -class D3D12DynamicHeap -{ -public: - D3D12DynamicHeap(D3D12DynamicMemoryManager& DynamicMemMgr, std::string HeapName, Uint64 PageSize) : - m_GlobalDynamicMemMgr{DynamicMemMgr}, - m_HeapName{std::move(HeapName)}, - m_PageSize{PageSize} - {} - - // clang-format off - D3D12DynamicHeap (const D3D12DynamicHeap&) = delete; - D3D12DynamicHeap (D3D12DynamicHeap&&) = delete; - D3D12DynamicHeap& operator= (const D3D12DynamicHeap&) = delete; - D3D12DynamicHeap& operator= (D3D12DynamicHeap&&) = delete; - // clang-format on - - ~D3D12DynamicHeap(); - - D3D12DynamicAllocation Allocate(Uint64 SizeInBytes, Uint64 Alignment, Uint64 DvpCtxFrameNumber); - void ReleaseAllocatedPages(Uint64 QueueMask); - - static constexpr Uint64 InvalidOffset = static_cast(-1); - - size_t GetAllocatedPagesCount() const { return m_AllocatedPages.size(); } - -private: - D3D12DynamicMemoryManager& m_GlobalDynamicMemMgr; - const std::string m_HeapName; - - std::vector m_AllocatedPages; - - const Uint64 m_PageSize; - - Uint64 m_CurrOffset = InvalidOffset; - Uint64 m_AvailableSize = 0; - - Uint64 m_CurrAllocatedSize = 0; - Uint64 m_CurrUsedSize = 0; - Uint64 m_CurrAlignedSize = 0; - Uint64 m_PeakAllocatedSize = 0; - Uint64 m_PeakUsedSize = 0; - Uint64 m_PeakAlignedSize = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.hpp new file mode 100644 index 00000000..cc0b1a9e --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.hpp @@ -0,0 +1,208 @@ +/* + * Copyright 2019-2020 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 + +#include +#include +#include +#include + +namespace Diligent +{ + +class RenderDeviceD3D12Impl; + +struct D3D12DynamicAllocation +{ + D3D12DynamicAllocation() noexcept {} + D3D12DynamicAllocation(ID3D12Resource* pBuff, + Uint64 _Offset, + Uint64 _Size, + void* _CPUAddress, + D3D12_GPU_VIRTUAL_ADDRESS _GPUAddress +#ifdef DEVELOPMENT + , + Uint64 _DvpCtxFrameNumber +#endif + ) noexcept : + // clang-format off + pBuffer {pBuff }, + Offset {_Offset }, + Size {_Size }, + CPUAddress {_CPUAddress }, + GPUAddress {_GPUAddress } +#ifdef DEVELOPMENT + , DvpCtxFrameNumber(_DvpCtxFrameNumber) +#endif + // clang-format on + {} + + ID3D12Resource* pBuffer = nullptr; // The D3D buffer associated with this memory. + Uint64 Offset = 0; // Offset from start of buffer resource + Uint64 Size = 0; // Reserved size of this allocation + void* CPUAddress = nullptr; // The CPU-writeable address + D3D12_GPU_VIRTUAL_ADDRESS GPUAddress = 0; // The GPU-visible address +#ifdef DEVELOPMENT + Uint64 DvpCtxFrameNumber = static_cast(-1); +#endif +}; + + +class D3D12DynamicPage +{ +public: + D3D12DynamicPage(ID3D12Device* pd3d12Device, Uint64 Size); + + // clang-format off + D3D12DynamicPage (const D3D12DynamicPage&) = delete; + D3D12DynamicPage ( D3D12DynamicPage&&) = default; + D3D12DynamicPage& operator= (const D3D12DynamicPage&) = delete; + D3D12DynamicPage& operator= ( D3D12DynamicPage&&) = delete; + // clang-format on + + void* GetCPUAddress(Uint64 Offset) + { + VERIFY_EXPR(m_pd3d12Buffer); + VERIFY(Offset < GetSize(), "Offset (", Offset, ") exceeds buffer size (", GetSize(), ")"); + return reinterpret_cast(m_CPUVirtualAddress) + Offset; + } + + D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress(Uint64 Offset) + { + VERIFY_EXPR(m_pd3d12Buffer); + VERIFY(Offset < GetSize(), "Offset (", Offset, ") exceeds buffer size (", GetSize(), ")"); + return m_GPUVirtualAddress + Offset; + } + + ID3D12Resource* GetD3D12Buffer() + { + return m_pd3d12Buffer; + } + + Uint64 GetSize() const + { + VERIFY_EXPR(m_pd3d12Buffer); + return m_pd3d12Buffer->GetDesc().Width; + } + + bool IsValid() const { return m_pd3d12Buffer != nullptr; } + +private: + CComPtr m_pd3d12Buffer; + void* m_CPUVirtualAddress = nullptr; // The CPU-writeable address + D3D12_GPU_VIRTUAL_ADDRESS m_GPUVirtualAddress = 0; // The GPU-visible address +}; + + +class D3D12DynamicMemoryManager +{ +public: + D3D12DynamicMemoryManager(IMemoryAllocator& Allocator, + RenderDeviceD3D12Impl& DeviceD3D12Impl, + Uint32 NumPagesToReserve, + Uint64 PageSize); + ~D3D12DynamicMemoryManager(); + + // clang-format off + D3D12DynamicMemoryManager (const D3D12DynamicMemoryManager&) = delete; + D3D12DynamicMemoryManager ( D3D12DynamicMemoryManager&&) = delete; + D3D12DynamicMemoryManager& operator= (const D3D12DynamicMemoryManager&) = delete; + D3D12DynamicMemoryManager& operator= ( D3D12DynamicMemoryManager&&) = delete; + // clang-format on + + void ReleasePages(std::vector& Pages, Uint64 QueueMask); + + void Destroy(); + + D3D12DynamicPage AllocatePage(Uint64 SizeInBytes); + +#ifdef DEVELOPMENT + int32_t GetAllocatedPageCounter() const + { + return m_AllocatedPageCounter; + } +#endif + +private: + RenderDeviceD3D12Impl& m_DeviceD3D12Impl; + + std::mutex m_AvailablePagesMtx; + using AvailablePagesMapElemType = std::pair; + std::multimap, STDAllocatorRawMem> m_AvailablePages; + +#ifdef DEVELOPMENT + std::atomic_int32_t m_AllocatedPageCounter = 0; +#endif +}; + + +class D3D12DynamicHeap +{ +public: + D3D12DynamicHeap(D3D12DynamicMemoryManager& DynamicMemMgr, std::string HeapName, Uint64 PageSize) : + m_GlobalDynamicMemMgr{DynamicMemMgr}, + m_HeapName{std::move(HeapName)}, + m_PageSize{PageSize} + {} + + // clang-format off + D3D12DynamicHeap (const D3D12DynamicHeap&) = delete; + D3D12DynamicHeap (D3D12DynamicHeap&&) = delete; + D3D12DynamicHeap& operator= (const D3D12DynamicHeap&) = delete; + D3D12DynamicHeap& operator= (D3D12DynamicHeap&&) = delete; + // clang-format on + + ~D3D12DynamicHeap(); + + D3D12DynamicAllocation Allocate(Uint64 SizeInBytes, Uint64 Alignment, Uint64 DvpCtxFrameNumber); + void ReleaseAllocatedPages(Uint64 QueueMask); + + static constexpr Uint64 InvalidOffset = static_cast(-1); + + size_t GetAllocatedPagesCount() const { return m_AllocatedPages.size(); } + +private: + D3D12DynamicMemoryManager& m_GlobalDynamicMemMgr; + const std::string m_HeapName; + + std::vector m_AllocatedPages; + + const Uint64 m_PageSize; + + Uint64 m_CurrOffset = InvalidOffset; + Uint64 m_AvailableSize = 0; + + Uint64 m_CurrAllocatedSize = 0; + Uint64 m_CurrUsedSize = 0; + Uint64 m_CurrAlignedSize = 0; + Uint64 m_PeakAllocatedSize = 0; + Uint64 m_PeakUsedSize = 0; + Uint64 m_PeakAlignedSize = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h b/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h deleted file mode 100644 index 8e5b346d..00000000 --- a/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include - -namespace Diligent -{ - -using D3D12CreateDeviceProcType = HRESULT(WINAPI*)( - _In_opt_ IUnknown* pAdapter, - D3D_FEATURE_LEVEL MinimumFeatureLevel, - _In_ REFIID riid, - _COM_Outptr_opt_ void** ppDevice); - -using D3D12GetDebugInterfaceProcType = HRESULT(WINAPI*)( - _In_ REFIID riid, - _COM_Outptr_opt_ void** ppvDebug); - -using D3D12SerializeRootSignatureProcType = HRESULT(WINAPI*)( - _In_ const D3D12_ROOT_SIGNATURE_DESC* pRootSignature, - _In_ D3D_ROOT_SIGNATURE_VERSION Version, - _Out_ ID3DBlob** ppBlob, - _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob); - -extern D3D12CreateDeviceProcType D3D12CreateDevice; -extern D3D12GetDebugInterfaceProcType D3D12GetDebugInterface; -extern D3D12SerializeRootSignatureProcType D3D12SerializeRootSignature; - -HMODULE LoadD3D12Dll(const char* DLLPath = "d3d12.dll"); - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12Loader.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12Loader.hpp new file mode 100644 index 00000000..8e5b346d --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/D3D12Loader.hpp @@ -0,0 +1,57 @@ +/* + * Copyright 2019-2020 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 + +#include + +namespace Diligent +{ + +using D3D12CreateDeviceProcType = HRESULT(WINAPI*)( + _In_opt_ IUnknown* pAdapter, + D3D_FEATURE_LEVEL MinimumFeatureLevel, + _In_ REFIID riid, + _COM_Outptr_opt_ void** ppDevice); + +using D3D12GetDebugInterfaceProcType = HRESULT(WINAPI*)( + _In_ REFIID riid, + _COM_Outptr_opt_ void** ppvDebug); + +using D3D12SerializeRootSignatureProcType = HRESULT(WINAPI*)( + _In_ const D3D12_ROOT_SIGNATURE_DESC* pRootSignature, + _In_ D3D_ROOT_SIGNATURE_VERSION Version, + _Out_ ID3DBlob** ppBlob, + _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob); + +extern D3D12CreateDeviceProcType D3D12CreateDevice; +extern D3D12GetDebugInterfaceProcType D3D12GetDebugInterface; +extern D3D12SerializeRootSignatureProcType D3D12SerializeRootSignature; + +HMODULE LoadD3D12Dll(const char* DLLPath = "d3d12.dll"); + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h deleted file mode 100644 index 240ea165..00000000 --- a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2020 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::D3D12ResourceBase class - -namespace Diligent -{ - -/// Base implementation of a D3D12 resource -class D3D12ResourceBase -{ -public: - D3D12ResourceBase() - {} - - ID3D12Resource* GetD3D12Resource() { return m_pd3d12Resource; } - -protected: - CComPtr m_pd3d12Resource; ///< D3D12 buffer object -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp new file mode 100644 index 00000000..240ea165 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2019-2020 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::D3D12ResourceBase class + +namespace Diligent +{ + +/// Base implementation of a D3D12 resource +class D3D12ResourceBase +{ +public: + D3D12ResourceBase() + {} + + ID3D12Resource* GetD3D12Resource() { return m_pd3d12Resource; } + +protected: + CComPtr m_pd3d12Resource; ///< D3D12 buffer object +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h deleted file mode 100644 index d8108c06..00000000 --- a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright 2019-2020 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. - */ - -// Descriptor heap management utilities. -// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/ for details - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "ObjectBase.h" -#include "VariableSizeAllocationsManager.hpp" - -namespace Diligent -{ - -class DescriptorHeapAllocation; -class DescriptorHeapAllocationManager; -class RenderDeviceD3D12Impl; - -class IDescriptorAllocator -{ -public: - // Allocate Count descriptors - virtual DescriptorHeapAllocation Allocate(uint32_t Count) = 0; - virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) = 0; - virtual Uint32 GetDescriptorSize() const = 0; -}; - - -// The class represents descriptor heap allocation (continuous descriptor range in a descriptor heap) -// -// m_FirstCpuHandle -// | -// | ~ ~ ~ ~ ~ X X X X X X X ~ ~ ~ ~ ~ ~ | D3D12 Descriptor Heap -// | -// m_FirstGpuHandle -// -class DescriptorHeapAllocation -{ -public: - // Creates null allocation - DescriptorHeapAllocation() noexcept : - // clang-format off - m_NumHandles {1 }, // One null descriptor handle - m_pDescriptorHeap {nullptr}, - m_DescriptorSize {0 } - // clang-format on - { - m_FirstCpuHandle.ptr = 0; - m_FirstGpuHandle.ptr = 0; - } - - // Initializes non-null allocation - DescriptorHeapAllocation(IDescriptorAllocator& Allocator, - ID3D12DescriptorHeap* pHeap, - D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, - D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, - Uint32 NHandles, - Uint16 AllocationManagerId) noexcept : - // clang-format off - m_FirstCpuHandle {CpuHandle }, - m_FirstGpuHandle {GpuHandle }, - m_pAllocator {&Allocator }, - m_NumHandles {NHandles }, - m_pDescriptorHeap {pHeap }, - m_AllocationManagerId {AllocationManagerId} - // clang-format on - { - VERIFY_EXPR(m_pAllocator != nullptr && m_pDescriptorHeap != nullptr); - auto DescriptorSize = m_pAllocator->GetDescriptorSize(); - VERIFY(DescriptorSize < std::numeric_limits::max(), "DescriptorSize exceeds allowed limit"); - m_DescriptorSize = static_cast(DescriptorSize); - } - - // Move constructor (copy is not allowed) - DescriptorHeapAllocation(DescriptorHeapAllocation&& Allocation) noexcept : - // clang-format off - m_FirstCpuHandle {std::move(Allocation.m_FirstCpuHandle) }, - m_FirstGpuHandle {std::move(Allocation.m_FirstGpuHandle) }, - m_NumHandles {std::move(Allocation.m_NumHandles) }, - m_pAllocator {std::move(Allocation.m_pAllocator) }, - m_AllocationManagerId {std::move(Allocation.m_AllocationManagerId)}, - m_pDescriptorHeap {std::move(Allocation.m_pDescriptorHeap) }, - m_DescriptorSize {std::move(Allocation.m_DescriptorSize) } - // clang-format on - { - Allocation.Reset(); - } - - // Move assignment (assignment is not allowed) - DescriptorHeapAllocation& operator=(DescriptorHeapAllocation&& Allocation) noexcept - { - m_FirstCpuHandle = std::move(Allocation.m_FirstCpuHandle); - m_FirstGpuHandle = std::move(Allocation.m_FirstGpuHandle); - m_NumHandles = std::move(Allocation.m_NumHandles); - m_pAllocator = std::move(Allocation.m_pAllocator); - m_AllocationManagerId = std::move(Allocation.m_AllocationManagerId); - m_pDescriptorHeap = std::move(Allocation.m_pDescriptorHeap); - m_DescriptorSize = std::move(Allocation.m_DescriptorSize); - - Allocation.Reset(); - - return *this; - } - - void Reset() - { - m_FirstCpuHandle.ptr = 0; - m_FirstGpuHandle.ptr = 0; - m_pAllocator = nullptr; - m_pDescriptorHeap = nullptr; - m_NumHandles = 0; - m_AllocationManagerId = static_cast(-1); - m_DescriptorSize = 0; - } - - // clang-format off - DescriptorHeapAllocation (const DescriptorHeapAllocation&) = delete; - DescriptorHeapAllocation& operator=(const DescriptorHeapAllocation&) = delete; - // clang-format on - - - // Destructor automatically releases this allocation through the allocator - ~DescriptorHeapAllocation() - { - if (!IsNull() && m_pAllocator) - m_pAllocator->Free(std::move(*this), ~Uint64{0}); - // Allocation must have been disposed by the allocator - VERIFY(IsNull(), "Non-null descriptor is being destroyed"); - } - - // Returns CPU descriptor handle at the specified offset - D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Uint32 Offset = 0) const - { - VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles); - - D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle = m_FirstCpuHandle; - CPUHandle.ptr += m_DescriptorSize * Offset; - - return CPUHandle; - } - - // Returns GPU descriptor handle at the specified offset - D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Uint32 Offset = 0) const - { - VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles); - D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle = m_FirstGpuHandle; - GPUHandle.ptr += m_DescriptorSize * Offset; - - return GPUHandle; - } - - // Returns pointer to D3D12 descriptor heap that contains this allocation - ID3D12DescriptorHeap* GetDescriptorHeap() { return m_pDescriptorHeap; } - - - // clang-format off - size_t GetNumHandles() const { return m_NumHandles; } - bool IsNull() const { return m_FirstCpuHandle.ptr == 0; } - bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; } - size_t GetAllocationManagerId() const { return m_AllocationManagerId; } - UINT GetDescriptorSize() const { return m_DescriptorSize; } - // clang-format on - -private: - // First CPU descriptor handle in this allocation - D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCpuHandle = {0}; - - // First GPU descriptor handle in this allocation - D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGpuHandle = {0}; - - // Keep strong reference to the parent heap to make sure it is alive while allocation is alive - TOO EXPENSIVE - //RefCntAutoPtr m_pAllocator; - - // Pointer to the descriptor heap allocator that created this allocation - IDescriptorAllocator* m_pAllocator = nullptr; - - // Pointer to the D3D12 descriptor heap that contains descriptors in this allocation - ID3D12DescriptorHeap* m_pDescriptorHeap = nullptr; - - // Number of descriptors in the allocation - Uint32 m_NumHandles = 0; - - // Allocation manager ID. One allocator may support several - // allocation managers. This field is required to identify - // the manager within the allocator that was used to create - // this allocation - Uint16 m_AllocationManagerId = static_cast(-1); - - // Descriptor size - Uint16 m_DescriptorSize = 0; -}; - - -// The class performs suballocations within one D3D12 descriptor heap. -// It uses VariableSizeAllocationsManager to manage free space in the heap -// -// | X X X X O O O X X O O X O O O O | D3D12 descriptor heap -// -// X - used descriptor -// O - available descriptor -// -class DescriptorHeapAllocationManager -{ -public: - // Creates a new D3D12 descriptor heap - DescriptorHeapAllocationManager(IMemoryAllocator& Allocator, - RenderDeviceD3D12Impl& DeviceD3D12Impl, - IDescriptorAllocator& ParentAllocator, - size_t ThisManagerId, - const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc); - - // Uses subrange of descriptors in the existing D3D12 descriptor heap - // that starts at offset FirstDescriptor and uses NumDescriptors descriptors - DescriptorHeapAllocationManager(IMemoryAllocator& Allocator, - RenderDeviceD3D12Impl& DeviceD3D12Impl, - IDescriptorAllocator& ParentAllocator, - size_t ThisManagerId, - ID3D12DescriptorHeap* pd3d12DescriptorHeap, - Uint32 FirstDescriptor, - Uint32 NumDescriptors); - - - // = default causes compiler error when instantiating std::vector::emplace_back() in Visual Studio 2015 (Version 14.0.23107.0 D14REL) - DescriptorHeapAllocationManager(DescriptorHeapAllocationManager&& rhs) noexcept : - // clang-format off - m_ParentAllocator {rhs.m_ParentAllocator }, - m_DeviceD3D12Impl {rhs.m_DeviceD3D12Impl }, - m_ThisManagerId {rhs.m_ThisManagerId }, - m_HeapDesc {rhs.m_HeapDesc }, - m_DescriptorSize {rhs.m_DescriptorSize }, - m_NumDescriptorsInAllocation{rhs.m_NumDescriptorsInAllocation}, - m_FirstCPUHandle {rhs.m_FirstCPUHandle }, - m_FirstGPUHandle {rhs.m_FirstGPUHandle }, - m_MaxAllocatedSize {rhs.m_MaxAllocatedSize }, - // Mutex is not movable - //m_FreeBlockManagerMutex (std::move(rhs.m_FreeBlockManagerMutex)) - m_FreeBlockManager {std::move(rhs.m_FreeBlockManager) }, - m_pd3d12DescriptorHeap {std::move(rhs.m_pd3d12DescriptorHeap)} - // clang-format on - { - rhs.m_NumDescriptorsInAllocation = 0; // Must be set to zero so that debug check in dtor passes - rhs.m_ThisManagerId = static_cast(-1); - rhs.m_FirstCPUHandle.ptr = 0; - rhs.m_FirstGPUHandle.ptr = 0; - rhs.m_MaxAllocatedSize = 0; -#ifdef DEVELOPMENT - m_AllocationsCounter.store(rhs.m_AllocationsCounter.load()); - rhs.m_AllocationsCounter = 0; -#endif - } - - // clang-format off - // No copies or move-assignments - DescriptorHeapAllocationManager& operator = (DescriptorHeapAllocationManager&&) = delete; - DescriptorHeapAllocationManager (const DescriptorHeapAllocationManager&) = delete; - DescriptorHeapAllocationManager& operator = (const DescriptorHeapAllocationManager&) = delete; - // clang-format on - - ~DescriptorHeapAllocationManager(); - - // Allocates Count descriptors - DescriptorHeapAllocation Allocate(uint32_t Count); - void FreeAllocation(DescriptorHeapAllocation&& Allocation); - - // clang-format off - size_t GetNumAvailableDescriptors()const { return m_FreeBlockManager.GetFreeSize(); } - Uint32 GetMaxDescriptors() const { return m_NumDescriptorsInAllocation; } - size_t GetMaxAllocatedSize() const { return m_MaxAllocatedSize; } - // clang-format on - -#ifdef DEVELOPMENT - int32_t DvpGetAllocationsCounter() const - { - return m_AllocationsCounter; - } -#endif - -private: - IDescriptorAllocator& m_ParentAllocator; - RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - - // External ID assigned to this descriptor allocations manager - size_t m_ThisManagerId = static_cast(-1); - - // Heap description - const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; - - const UINT m_DescriptorSize = 0; - - // Number of descriptors in the allocation. - // If this manager was initialized as a subrange in the existing heap, - // this value may be different from m_HeapDesc.NumDescriptors - Uint32 m_NumDescriptorsInAllocation = 0; - - // Allocations manager used to handle descriptor allocations within the heap - std::mutex m_FreeBlockManagerMutex; - VariableSizeAllocationsManager m_FreeBlockManager; - - // Strong reference to D3D12 descriptor heap object - CComPtr m_pd3d12DescriptorHeap; - - // First CPU descriptor handle in the available descriptor range - D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCPUHandle = {0}; - - // First GPU descriptor handle in the available descriptor range - D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGPUHandle = {0}; - - size_t m_MaxAllocatedSize = 0; - -#ifdef DEVELOPMENT - std::atomic_int32_t m_AllocationsCounter = 0; -#endif - - // Note: when adding new members, do not forget to update move ctor -}; - -// CPU descriptor heap is intended to provide storage for resource view descriptor handles. -// It contains a pool of DescriptorHeapAllocationManager object instances, where every instance manages -// its own CPU-only D3D12 descriptor heap: -// -// m_HeapPool[0] m_HeapPool[1] m_HeapPool[2] -// | X X X X X X X X |, | X X X O O X X O |, | X O O O O O O O | -// -// X - used descriptor m_AvailableHeaps = {1,2} -// O - available descriptor -// -// Allocation routine goes through the list of managers that have available descriptors and tries to process -// the request using every manager. If there are no available managers or no manager was able to handle the request, -// the function creates a new descriptor heap manager and lets it handle the request -// -// Render device contains four CPUDescriptorHeap object instances (one for each D3D12 heap type). The heaps are accessed -// when a texture or a buffer view is created. -// -class CPUDescriptorHeap final : public IDescriptorAllocator -{ -public: - // Initializes the heap - CPUDescriptorHeap(IMemoryAllocator& Allocator, - RenderDeviceD3D12Impl& DeviceD3D12Impl, - Uint32 NumDescriptorsInHeap, - D3D12_DESCRIPTOR_HEAP_TYPE Type, - D3D12_DESCRIPTOR_HEAP_FLAGS Flags); - - // clang-format off - CPUDescriptorHeap (const CPUDescriptorHeap&) = delete; - CPUDescriptorHeap (CPUDescriptorHeap&&) = delete; - CPUDescriptorHeap& operator = (const CPUDescriptorHeap&) = delete; - CPUDescriptorHeap& operator = (CPUDescriptorHeap&&) = delete; - // clang-format on - - ~CPUDescriptorHeap(); - - virtual DescriptorHeapAllocation Allocate(uint32_t Count) override final; - virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final; - virtual Uint32 GetDescriptorSize() const override final { return m_DescriptorSize; } - -#ifdef DEVELOPMENT - int32_t DvpGetTotalAllocationCount(); -#endif - -private: - void FreeAllocation(DescriptorHeapAllocation&& Allocation); - - IMemoryAllocator& m_MemAllocator; - RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - - // Pool of descriptor heap managers - std::mutex m_HeapPoolMutex; - std::vector> m_HeapPool; - // Indices of available descriptor heap managers - std::unordered_set, std::equal_to, STDAllocatorRawMem> m_AvailableHeaps; - - D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; - const UINT m_DescriptorSize = 0; - - // Maximum heap size during the application lifetime - for statistic purposes - Uint32 m_MaxSize = 0; - Uint32 m_CurrentSize = 0; -}; - -// GPU descriptor heap provides storage for shader-visible descriptors -// The heap contains single D3D12 descriptor heap that is split into two parts. -// The first part stores static and mutable resource descriptor handles. -// The second part is intended to provide temporary storage for dynamic resources. -// Space for dynamic resources is allocated in chunks, and then descriptors are suballocated within every -// chunk. DynamicSuballocationsManager facilitates this process. -// -// -// static and mutable handles || dynamic space -// || chunk 0 chunk 1 chunk 2 unused -// | X O O X X O X O O O O X X X X O || | X X X O | | X X O O | | O O O O | O O O O || -// | | -// suballocation suballocation -// within chunk 0 within chunk 1 -// -// Render device contains two GPUDescriptorHeap instances (CBV_SRV_UAV and SAMPLER). The heaps -// are used to allocate GPU-visible descriptors for shader resource binding objects. The heaps -// are also used by the command contexts (through DynamicSuballocationsManager to allocated dynamic descriptors) -// -// _______________________________________________________________________________________________________________________________ -// | Render Device | -// | | -// | m_CPUDescriptorHeaps[CBV_SRV_UAV] | X X X X X X X X |, | X X X X X X X X |, | X O O X O O O O | | -// | m_CPUDescriptorHeaps[SAMPLER] | X X X X O O O X |, | X O O X O O O O | | -// | m_CPUDescriptorHeaps[RTV] | X X X O O O O O |, | O O O O O O O O | | -// | m_CPUDescriptorHeaps[DSV] | X X X O X O X O | | -// | ctx1 ctx2 | -// | m_GPUDescriptorHeaps[CBV_SRV_UAV] | X O O X X O X O O O O X X X X O || | X X X O | | X X O O | | O O O O | O O O O || | -// | m_GPUDescriptorHeaps[SAMPLER] | X X O O X O X X X O O X O O O O || | X X O O | | X O O O | | O O O O | O O O O || | -// | | -// |_______________________________________________________________________________________________________________________________| -// -// ________________________________________________ ________________________________________________ -// |Device Context 1 | |Device Context 2 | -// | | | | -// | m_DynamicGPUDescriptorAllocator[CBV_SRV_UAV] | | m_DynamicGPUDescriptorAllocator[CBV_SRV_UAV] | -// | m_DynamicGPUDescriptorAllocator[SAMPLER] | | m_DynamicGPUDescriptorAllocator[SAMPLER] | -// |________________________________________________| |________________________________________________| -// -class GPUDescriptorHeap final : public IDescriptorAllocator -{ -public: - GPUDescriptorHeap(IMemoryAllocator& Allocator, - RenderDeviceD3D12Impl& Device, - Uint32 NumDescriptorsInHeap, - Uint32 NumDynamicDescriptors, - D3D12_DESCRIPTOR_HEAP_TYPE Type, - D3D12_DESCRIPTOR_HEAP_FLAGS Flags); - - // clang-format off - GPUDescriptorHeap (const GPUDescriptorHeap&) = delete; - GPUDescriptorHeap (GPUDescriptorHeap&&) = delete; - GPUDescriptorHeap& operator = (const GPUDescriptorHeap&) = delete; - GPUDescriptorHeap& operator = (GPUDescriptorHeap&&) = delete; - // clang-format on - - ~GPUDescriptorHeap(); - - virtual DescriptorHeapAllocation Allocate(uint32_t Count) override final - { - return m_HeapAllocationManager.Allocate(Count); - } - - virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final; - virtual Uint32 GetDescriptorSize() const override final { return m_DescriptorSize; } - - DescriptorHeapAllocation AllocateDynamic(uint32_t Count) - { - return m_DynamicAllocationsManager.Allocate(Count); - } - - const D3D12_DESCRIPTOR_HEAP_DESC& GetHeapDesc() const { return m_HeapDesc; } - Uint32 GetMaxStaticDescriptors() const { return m_HeapAllocationManager.GetMaxDescriptors(); } - Uint32 GetMaxDynamicDescriptors() const { return m_DynamicAllocationsManager.GetMaxDescriptors(); } - -#ifdef DEVELOPMENT - int32_t DvpGetTotalAllocationCount() const - { - return m_HeapAllocationManager.DvpGetAllocationsCounter() + - m_DynamicAllocationsManager.DvpGetAllocationsCounter(); - } -#endif - -protected: - RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - - const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; - CComPtr m_pd3d12DescriptorHeap; - - const UINT m_DescriptorSize; - - // Allocation manager for static/mutable part - DescriptorHeapAllocationManager m_HeapAllocationManager; - - // Allocation manager for dynamic part - DescriptorHeapAllocationManager m_DynamicAllocationsManager; -}; - - -// The class facilitates allocation of dynamic descriptor handles. It requests a chunk of heap -// from the master GPU descriptor heap and then performs linear suballocation within the chunk -// At the end of the frame all allocations are disposed. - -// static and mutable handles || dynamic space -// || chunk 0 chunk 2 -// | || | X X X O | | O O O O | || GPU Descriptor Heap -// | | -// m_Suballocations[0] m_Suballocations[1] -// -class DynamicSuballocationsManager final : public IDescriptorAllocator -{ -public: - DynamicSuballocationsManager(IMemoryAllocator& Allocator, - GPUDescriptorHeap& ParentGPUHeap, - Uint32 DynamicChunkSize, - String ManagerName); - - // clang-format off - DynamicSuballocationsManager (const DynamicSuballocationsManager&) = delete; - DynamicSuballocationsManager (DynamicSuballocationsManager&&) = delete; - DynamicSuballocationsManager& operator = (const DynamicSuballocationsManager&) = delete; - DynamicSuballocationsManager& operator = (DynamicSuballocationsManager&&) = delete; - // clang-format on - - ~DynamicSuballocationsManager(); - - void ReleaseAllocations(Uint64 CmdQueueMask); - - virtual DescriptorHeapAllocation Allocate(Uint32 Count) override final; - virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final - { - // Do nothing. Dynamic allocations are not disposed individually, but as whole chunks - // at the end of the frame by ReleaseAllocations() - Allocation.Reset(); - } - - virtual Uint32 GetDescriptorSize() const override final { return m_ParentGPUHeap.GetDescriptorSize(); } - - size_t GetSuballocationCount() const { return m_Suballocations.size(); } - -private: - // Parent GPU descriptor heap that is used to allocate chunks - GPUDescriptorHeap& m_ParentGPUHeap; - const String m_ManagerName; - - // List of chunks allocated from the master GPU descriptor heap. All chunks are disposed at the end - // of the frame - std::vector> m_Suballocations; - - Uint32 m_CurrentSuballocationOffset = 0; - Uint32 m_DynamicChunkSize = 0; - - Uint32 m_CurrDescriptorCount = 0; - Uint32 m_PeakDescriptorCount = 0; - Uint32 m_CurrSuballocationsTotalSize = 0; - Uint32 m_PeakSuballocationsTotalSize = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp new file mode 100644 index 00000000..d8108c06 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp @@ -0,0 +1,569 @@ +/* + * Copyright 2019-2020 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. + */ + +// Descriptor heap management utilities. +// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/ for details + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "ObjectBase.h" +#include "VariableSizeAllocationsManager.hpp" + +namespace Diligent +{ + +class DescriptorHeapAllocation; +class DescriptorHeapAllocationManager; +class RenderDeviceD3D12Impl; + +class IDescriptorAllocator +{ +public: + // Allocate Count descriptors + virtual DescriptorHeapAllocation Allocate(uint32_t Count) = 0; + virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) = 0; + virtual Uint32 GetDescriptorSize() const = 0; +}; + + +// The class represents descriptor heap allocation (continuous descriptor range in a descriptor heap) +// +// m_FirstCpuHandle +// | +// | ~ ~ ~ ~ ~ X X X X X X X ~ ~ ~ ~ ~ ~ | D3D12 Descriptor Heap +// | +// m_FirstGpuHandle +// +class DescriptorHeapAllocation +{ +public: + // Creates null allocation + DescriptorHeapAllocation() noexcept : + // clang-format off + m_NumHandles {1 }, // One null descriptor handle + m_pDescriptorHeap {nullptr}, + m_DescriptorSize {0 } + // clang-format on + { + m_FirstCpuHandle.ptr = 0; + m_FirstGpuHandle.ptr = 0; + } + + // Initializes non-null allocation + DescriptorHeapAllocation(IDescriptorAllocator& Allocator, + ID3D12DescriptorHeap* pHeap, + D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle, + D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle, + Uint32 NHandles, + Uint16 AllocationManagerId) noexcept : + // clang-format off + m_FirstCpuHandle {CpuHandle }, + m_FirstGpuHandle {GpuHandle }, + m_pAllocator {&Allocator }, + m_NumHandles {NHandles }, + m_pDescriptorHeap {pHeap }, + m_AllocationManagerId {AllocationManagerId} + // clang-format on + { + VERIFY_EXPR(m_pAllocator != nullptr && m_pDescriptorHeap != nullptr); + auto DescriptorSize = m_pAllocator->GetDescriptorSize(); + VERIFY(DescriptorSize < std::numeric_limits::max(), "DescriptorSize exceeds allowed limit"); + m_DescriptorSize = static_cast(DescriptorSize); + } + + // Move constructor (copy is not allowed) + DescriptorHeapAllocation(DescriptorHeapAllocation&& Allocation) noexcept : + // clang-format off + m_FirstCpuHandle {std::move(Allocation.m_FirstCpuHandle) }, + m_FirstGpuHandle {std::move(Allocation.m_FirstGpuHandle) }, + m_NumHandles {std::move(Allocation.m_NumHandles) }, + m_pAllocator {std::move(Allocation.m_pAllocator) }, + m_AllocationManagerId {std::move(Allocation.m_AllocationManagerId)}, + m_pDescriptorHeap {std::move(Allocation.m_pDescriptorHeap) }, + m_DescriptorSize {std::move(Allocation.m_DescriptorSize) } + // clang-format on + { + Allocation.Reset(); + } + + // Move assignment (assignment is not allowed) + DescriptorHeapAllocation& operator=(DescriptorHeapAllocation&& Allocation) noexcept + { + m_FirstCpuHandle = std::move(Allocation.m_FirstCpuHandle); + m_FirstGpuHandle = std::move(Allocation.m_FirstGpuHandle); + m_NumHandles = std::move(Allocation.m_NumHandles); + m_pAllocator = std::move(Allocation.m_pAllocator); + m_AllocationManagerId = std::move(Allocation.m_AllocationManagerId); + m_pDescriptorHeap = std::move(Allocation.m_pDescriptorHeap); + m_DescriptorSize = std::move(Allocation.m_DescriptorSize); + + Allocation.Reset(); + + return *this; + } + + void Reset() + { + m_FirstCpuHandle.ptr = 0; + m_FirstGpuHandle.ptr = 0; + m_pAllocator = nullptr; + m_pDescriptorHeap = nullptr; + m_NumHandles = 0; + m_AllocationManagerId = static_cast(-1); + m_DescriptorSize = 0; + } + + // clang-format off + DescriptorHeapAllocation (const DescriptorHeapAllocation&) = delete; + DescriptorHeapAllocation& operator=(const DescriptorHeapAllocation&) = delete; + // clang-format on + + + // Destructor automatically releases this allocation through the allocator + ~DescriptorHeapAllocation() + { + if (!IsNull() && m_pAllocator) + m_pAllocator->Free(std::move(*this), ~Uint64{0}); + // Allocation must have been disposed by the allocator + VERIFY(IsNull(), "Non-null descriptor is being destroyed"); + } + + // Returns CPU descriptor handle at the specified offset + D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Uint32 Offset = 0) const + { + VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles); + + D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle = m_FirstCpuHandle; + CPUHandle.ptr += m_DescriptorSize * Offset; + + return CPUHandle; + } + + // Returns GPU descriptor handle at the specified offset + D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Uint32 Offset = 0) const + { + VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles); + D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle = m_FirstGpuHandle; + GPUHandle.ptr += m_DescriptorSize * Offset; + + return GPUHandle; + } + + // Returns pointer to D3D12 descriptor heap that contains this allocation + ID3D12DescriptorHeap* GetDescriptorHeap() { return m_pDescriptorHeap; } + + + // clang-format off + size_t GetNumHandles() const { return m_NumHandles; } + bool IsNull() const { return m_FirstCpuHandle.ptr == 0; } + bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; } + size_t GetAllocationManagerId() const { return m_AllocationManagerId; } + UINT GetDescriptorSize() const { return m_DescriptorSize; } + // clang-format on + +private: + // First CPU descriptor handle in this allocation + D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCpuHandle = {0}; + + // First GPU descriptor handle in this allocation + D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGpuHandle = {0}; + + // Keep strong reference to the parent heap to make sure it is alive while allocation is alive - TOO EXPENSIVE + //RefCntAutoPtr m_pAllocator; + + // Pointer to the descriptor heap allocator that created this allocation + IDescriptorAllocator* m_pAllocator = nullptr; + + // Pointer to the D3D12 descriptor heap that contains descriptors in this allocation + ID3D12DescriptorHeap* m_pDescriptorHeap = nullptr; + + // Number of descriptors in the allocation + Uint32 m_NumHandles = 0; + + // Allocation manager ID. One allocator may support several + // allocation managers. This field is required to identify + // the manager within the allocator that was used to create + // this allocation + Uint16 m_AllocationManagerId = static_cast(-1); + + // Descriptor size + Uint16 m_DescriptorSize = 0; +}; + + +// The class performs suballocations within one D3D12 descriptor heap. +// It uses VariableSizeAllocationsManager to manage free space in the heap +// +// | X X X X O O O X X O O X O O O O | D3D12 descriptor heap +// +// X - used descriptor +// O - available descriptor +// +class DescriptorHeapAllocationManager +{ +public: + // Creates a new D3D12 descriptor heap + DescriptorHeapAllocationManager(IMemoryAllocator& Allocator, + RenderDeviceD3D12Impl& DeviceD3D12Impl, + IDescriptorAllocator& ParentAllocator, + size_t ThisManagerId, + const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc); + + // Uses subrange of descriptors in the existing D3D12 descriptor heap + // that starts at offset FirstDescriptor and uses NumDescriptors descriptors + DescriptorHeapAllocationManager(IMemoryAllocator& Allocator, + RenderDeviceD3D12Impl& DeviceD3D12Impl, + IDescriptorAllocator& ParentAllocator, + size_t ThisManagerId, + ID3D12DescriptorHeap* pd3d12DescriptorHeap, + Uint32 FirstDescriptor, + Uint32 NumDescriptors); + + + // = default causes compiler error when instantiating std::vector::emplace_back() in Visual Studio 2015 (Version 14.0.23107.0 D14REL) + DescriptorHeapAllocationManager(DescriptorHeapAllocationManager&& rhs) noexcept : + // clang-format off + m_ParentAllocator {rhs.m_ParentAllocator }, + m_DeviceD3D12Impl {rhs.m_DeviceD3D12Impl }, + m_ThisManagerId {rhs.m_ThisManagerId }, + m_HeapDesc {rhs.m_HeapDesc }, + m_DescriptorSize {rhs.m_DescriptorSize }, + m_NumDescriptorsInAllocation{rhs.m_NumDescriptorsInAllocation}, + m_FirstCPUHandle {rhs.m_FirstCPUHandle }, + m_FirstGPUHandle {rhs.m_FirstGPUHandle }, + m_MaxAllocatedSize {rhs.m_MaxAllocatedSize }, + // Mutex is not movable + //m_FreeBlockManagerMutex (std::move(rhs.m_FreeBlockManagerMutex)) + m_FreeBlockManager {std::move(rhs.m_FreeBlockManager) }, + m_pd3d12DescriptorHeap {std::move(rhs.m_pd3d12DescriptorHeap)} + // clang-format on + { + rhs.m_NumDescriptorsInAllocation = 0; // Must be set to zero so that debug check in dtor passes + rhs.m_ThisManagerId = static_cast(-1); + rhs.m_FirstCPUHandle.ptr = 0; + rhs.m_FirstGPUHandle.ptr = 0; + rhs.m_MaxAllocatedSize = 0; +#ifdef DEVELOPMENT + m_AllocationsCounter.store(rhs.m_AllocationsCounter.load()); + rhs.m_AllocationsCounter = 0; +#endif + } + + // clang-format off + // No copies or move-assignments + DescriptorHeapAllocationManager& operator = (DescriptorHeapAllocationManager&&) = delete; + DescriptorHeapAllocationManager (const DescriptorHeapAllocationManager&) = delete; + DescriptorHeapAllocationManager& operator = (const DescriptorHeapAllocationManager&) = delete; + // clang-format on + + ~DescriptorHeapAllocationManager(); + + // Allocates Count descriptors + DescriptorHeapAllocation Allocate(uint32_t Count); + void FreeAllocation(DescriptorHeapAllocation&& Allocation); + + // clang-format off + size_t GetNumAvailableDescriptors()const { return m_FreeBlockManager.GetFreeSize(); } + Uint32 GetMaxDescriptors() const { return m_NumDescriptorsInAllocation; } + size_t GetMaxAllocatedSize() const { return m_MaxAllocatedSize; } + // clang-format on + +#ifdef DEVELOPMENT + int32_t DvpGetAllocationsCounter() const + { + return m_AllocationsCounter; + } +#endif + +private: + IDescriptorAllocator& m_ParentAllocator; + RenderDeviceD3D12Impl& m_DeviceD3D12Impl; + + // External ID assigned to this descriptor allocations manager + size_t m_ThisManagerId = static_cast(-1); + + // Heap description + const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; + + const UINT m_DescriptorSize = 0; + + // Number of descriptors in the allocation. + // If this manager was initialized as a subrange in the existing heap, + // this value may be different from m_HeapDesc.NumDescriptors + Uint32 m_NumDescriptorsInAllocation = 0; + + // Allocations manager used to handle descriptor allocations within the heap + std::mutex m_FreeBlockManagerMutex; + VariableSizeAllocationsManager m_FreeBlockManager; + + // Strong reference to D3D12 descriptor heap object + CComPtr m_pd3d12DescriptorHeap; + + // First CPU descriptor handle in the available descriptor range + D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCPUHandle = {0}; + + // First GPU descriptor handle in the available descriptor range + D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGPUHandle = {0}; + + size_t m_MaxAllocatedSize = 0; + +#ifdef DEVELOPMENT + std::atomic_int32_t m_AllocationsCounter = 0; +#endif + + // Note: when adding new members, do not forget to update move ctor +}; + +// CPU descriptor heap is intended to provide storage for resource view descriptor handles. +// It contains a pool of DescriptorHeapAllocationManager object instances, where every instance manages +// its own CPU-only D3D12 descriptor heap: +// +// m_HeapPool[0] m_HeapPool[1] m_HeapPool[2] +// | X X X X X X X X |, | X X X O O X X O |, | X O O O O O O O | +// +// X - used descriptor m_AvailableHeaps = {1,2} +// O - available descriptor +// +// Allocation routine goes through the list of managers that have available descriptors and tries to process +// the request using every manager. If there are no available managers or no manager was able to handle the request, +// the function creates a new descriptor heap manager and lets it handle the request +// +// Render device contains four CPUDescriptorHeap object instances (one for each D3D12 heap type). The heaps are accessed +// when a texture or a buffer view is created. +// +class CPUDescriptorHeap final : public IDescriptorAllocator +{ +public: + // Initializes the heap + CPUDescriptorHeap(IMemoryAllocator& Allocator, + RenderDeviceD3D12Impl& DeviceD3D12Impl, + Uint32 NumDescriptorsInHeap, + D3D12_DESCRIPTOR_HEAP_TYPE Type, + D3D12_DESCRIPTOR_HEAP_FLAGS Flags); + + // clang-format off + CPUDescriptorHeap (const CPUDescriptorHeap&) = delete; + CPUDescriptorHeap (CPUDescriptorHeap&&) = delete; + CPUDescriptorHeap& operator = (const CPUDescriptorHeap&) = delete; + CPUDescriptorHeap& operator = (CPUDescriptorHeap&&) = delete; + // clang-format on + + ~CPUDescriptorHeap(); + + virtual DescriptorHeapAllocation Allocate(uint32_t Count) override final; + virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final; + virtual Uint32 GetDescriptorSize() const override final { return m_DescriptorSize; } + +#ifdef DEVELOPMENT + int32_t DvpGetTotalAllocationCount(); +#endif + +private: + void FreeAllocation(DescriptorHeapAllocation&& Allocation); + + IMemoryAllocator& m_MemAllocator; + RenderDeviceD3D12Impl& m_DeviceD3D12Impl; + + // Pool of descriptor heap managers + std::mutex m_HeapPoolMutex; + std::vector> m_HeapPool; + // Indices of available descriptor heap managers + std::unordered_set, std::equal_to, STDAllocatorRawMem> m_AvailableHeaps; + + D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; + const UINT m_DescriptorSize = 0; + + // Maximum heap size during the application lifetime - for statistic purposes + Uint32 m_MaxSize = 0; + Uint32 m_CurrentSize = 0; +}; + +// GPU descriptor heap provides storage for shader-visible descriptors +// The heap contains single D3D12 descriptor heap that is split into two parts. +// The first part stores static and mutable resource descriptor handles. +// The second part is intended to provide temporary storage for dynamic resources. +// Space for dynamic resources is allocated in chunks, and then descriptors are suballocated within every +// chunk. DynamicSuballocationsManager facilitates this process. +// +// +// static and mutable handles || dynamic space +// || chunk 0 chunk 1 chunk 2 unused +// | X O O X X O X O O O O X X X X O || | X X X O | | X X O O | | O O O O | O O O O || +// | | +// suballocation suballocation +// within chunk 0 within chunk 1 +// +// Render device contains two GPUDescriptorHeap instances (CBV_SRV_UAV and SAMPLER). The heaps +// are used to allocate GPU-visible descriptors for shader resource binding objects. The heaps +// are also used by the command contexts (through DynamicSuballocationsManager to allocated dynamic descriptors) +// +// _______________________________________________________________________________________________________________________________ +// | Render Device | +// | | +// | m_CPUDescriptorHeaps[CBV_SRV_UAV] | X X X X X X X X |, | X X X X X X X X |, | X O O X O O O O | | +// | m_CPUDescriptorHeaps[SAMPLER] | X X X X O O O X |, | X O O X O O O O | | +// | m_CPUDescriptorHeaps[RTV] | X X X O O O O O |, | O O O O O O O O | | +// | m_CPUDescriptorHeaps[DSV] | X X X O X O X O | | +// | ctx1 ctx2 | +// | m_GPUDescriptorHeaps[CBV_SRV_UAV] | X O O X X O X O O O O X X X X O || | X X X O | | X X O O | | O O O O | O O O O || | +// | m_GPUDescriptorHeaps[SAMPLER] | X X O O X O X X X O O X O O O O || | X X O O | | X O O O | | O O O O | O O O O || | +// | | +// |_______________________________________________________________________________________________________________________________| +// +// ________________________________________________ ________________________________________________ +// |Device Context 1 | |Device Context 2 | +// | | | | +// | m_DynamicGPUDescriptorAllocator[CBV_SRV_UAV] | | m_DynamicGPUDescriptorAllocator[CBV_SRV_UAV] | +// | m_DynamicGPUDescriptorAllocator[SAMPLER] | | m_DynamicGPUDescriptorAllocator[SAMPLER] | +// |________________________________________________| |________________________________________________| +// +class GPUDescriptorHeap final : public IDescriptorAllocator +{ +public: + GPUDescriptorHeap(IMemoryAllocator& Allocator, + RenderDeviceD3D12Impl& Device, + Uint32 NumDescriptorsInHeap, + Uint32 NumDynamicDescriptors, + D3D12_DESCRIPTOR_HEAP_TYPE Type, + D3D12_DESCRIPTOR_HEAP_FLAGS Flags); + + // clang-format off + GPUDescriptorHeap (const GPUDescriptorHeap&) = delete; + GPUDescriptorHeap (GPUDescriptorHeap&&) = delete; + GPUDescriptorHeap& operator = (const GPUDescriptorHeap&) = delete; + GPUDescriptorHeap& operator = (GPUDescriptorHeap&&) = delete; + // clang-format on + + ~GPUDescriptorHeap(); + + virtual DescriptorHeapAllocation Allocate(uint32_t Count) override final + { + return m_HeapAllocationManager.Allocate(Count); + } + + virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final; + virtual Uint32 GetDescriptorSize() const override final { return m_DescriptorSize; } + + DescriptorHeapAllocation AllocateDynamic(uint32_t Count) + { + return m_DynamicAllocationsManager.Allocate(Count); + } + + const D3D12_DESCRIPTOR_HEAP_DESC& GetHeapDesc() const { return m_HeapDesc; } + Uint32 GetMaxStaticDescriptors() const { return m_HeapAllocationManager.GetMaxDescriptors(); } + Uint32 GetMaxDynamicDescriptors() const { return m_DynamicAllocationsManager.GetMaxDescriptors(); } + +#ifdef DEVELOPMENT + int32_t DvpGetTotalAllocationCount() const + { + return m_HeapAllocationManager.DvpGetAllocationsCounter() + + m_DynamicAllocationsManager.DvpGetAllocationsCounter(); + } +#endif + +protected: + RenderDeviceD3D12Impl& m_DeviceD3D12Impl; + + const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc; + CComPtr m_pd3d12DescriptorHeap; + + const UINT m_DescriptorSize; + + // Allocation manager for static/mutable part + DescriptorHeapAllocationManager m_HeapAllocationManager; + + // Allocation manager for dynamic part + DescriptorHeapAllocationManager m_DynamicAllocationsManager; +}; + + +// The class facilitates allocation of dynamic descriptor handles. It requests a chunk of heap +// from the master GPU descriptor heap and then performs linear suballocation within the chunk +// At the end of the frame all allocations are disposed. + +// static and mutable handles || dynamic space +// || chunk 0 chunk 2 +// | || | X X X O | | O O O O | || GPU Descriptor Heap +// | | +// m_Suballocations[0] m_Suballocations[1] +// +class DynamicSuballocationsManager final : public IDescriptorAllocator +{ +public: + DynamicSuballocationsManager(IMemoryAllocator& Allocator, + GPUDescriptorHeap& ParentGPUHeap, + Uint32 DynamicChunkSize, + String ManagerName); + + // clang-format off + DynamicSuballocationsManager (const DynamicSuballocationsManager&) = delete; + DynamicSuballocationsManager (DynamicSuballocationsManager&&) = delete; + DynamicSuballocationsManager& operator = (const DynamicSuballocationsManager&) = delete; + DynamicSuballocationsManager& operator = (DynamicSuballocationsManager&&) = delete; + // clang-format on + + ~DynamicSuballocationsManager(); + + void ReleaseAllocations(Uint64 CmdQueueMask); + + virtual DescriptorHeapAllocation Allocate(Uint32 Count) override final; + virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) override final + { + // Do nothing. Dynamic allocations are not disposed individually, but as whole chunks + // at the end of the frame by ReleaseAllocations() + Allocation.Reset(); + } + + virtual Uint32 GetDescriptorSize() const override final { return m_ParentGPUHeap.GetDescriptorSize(); } + + size_t GetSuballocationCount() const { return m_Suballocations.size(); } + +private: + // Parent GPU descriptor heap that is used to allocate chunks + GPUDescriptorHeap& m_ParentGPUHeap; + const String m_ManagerName; + + // List of chunks allocated from the master GPU descriptor heap. All chunks are disposed at the end + // of the frame + std::vector> m_Suballocations; + + Uint32 m_CurrentSuballocationOffset = 0; + Uint32 m_DynamicChunkSize = 0; + + Uint32 m_CurrDescriptorCount = 0; + Uint32 m_PeakDescriptorCount = 0; + Uint32 m_CurrSuballocationsTotalSize = 0; + Uint32 m_PeakSuballocationsTotalSize = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h deleted file mode 100644 index 2253dbc2..00000000 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::DeviceContextD3D12Impl class - -#include - -#include "DeviceContextD3D12.h" -#include "DeviceContextNextGenBase.h" -#include "BufferD3D12Impl.h" -#include "TextureD3D12Impl.h" -#include "QueryD3D12Impl.h" -#include "PipelineStateD3D12Impl.h" -#include "D3D12DynamicHeap.h" - -namespace Diligent -{ - -class RenderDeviceD3D12Impl; - -struct DeviceContextD3D12ImplTraits -{ - using BufferType = BufferD3D12Impl; - using TextureType = TextureD3D12Impl; - using PipelineStateType = PipelineStateD3D12Impl; - using DeviceType = RenderDeviceD3D12Impl; - using ICommandQueueType = ICommandQueueD3D12; - using QueryType = QueryD3D12Impl; -}; - -/// Device context implementation in Direct3D12 backend. -class DeviceContextD3D12Impl final : public DeviceContextNextGenBase -{ -public: - using TDeviceContextBase = DeviceContextNextGenBase; - - DeviceContextD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - bool bIsDeferred, - const EngineD3D12CreateInfo& EngineCI, - Uint32 ContextId, - Uint32 CommandQueueId); - ~DeviceContextD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IDeviceContext::SetPipelineState() in Direct3D12 backend. - virtual void SetPipelineState(IPipelineState* pPipelineState) override final; - - /// Implementation of IDeviceContext::TransitionShaderResources() in Direct3D12 backend. - virtual void TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) override final; - - /// Implementation of IDeviceContext::CommitShaderResources() in Direct3D12 backend. - virtual void CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::SetStencilRef() in Direct3D12 backend. - virtual void SetStencilRef(Uint32 StencilRef) override final; - - /// Implementation of IDeviceContext::SetBlendFactors() in Direct3D12 backend. - virtual void SetBlendFactors(const float* pBlendFactors = nullptr) override final; - - /// Implementation of IDeviceContext::SetVertexBuffers() in Direct3D12 backend. - virtual void SetVertexBuffers(Uint32 StartSlot, - Uint32 NumBuffersSet, - IBuffer** ppBuffers, - Uint32* pOffsets, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - SET_VERTEX_BUFFERS_FLAGS Flags) override final; - - /// Implementation of IDeviceContext::InvalidateState() in Direct3D12 backend. - virtual void InvalidateState() override final; - - /// Implementation of IDeviceContext::SetIndexBuffer() in Direct3D12 backend. - virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::SetViewports() in Direct3D12 backend. - virtual void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight) override final; - - /// Implementation of IDeviceContext::SetScissorRects() in Direct3D12 backend. - virtual void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight) override final; - - /// Implementation of IDeviceContext::SetRenderTargets() in Direct3D12 backend. - virtual void SetRenderTargets(Uint32 NumRenderTargets, - ITextureView* ppRenderTargets[], - ITextureView* pDepthStencil, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - // clang-format off - /// Implementation of IDeviceContext::Draw() in Direct3D12 backend. - virtual void Draw (const DrawAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DrawIndexed() in Direct3D12 backend. - virtual void DrawIndexed (const DrawIndexedAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DrawIndirect() in Direct3D12 backend. - virtual void DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - /// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D12 backend. - virtual void DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - - - /// Implementation of IDeviceContext::DispatchCompute() in Direct3D12 backend. - virtual void DispatchCompute (const DispatchComputeAttribs& Attribs) override final; - /// Implementation of IDeviceContext::DispatchComputeIndirect() in Direct3D12 backend. - virtual void DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; - // clang-format on - - /// Implementation of IDeviceContext::ClearDepthStencil() in Direct3D12 backend. - virtual void ClearDepthStencil(ITextureView* pView, - CLEAR_DEPTH_STENCIL_FLAGS ClearFlags, - float fDepth, - Uint8 Stencil, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::ClearRenderTarget() in Direct3D12 backend. - virtual void ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::UpdateBuffer() in Direct3D12 backend. - virtual void UpdateBuffer(IBuffer* pBuffer, - Uint32 Offset, - Uint32 Size, - const void* pData, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - - /// Implementation of IDeviceContext::CopyBuffer() in Direct3D12 backend. - virtual void CopyBuffer(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - IBuffer* pDstBuffer, - Uint32 DstOffset, - Uint32 Size, - RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override final; - - /// Implementation of IDeviceContext::MapBuffer() in Direct3D12 backend. - virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override final; - - /// Implementation of IDeviceContext::UnmapBuffer() in Direct3D12 backend. - virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override final; - - /// Implementation of IDeviceContext::UpdateTexture() in Direct3D12 backend. - virtual void UpdateTexture(ITexture* pTexture, - Uint32 MipLevel, - Uint32 Slice, - const Box& DstBox, - const TextureSubResData& SubresData, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) override final; - - /// Implementation of IDeviceContext::CopyTexture() in Direct3D12 backend. - virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override final; - - /// Implementation of IDeviceContext::MapTextureSubresource() in Direct3D12 backend. - virtual void MapTextureSubresource(ITexture* pTexture, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - MAP_FLAGS MapFlags, - const Box* pMapRegion, - MappedTextureSubresource& MappedData) override final; - - /// Implementation of IDeviceContext::UnmapTextureSubresource() in Direct3D12 backend. - virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override final; - - /// Implementation of IDeviceContext::FinishFrame() in Direct3D12 backend. - virtual void FinishFrame() override final; - - /// Implementation of IDeviceContext::TransitionResourceStates() in Direct3D12 backend. - virtual void TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers) override final; - - /// Implementation of IDeviceContext::ResolveTextureSubresource() in Direct3D12 backend. - virtual void ResolveTextureSubresource(ITexture* pSrcTexture, - ITexture* pDstTexture, - const ResolveTextureSubresourceAttribs& ResolveAttribs) override final; - - /// Implementation of IDeviceContext::FinishCommandList() in Direct3D12 backend. - virtual void FinishCommandList(class ICommandList** ppCommandList) override final; - - /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D12 backend. - virtual void ExecuteCommandList(class ICommandList* pCommandList) override final; - - /// Implementation of IDeviceContext::SignalFence() in Direct3D12 backend. - virtual void SignalFence(IFence* pFence, Uint64 Value) override final; - - /// Implementation of IDeviceContext::WaitForFence() in Direct3D12 backend. - virtual void WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext) override final; - - /// Implementation of IDeviceContext::WaitForIdle() in Direct3D12 backend. - virtual void WaitForIdle() override final; - - /// Implementation of IDeviceContext::BeginQuery() in Direct3D12 backend. - virtual void BeginQuery(IQuery* pQuery) override final; - - /// Implementation of IDeviceContext::EndQuery() in Direct3D12 backend. - virtual void EndQuery(IQuery* pQuery) override final; - - /// Implementation of IDeviceContext::Flush() in Direct3D12 backend. - virtual void Flush() override final; - - /// Implementation of IDeviceContext::TransitionTextureState() in Direct3D12 backend. - virtual void TransitionTextureState(ITexture* pTexture, D3D12_RESOURCE_STATES State) override final; - - /// Implementation of IDeviceContext::TransitionBufferState() in Direct3D12 backend. - virtual void TransitionBufferState(IBuffer* pBuffer, D3D12_RESOURCE_STATES State) override final; - - /// Implementation of IDeviceContextD3D12::ID3D12GraphicsCommandList() in Direct3D12 backend. - virtual ID3D12GraphicsCommandList* GetD3D12CommandList() override final; - - ///// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) - //static constexpr int NumShaderTypes = 6; - - void UpdateBufferRegion(class BufferD3D12Impl* pBuffD3D12, - D3D12DynamicAllocation& Allocation, - Uint64 DstOffset, - Uint64 NumBytes, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode); - - void CopyTextureRegion(class TextureD3D12Impl* pSrcTexture, - Uint32 SrcSubResIndex, - const D3D12_BOX* pD3D12SrcBox, - RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode, - class TextureD3D12Impl* pDstTexture, - Uint32 DstSubResIndex, - Uint32 DstX, - Uint32 DstY, - Uint32 DstZ, - RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode); - - void CopyTextureRegion(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - Uint32 SrcStride, - Uint32 SrcDepthStride, - class TextureD3D12Impl& TextureD3D12, - Uint32 DstSubResIndex, - const Box& DstBox, - RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode, - RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); - void CopyTextureRegion(ID3D12Resource* pd3d12Buffer, - Uint32 SrcOffset, - Uint32 SrcStride, - Uint32 SrcDepthStride, - Uint32 BufferSize, - class TextureD3D12Impl& TextureD3D12, - Uint32 DstSubResIndex, - const Box& DstBox, - RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); - - void UpdateTextureRegion(const void* pSrcData, - Uint32 SrcStride, - Uint32 SrcDepthStride, - class TextureD3D12Impl& TextureD3D12, - Uint32 DstSubResIndex, - const Box& DstBox, - RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); - - virtual void GenerateMips(ITextureView* pTexView) override final; - - D3D12DynamicAllocation AllocateDynamicSpace(size_t NumBytes, size_t Alignment); - - Uint32 GetContextId() const { return m_ContextId; } - - size_t GetNumCommandsInCtx() const { return m_State.NumCommands; } - - Int64 GetCurrentFrameNumber() const { return m_ContextFrameNumber; } - -private: - void CommitD3D12IndexBuffer(GraphicsContext& GraphCtx, VALUE_TYPE IndexType); - void CommitD3D12VertexBuffers(class GraphicsContext& GraphCtx); - void CommitRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode); - void CommitViewports(); - void CommitScissorRects(class GraphicsContext& GraphCtx, bool ScissorEnable); - void Flush(bool RequestNewCmdCtx); - - __forceinline void RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl); - - __forceinline void TransitionOrVerifyBufferState(CommandContext& CmdCtx, - BufferD3D12Impl& Buffer, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - RESOURCE_STATE RequiredState, - const char* OperationName); - __forceinline void TransitionOrVerifyTextureState(CommandContext& CmdCtx, - TextureD3D12Impl& Texture, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - RESOURCE_STATE RequiredState, - const char* OperationName); - - __forceinline void PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags); - - __forceinline void PrepareForIndexedDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags, VALUE_TYPE IndexType); - - __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx); - - __forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx, - IBuffer* pAttribsBuffer, - RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, - ID3D12Resource*& pd3d12ArgsBuff, - Uint64& BuffDataStartByteOffset); - - struct TextureUploadSpace - { - D3D12DynamicAllocation Allocation; - Uint32 AlignedOffset = 0; - Uint32 Stride = 0; - Uint32 DepthStride = 0; - Uint32 RowSize = 0; - Uint32 RowCount = 0; - Box Region; - }; - TextureUploadSpace AllocateTextureUploadSpace(TEXTURE_FORMAT TexFmt, - const Box& Region); - - - friend class SwapChainD3D12Impl; - inline class CommandContext& GetCmdContext() - { - // Make sure that the number of commands in the context is at least one, - // so that the context cannot be disposed by Flush() - m_State.NumCommands = m_State.NumCommands != 0 ? m_State.NumCommands : 1; - return *m_CurrCmdCtx; - } - std::unique_ptr> m_CurrCmdCtx; - - struct State - { - size_t NumCommands = 0; - - CComPtr CommittedD3D12IndexBuffer; - VALUE_TYPE CommittedIBFormat = VT_UNDEFINED; - Uint64 CommittedD3D12IndexDataStartOffset = 0; - - // Indicates if currently committed D3D12 vertex buffers are up to date - bool bCommittedD3D12VBsUpToDate = false; - - // Indicates if currently committed D3D11 index buffer is up to date - bool bCommittedD3D12IBUpToDate = false; - - // Indicates if root views have been committed since the time SRB - // has been committed. - bool bRootViewsCommitted = false; - - class ShaderResourceCacheD3D12* pCommittedResourceCache = nullptr; - } m_State; - - CComPtr m_pDrawIndirectSignature; - CComPtr m_pDrawIndexedIndirectSignature; - CComPtr m_pDispatchIndirectSignature; - - D3D12DynamicHeap m_DynamicHeap; - - // Every context must use its own allocator that maintains individual list of retired descriptor heaps to - // avoid interference with other command contexts - // The allocations in heaps are discarded at the end of the frame. - DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2]; - - FixedBlockMemoryAllocator m_CmdListAllocator; - - std::vector>> m_PendingFences; - - struct MappedTextureKey - { - TextureD3D12Impl* const Texture; - UINT const Subresource; - - bool operator==(const MappedTextureKey& rhs) const - { - return Texture == rhs.Texture && Subresource == rhs.Subresource; - } - struct Hasher - { - size_t operator()(const MappedTextureKey& Key) const - { - return ComputeHash(Key.Texture, Key.Subresource); - } - }; - }; - std::unordered_map m_MappedTextures; - - Int32 m_ActiveQueriesCounter = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp new file mode 100644 index 00000000..6971d8a8 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -0,0 +1,404 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::DeviceContextD3D12Impl class + +#include + +#include "DeviceContextD3D12.h" +#include "DeviceContextNextGenBase.h" +#include "BufferD3D12Impl.hpp" +#include "TextureD3D12Impl.hpp" +#include "QueryD3D12Impl.hpp" +#include "PipelineStateD3D12Impl.hpp" +#include "D3D12DynamicHeap.hpp" + +namespace Diligent +{ + +class RenderDeviceD3D12Impl; + +struct DeviceContextD3D12ImplTraits +{ + using BufferType = BufferD3D12Impl; + using TextureType = TextureD3D12Impl; + using PipelineStateType = PipelineStateD3D12Impl; + using DeviceType = RenderDeviceD3D12Impl; + using ICommandQueueType = ICommandQueueD3D12; + using QueryType = QueryD3D12Impl; +}; + +/// Device context implementation in Direct3D12 backend. +class DeviceContextD3D12Impl final : public DeviceContextNextGenBase +{ +public: + using TDeviceContextBase = DeviceContextNextGenBase; + + DeviceContextD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + bool bIsDeferred, + const EngineD3D12CreateInfo& EngineCI, + Uint32 ContextId, + Uint32 CommandQueueId); + ~DeviceContextD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IDeviceContext::SetPipelineState() in Direct3D12 backend. + virtual void SetPipelineState(IPipelineState* pPipelineState) override final; + + /// Implementation of IDeviceContext::TransitionShaderResources() in Direct3D12 backend. + virtual void TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) override final; + + /// Implementation of IDeviceContext::CommitShaderResources() in Direct3D12 backend. + virtual void CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::SetStencilRef() in Direct3D12 backend. + virtual void SetStencilRef(Uint32 StencilRef) override final; + + /// Implementation of IDeviceContext::SetBlendFactors() in Direct3D12 backend. + virtual void SetBlendFactors(const float* pBlendFactors = nullptr) override final; + + /// Implementation of IDeviceContext::SetVertexBuffers() in Direct3D12 backend. + virtual void SetVertexBuffers(Uint32 StartSlot, + Uint32 NumBuffersSet, + IBuffer** ppBuffers, + Uint32* pOffsets, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + SET_VERTEX_BUFFERS_FLAGS Flags) override final; + + /// Implementation of IDeviceContext::InvalidateState() in Direct3D12 backend. + virtual void InvalidateState() override final; + + /// Implementation of IDeviceContext::SetIndexBuffer() in Direct3D12 backend. + virtual void SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::SetViewports() in Direct3D12 backend. + virtual void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight) override final; + + /// Implementation of IDeviceContext::SetScissorRects() in Direct3D12 backend. + virtual void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight) override final; + + /// Implementation of IDeviceContext::SetRenderTargets() in Direct3D12 backend. + virtual void SetRenderTargets(Uint32 NumRenderTargets, + ITextureView* ppRenderTargets[], + ITextureView* pDepthStencil, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + // clang-format off + /// Implementation of IDeviceContext::Draw() in Direct3D12 backend. + virtual void Draw (const DrawAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawIndexed() in Direct3D12 backend. + virtual void DrawIndexed (const DrawIndexedAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawIndirect() in Direct3D12 backend. + virtual void DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D12 backend. + virtual void DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + + + /// Implementation of IDeviceContext::DispatchCompute() in Direct3D12 backend. + virtual void DispatchCompute (const DispatchComputeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DispatchComputeIndirect() in Direct3D12 backend. + virtual void DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + // clang-format on + + /// Implementation of IDeviceContext::ClearDepthStencil() in Direct3D12 backend. + virtual void ClearDepthStencil(ITextureView* pView, + CLEAR_DEPTH_STENCIL_FLAGS ClearFlags, + float fDepth, + Uint8 Stencil, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::ClearRenderTarget() in Direct3D12 backend. + virtual void ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::UpdateBuffer() in Direct3D12 backend. + virtual void UpdateBuffer(IBuffer* pBuffer, + Uint32 Offset, + Uint32 Size, + const void* pData, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; + + /// Implementation of IDeviceContext::CopyBuffer() in Direct3D12 backend. + virtual void CopyBuffer(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + IBuffer* pDstBuffer, + Uint32 DstOffset, + Uint32 Size, + RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) override final; + + /// Implementation of IDeviceContext::MapBuffer() in Direct3D12 backend. + virtual void MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) override final; + + /// Implementation of IDeviceContext::UnmapBuffer() in Direct3D12 backend. + virtual void UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) override final; + + /// Implementation of IDeviceContext::UpdateTexture() in Direct3D12 backend. + virtual void UpdateTexture(ITexture* pTexture, + Uint32 MipLevel, + Uint32 Slice, + const Box& DstBox, + const TextureSubResData& SubresData, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) override final; + + /// Implementation of IDeviceContext::CopyTexture() in Direct3D12 backend. + virtual void CopyTexture(const CopyTextureAttribs& CopyAttribs) override final; + + /// Implementation of IDeviceContext::MapTextureSubresource() in Direct3D12 backend. + virtual void MapTextureSubresource(ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) override final; + + /// Implementation of IDeviceContext::UnmapTextureSubresource() in Direct3D12 backend. + virtual void UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) override final; + + /// Implementation of IDeviceContext::FinishFrame() in Direct3D12 backend. + virtual void FinishFrame() override final; + + /// Implementation of IDeviceContext::TransitionResourceStates() in Direct3D12 backend. + virtual void TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers) override final; + + /// Implementation of IDeviceContext::ResolveTextureSubresource() in Direct3D12 backend. + virtual void ResolveTextureSubresource(ITexture* pSrcTexture, + ITexture* pDstTexture, + const ResolveTextureSubresourceAttribs& ResolveAttribs) override final; + + /// Implementation of IDeviceContext::FinishCommandList() in Direct3D12 backend. + virtual void FinishCommandList(class ICommandList** ppCommandList) override final; + + /// Implementation of IDeviceContext::ExecuteCommandList() in Direct3D12 backend. + virtual void ExecuteCommandList(class ICommandList* pCommandList) override final; + + /// Implementation of IDeviceContext::SignalFence() in Direct3D12 backend. + virtual void SignalFence(IFence* pFence, Uint64 Value) override final; + + /// Implementation of IDeviceContext::WaitForFence() in Direct3D12 backend. + virtual void WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext) override final; + + /// Implementation of IDeviceContext::WaitForIdle() in Direct3D12 backend. + virtual void WaitForIdle() override final; + + /// Implementation of IDeviceContext::BeginQuery() in Direct3D12 backend. + virtual void BeginQuery(IQuery* pQuery) override final; + + /// Implementation of IDeviceContext::EndQuery() in Direct3D12 backend. + virtual void EndQuery(IQuery* pQuery) override final; + + /// Implementation of IDeviceContext::Flush() in Direct3D12 backend. + virtual void Flush() override final; + + /// Implementation of IDeviceContext::TransitionTextureState() in Direct3D12 backend. + virtual void TransitionTextureState(ITexture* pTexture, D3D12_RESOURCE_STATES State) override final; + + /// Implementation of IDeviceContext::TransitionBufferState() in Direct3D12 backend. + virtual void TransitionBufferState(IBuffer* pBuffer, D3D12_RESOURCE_STATES State) override final; + + /// Implementation of IDeviceContextD3D12::ID3D12GraphicsCommandList() in Direct3D12 backend. + virtual ID3D12GraphicsCommandList* GetD3D12CommandList() override final; + + ///// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) + //static constexpr int NumShaderTypes = 6; + + void UpdateBufferRegion(class BufferD3D12Impl* pBuffD3D12, + D3D12DynamicAllocation& Allocation, + Uint64 DstOffset, + Uint64 NumBytes, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode); + + void CopyTextureRegion(class TextureD3D12Impl* pSrcTexture, + Uint32 SrcSubResIndex, + const D3D12_BOX* pD3D12SrcBox, + RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode, + class TextureD3D12Impl* pDstTexture, + Uint32 DstSubResIndex, + Uint32 DstX, + Uint32 DstY, + Uint32 DstZ, + RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode); + + void CopyTextureRegion(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + class TextureD3D12Impl& TextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox, + RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); + void CopyTextureRegion(ID3D12Resource* pd3d12Buffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + Uint32 BufferSize, + class TextureD3D12Impl& TextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); + + void UpdateTextureRegion(const void* pSrcData, + Uint32 SrcStride, + Uint32 SrcDepthStride, + class TextureD3D12Impl& TextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode); + + virtual void GenerateMips(ITextureView* pTexView) override final; + + D3D12DynamicAllocation AllocateDynamicSpace(size_t NumBytes, size_t Alignment); + + Uint32 GetContextId() const { return m_ContextId; } + + size_t GetNumCommandsInCtx() const { return m_State.NumCommands; } + + Int64 GetCurrentFrameNumber() const { return m_ContextFrameNumber; } + +private: + void CommitD3D12IndexBuffer(GraphicsContext& GraphCtx, VALUE_TYPE IndexType); + void CommitD3D12VertexBuffers(class GraphicsContext& GraphCtx); + void CommitRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode); + void CommitViewports(); + void CommitScissorRects(class GraphicsContext& GraphCtx, bool ScissorEnable); + void Flush(bool RequestNewCmdCtx); + + __forceinline void RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl); + + __forceinline void TransitionOrVerifyBufferState(CommandContext& CmdCtx, + BufferD3D12Impl& Buffer, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName); + __forceinline void TransitionOrVerifyTextureState(CommandContext& CmdCtx, + TextureD3D12Impl& Texture, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName); + + __forceinline void PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags); + + __forceinline void PrepareForIndexedDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags, VALUE_TYPE IndexType); + + __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx); + + __forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx, + IBuffer* pAttribsBuffer, + RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, + ID3D12Resource*& pd3d12ArgsBuff, + Uint64& BuffDataStartByteOffset); + + struct TextureUploadSpace + { + D3D12DynamicAllocation Allocation; + Uint32 AlignedOffset = 0; + Uint32 Stride = 0; + Uint32 DepthStride = 0; + Uint32 RowSize = 0; + Uint32 RowCount = 0; + Box Region; + }; + TextureUploadSpace AllocateTextureUploadSpace(TEXTURE_FORMAT TexFmt, + const Box& Region); + + + friend class SwapChainD3D12Impl; + inline class CommandContext& GetCmdContext() + { + // Make sure that the number of commands in the context is at least one, + // so that the context cannot be disposed by Flush() + m_State.NumCommands = m_State.NumCommands != 0 ? m_State.NumCommands : 1; + return *m_CurrCmdCtx; + } + std::unique_ptr> m_CurrCmdCtx; + + struct State + { + size_t NumCommands = 0; + + CComPtr CommittedD3D12IndexBuffer; + VALUE_TYPE CommittedIBFormat = VT_UNDEFINED; + Uint64 CommittedD3D12IndexDataStartOffset = 0; + + // Indicates if currently committed D3D12 vertex buffers are up to date + bool bCommittedD3D12VBsUpToDate = false; + + // Indicates if currently committed D3D11 index buffer is up to date + bool bCommittedD3D12IBUpToDate = false; + + // Indicates if root views have been committed since the time SRB + // has been committed. + bool bRootViewsCommitted = false; + + class ShaderResourceCacheD3D12* pCommittedResourceCache = nullptr; + } m_State; + + CComPtr m_pDrawIndirectSignature; + CComPtr m_pDrawIndexedIndirectSignature; + CComPtr m_pDispatchIndirectSignature; + + D3D12DynamicHeap m_DynamicHeap; + + // Every context must use its own allocator that maintains individual list of retired descriptor heaps to + // avoid interference with other command contexts + // The allocations in heaps are discarded at the end of the frame. + DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2]; + + FixedBlockMemoryAllocator m_CmdListAllocator; + + std::vector>> m_PendingFences; + + struct MappedTextureKey + { + TextureD3D12Impl* const Texture; + UINT const Subresource; + + bool operator==(const MappedTextureKey& rhs) const + { + return Texture == rhs.Texture && Subresource == rhs.Subresource; + } + struct Hasher + { + size_t operator()(const MappedTextureKey& Key) const + { + return ComputeHash(Key.Texture, Key.Subresource); + } + }; + }; + std::unordered_map m_MappedTextures; + + Int32 m_ActiveQueriesCounter = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.h deleted file mode 100644 index cacc1e11..00000000 --- a/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::FenceD3D12Impl class - -#include "FenceD3D12.h" -#include "RenderDeviceD3D12.h" -#include "FenceBase.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Fence implementation in Direct3D12 backend. -class FenceD3D12Impl final : public FenceBase -{ -public: - using TFenceBase = FenceBase; - - FenceD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - const FenceDesc& Desc); - ~FenceD3D12Impl(); - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_FenceD3D12, TFenceBase); - - /// Implementation of IFence::GetCompletedValue() in Direct3D12 backend. - virtual Uint64 GetCompletedValue() override final; - - /// Implementation of IFence::GetCompletedValue() in Direct3D12 backend. - virtual void Reset(Uint64 Value) override final; - - /// Implementation of IFenceD3D12::GetD3D12Fence(). - ID3D12Fence* GetD3D12Fence() override final { return m_pd3d12Fence; } - - /// Implementation of IFenceD3D12::WaitForCompletion(). - virtual void WaitForCompletion(Uint64 Value) override final; - -private: - CComPtr m_pd3d12Fence; ///< D3D12 Fence object -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.hpp new file mode 100644 index 00000000..1549e584 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/FenceD3D12Impl.hpp @@ -0,0 +1,72 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::FenceD3D12Impl class + +#include "FenceD3D12.h" +#include "RenderDeviceD3D12.h" +#include "FenceBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Fence implementation in Direct3D12 backend. +class FenceD3D12Impl final : public FenceBase +{ +public: + using TFenceBase = FenceBase; + + FenceD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + const FenceDesc& Desc); + ~FenceD3D12Impl(); + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_FenceD3D12, TFenceBase); + + /// Implementation of IFence::GetCompletedValue() in Direct3D12 backend. + virtual Uint64 GetCompletedValue() override final; + + /// Implementation of IFence::GetCompletedValue() in Direct3D12 backend. + virtual void Reset(Uint64 Value) override final; + + /// Implementation of IFenceD3D12::GetD3D12Fence(). + ID3D12Fence* GetD3D12Fence() override final { return m_pd3d12Fence; } + + /// Implementation of IFenceD3D12::WaitForCompletion(). + virtual void WaitForCompletion(Uint64 Value) override final; + +private: + CComPtr m_pd3d12Fence; ///< D3D12 Fence object +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/GenerateMips.h b/Graphics/GraphicsEngineD3D12/include/GenerateMips.h deleted file mode 100644 index a62f9665..00000000 --- a/Graphics/GraphicsEngineD3D12/include/GenerateMips.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019-2020 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. - */ - - -// The source code in this file is derived from ColorBuffer.h and GraphicsCore.h developed by Minigraph -// Original source files header: - -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -// Developed by Minigraph -// -// Author: James Stanard -// - - -#pragma once - -/// \file -/// Implementation of mipmap generation routines - - -namespace Diligent -{ -class GenerateMipsHelper -{ -public: - GenerateMipsHelper(ID3D12Device* pd3d12Device); - - void GenerateMips(ID3D12Device* pd3d12Device, class TextureViewD3D12Impl* pTexView, class CommandContext& Ctx) const; - -private: - CComPtr m_pGenerateMipsRS; - CComPtr m_pGenerateMipsLinearPSO[4]; - CComPtr m_pGenerateMipsGammaPSO[4]; -}; -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/GenerateMips.hpp b/Graphics/GraphicsEngineD3D12/include/GenerateMips.hpp new file mode 100644 index 00000000..a62f9665 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/GenerateMips.hpp @@ -0,0 +1,66 @@ +/* + * Copyright 2019-2020 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. + */ + + +// The source code in this file is derived from ColorBuffer.h and GraphicsCore.h developed by Minigraph +// Original source files header: + +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +// Developed by Minigraph +// +// Author: James Stanard +// + + +#pragma once + +/// \file +/// Implementation of mipmap generation routines + + +namespace Diligent +{ +class GenerateMipsHelper +{ +public: + GenerateMipsHelper(ID3D12Device* pd3d12Device); + + void GenerateMips(ID3D12Device* pd3d12Device, class TextureViewD3D12Impl* pTexView, class CommandContext& Ctx) const; + +private: + CComPtr m_pGenerateMipsRS; + CComPtr m_pGenerateMipsLinearPSO[4]; + CComPtr m_pGenerateMipsGammaPSO[4]; +}; +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h deleted file mode 100644 index d23d54e1..00000000 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::PipelineStateD3D12Impl class - -#include "RenderDeviceD3D12.h" -#include "PipelineStateD3D12.h" -#include "PipelineStateBase.h" -#include "RootSignature.h" -#include "ShaderResourceLayoutD3D12.h" -#include "SRBMemoryAllocator.hpp" -#include "RenderDeviceD3D12Impl.h" -#include "ShaderVariableD3D12.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Pipeline state object implementation in Direct3D12 backend. -class PipelineStateD3D12Impl final : public PipelineStateBase -{ -public: - using TPipelineStateBase = PipelineStateBase; - - PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const PipelineStateDesc& PipelineDesc); - ~PipelineStateD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IPipelineState::BindStaticResources() in Direct3D12 backend. - virtual void BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final; - - /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D12 backend. - virtual Uint32 GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; - - /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D12 backend. - virtual IShaderResourceVariable* GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final; - - /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D12 backend. - virtual IShaderResourceVariable* GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; - - /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D12 backend. - virtual void CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final; - - /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D12 backend. - virtual bool IsCompatibleWith(const IPipelineState* pPSO) const override final; - - /// Implementation of IPipelineStateD3D12::GetD3D12PipelineState(). - virtual ID3D12PipelineState* GetD3D12PipelineState() const override final { return m_pd3d12PSO; } - - /// Implementation of IPipelineStateD3D12::GetD3D12RootSignature(). - virtual ID3D12RootSignature* GetD3D12RootSignature() const override final { return m_RootSig.GetD3D12RootSignature(); } - - struct CommitAndTransitionResourcesAttribs - { - Uint32 CtxId = 0; - IShaderResourceBinding* pShaderResourceBinding = nullptr; - bool CommitResources = false; - bool TransitionResources = false; - bool ValidateStates = false; - }; - ShaderResourceCacheD3D12* CommitAndTransitionShaderResources(class DeviceContextD3D12Impl* pDeviceCtx, - class CommandContext& CmdCtx, - CommitAndTransitionResourcesAttribs& Attrib) const; - - const RootSignature& GetRootSignature() const { return m_RootSig; } - - const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return m_pShaderResourceLayouts[ShaderInd]; - } - - const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return m_pShaderResourceLayouts[m_NumShaders + ShaderInd]; - } - - ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return m_pStaticResourceCaches[ShaderInd]; - } - - bool ContainsShaderResources() const; - - SRBMemoryAllocator& GetSRBMemoryAllocator() - { - return m_SRBMemAllocator; - } - -private: - CComPtr m_pd3d12PSO; - RootSignature m_RootSig; - - // Must be defined before default SRB - SRBMemoryAllocator m_SRBMemAllocator; - - ShaderResourceLayoutD3D12* m_pShaderResourceLayouts = nullptr; - ShaderResourceCacheD3D12* m_pStaticResourceCaches = nullptr; - ShaderVariableManagerD3D12* m_pStaticVarManagers = nullptr; - // Resource layout index in m_ResourceLayouts[] array for every shader stage - Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp new file mode 100644 index 00000000..9431d2f4 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -0,0 +1,135 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::PipelineStateD3D12Impl class + +#include "RenderDeviceD3D12.h" +#include "PipelineStateD3D12.h" +#include "PipelineStateBase.hpp" +#include "RootSignature.hpp" +#include "ShaderResourceLayoutD3D12.hpp" +#include "SRBMemoryAllocator.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "ShaderVariableD3D12.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Pipeline state object implementation in Direct3D12 backend. +class PipelineStateD3D12Impl final : public PipelineStateBase +{ +public: + using TPipelineStateBase = PipelineStateBase; + + PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const PipelineStateDesc& PipelineDesc); + ~PipelineStateD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IPipelineState::BindStaticResources() in Direct3D12 backend. + virtual void BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final; + + /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D12 backend. + virtual Uint32 GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; + + /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D12 backend. + virtual IShaderResourceVariable* GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final; + + /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D12 backend. + virtual IShaderResourceVariable* GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; + + /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D12 backend. + virtual void CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final; + + /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D12 backend. + virtual bool IsCompatibleWith(const IPipelineState* pPSO) const override final; + + /// Implementation of IPipelineStateD3D12::GetD3D12PipelineState(). + virtual ID3D12PipelineState* GetD3D12PipelineState() const override final { return m_pd3d12PSO; } + + /// Implementation of IPipelineStateD3D12::GetD3D12RootSignature(). + virtual ID3D12RootSignature* GetD3D12RootSignature() const override final { return m_RootSig.GetD3D12RootSignature(); } + + struct CommitAndTransitionResourcesAttribs + { + Uint32 CtxId = 0; + IShaderResourceBinding* pShaderResourceBinding = nullptr; + bool CommitResources = false; + bool TransitionResources = false; + bool ValidateStates = false; + }; + ShaderResourceCacheD3D12* CommitAndTransitionShaderResources(class DeviceContextD3D12Impl* pDeviceCtx, + class CommandContext& CmdCtx, + CommitAndTransitionResourcesAttribs& Attrib) const; + + const RootSignature& GetRootSignature() const { return m_RootSig; } + + const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_pShaderResourceLayouts[ShaderInd]; + } + + const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_pShaderResourceLayouts[m_NumShaders + ShaderInd]; + } + + ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_pStaticResourceCaches[ShaderInd]; + } + + bool ContainsShaderResources() const; + + SRBMemoryAllocator& GetSRBMemoryAllocator() + { + return m_SRBMemAllocator; + } + +private: + CComPtr m_pd3d12PSO; + RootSignature m_RootSig; + + // Must be defined before default SRB + SRBMemoryAllocator m_SRBMemAllocator; + + ShaderResourceLayoutD3D12* m_pShaderResourceLayouts = nullptr; + ShaderResourceCacheD3D12* m_pStaticResourceCaches = nullptr; + ShaderVariableManagerD3D12* m_pStaticVarManagers = nullptr; + // Resource layout index in m_ResourceLayouts[] array for every shader stage + Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.h deleted file mode 100644 index 0c47565e..00000000 --- a/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::QueryD3D12Impl class - -#include "QueryD3D12.h" -#include "QueryBase.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries - -/// Query implementation in Direct3D12 backend. -class QueryD3D12Impl final : public QueryBase -{ -public: - using TQueryBase = QueryBase; - - QueryD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - const QueryDesc& Desc); - ~QueryD3D12Impl(); - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_QueryD3D12, TQueryBase); - - /// Implementation of IQuery::GetData(). - virtual bool GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) override final; - - /// Implementation of IQueryD3D12::GetD3D12QueryHeap(). - virtual ID3D12QueryHeap* GetD3D12QueryHeap() override final - { - return m_pDevice->GetQueryManager().GetQueryHeap(m_Desc.Type); - } - - /// Implementation of IQueryD3D12::GetQueryHeapIndex(). - virtual Uint32 GetQueryHeapIndex() const override final - { - return m_QueryHeapIndex; - } - - bool OnEndQuery(IDeviceContext* pContext); - -private: - Uint32 m_QueryHeapIndex = static_cast(-1); - Uint64 m_QueryEndFenceValue = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.hpp new file mode 100644 index 00000000..129e0307 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/QueryD3D12Impl.hpp @@ -0,0 +1,79 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::QueryD3D12Impl class + +#include "QueryD3D12.h" +#include "QueryBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries + +/// Query implementation in Direct3D12 backend. +class QueryD3D12Impl final : public QueryBase +{ +public: + using TQueryBase = QueryBase; + + QueryD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + const QueryDesc& Desc); + ~QueryD3D12Impl(); + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_QueryD3D12, TQueryBase); + + /// Implementation of IQuery::GetData(). + virtual bool GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) override final; + + /// Implementation of IQueryD3D12::GetD3D12QueryHeap(). + virtual ID3D12QueryHeap* GetD3D12QueryHeap() override final + { + return m_pDevice->GetQueryManager().GetQueryHeap(m_Desc.Type); + } + + /// Implementation of IQueryD3D12::GetQueryHeapIndex(). + virtual Uint32 GetQueryHeapIndex() const override final + { + return m_QueryHeapIndex; + } + + bool OnEndQuery(IDeviceContext* pContext); + +private: + Uint32 m_QueryHeapIndex = static_cast(-1); + Uint64 m_QueryEndFenceValue = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h b/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h deleted file mode 100644 index 13337696..00000000 --- a/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include -#include -#include -#include - -#include "Query.h" - -namespace Diligent -{ - -class CommandContext; - -// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries - -class QueryManagerD3D12 -{ -public: - QueryManagerD3D12(ID3D12Device* pd3d12Device, - const Uint32 QueryHeapSizes[]); - ~QueryManagerD3D12(); - - // clang-format off - QueryManagerD3D12 (const QueryManagerD3D12&) = delete; - QueryManagerD3D12 ( QueryManagerD3D12&&) = delete; - QueryManagerD3D12& operator = (const QueryManagerD3D12&) = delete; - QueryManagerD3D12& operator = ( QueryManagerD3D12&&) = delete; - // clang-format on - - static constexpr Uint32 InvalidIndex = static_cast(-1); - - Uint32 AllocateQuery(QUERY_TYPE Type); - void ReleaseQuery(QUERY_TYPE Type, Uint32 Index); - - ID3D12QueryHeap* GetQueryHeap(QUERY_TYPE Type) - { - return m_Heaps[Type].pd3d12QueryHeap; - } - - void BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); - void EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); - void ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const; - -private: - struct QueryHeapInfo - { - CComPtr pd3d12QueryHeap; - std::deque AvailableQueries; - std::vector ResolveBufferOffsets; - - Uint32 HeapSize = 0; - Uint32 MaxAllocatedQueries = 0; - }; - - std::mutex m_HeapMutex; - std::array m_Heaps; - - // Readback buffer that will contain the query data. - CComPtr m_pd3d12ResolveBuffer; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.hpp new file mode 100644 index 00000000..13337696 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.hpp @@ -0,0 +1,90 @@ +/* + * Copyright 2019-2020 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 + +#include +#include +#include +#include + +#include "Query.h" + +namespace Diligent +{ + +class CommandContext; + +// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries + +class QueryManagerD3D12 +{ +public: + QueryManagerD3D12(ID3D12Device* pd3d12Device, + const Uint32 QueryHeapSizes[]); + ~QueryManagerD3D12(); + + // clang-format off + QueryManagerD3D12 (const QueryManagerD3D12&) = delete; + QueryManagerD3D12 ( QueryManagerD3D12&&) = delete; + QueryManagerD3D12& operator = (const QueryManagerD3D12&) = delete; + QueryManagerD3D12& operator = ( QueryManagerD3D12&&) = delete; + // clang-format on + + static constexpr Uint32 InvalidIndex = static_cast(-1); + + Uint32 AllocateQuery(QUERY_TYPE Type); + void ReleaseQuery(QUERY_TYPE Type, Uint32 Index); + + ID3D12QueryHeap* GetQueryHeap(QUERY_TYPE Type) + { + return m_Heaps[Type].pd3d12QueryHeap; + } + + void BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); + void EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); + void ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const; + +private: + struct QueryHeapInfo + { + CComPtr pd3d12QueryHeap; + std::deque AvailableQueries; + std::vector ResolveBufferOffsets; + + Uint32 HeapSize = 0; + Uint32 MaxAllocatedQueries = 0; + }; + + std::mutex m_HeapMutex; + std::array m_Heaps; + + // Readback buffer that will contain the query data. + CComPtr m_pd3d12ResolveBuffer; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h deleted file mode 100644 index 922a4c22..00000000 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::RenderDeviceD3D12Impl class -#include "RenderDeviceD3D12.h" -#include "RenderDeviceD3DBase.h" -#include "RenderDeviceNextGenBase.h" -#include "DescriptorHeap.h" -#include "CommandListManager.h" -#include "CommandContext.h" -#include "D3D12DynamicHeap.h" -#include "Atomics.h" -#include "CommandQueueD3D12.h" -#include "GenerateMips.h" -#include "QueryManagerD3D12.h" - -namespace Diligent -{ - -/// Render device implementation in Direct3D12 backend. -class RenderDeviceD3D12Impl final : public RenderDeviceNextGenBase, ICommandQueueD3D12> -{ -public: - using TRenderDeviceBase = RenderDeviceNextGenBase, ICommandQueueD3D12>; - - RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - IEngineFactory* pEngineFactory, - const EngineD3D12CreateInfo& EngineCI, - ID3D12Device* pD3D12Device, - size_t CommandQueueCount, - ICommandQueueD3D12** ppCmdQueues); - ~RenderDeviceD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D12 backend. - virtual void CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState) override final; - - /// Implementation of IRenderDevice::CreateBuffer() in Direct3D12 backend. - virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer) override final; - - /// Implementation of IRenderDevice::CreateShader() in Direct3D12 backend. - virtual void CreateShader(const ShaderCreateInfo& ShaderCreateInfo, IShader** ppShader) override final; - - /// Implementation of IRenderDevice::CreateTexture() in Direct3D12 backend. - virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture) override final; - - void CreateTexture(const TextureDesc& TexDesc, ID3D12Resource* pd3d12Texture, RESOURCE_STATE InitialState, class TextureD3D12Impl** ppTexture); - - /// Implementation of IRenderDevice::CreateSampler() in Direct3D12 backend. - virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; - - /// Implementation of IRenderDevice::CreateFence() in Direct3D12 backend. - virtual void CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; - - /// Implementation of IRenderDevice::CreateQuery() in Direct3D12 backend. - virtual void CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) override final; - - /// Implementation of IRenderDeviceD3D12::GetD3D12Device(). - virtual ID3D12Device* GetD3D12Device() override final { return m_pd3d12Device; } - - /// Implementation of IRenderDeviceD3D12::CreateTextureFromD3DResource(). - virtual void CreateTextureFromD3DResource(ID3D12Resource* pd3d12Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; - - /// Implementation of IRenderDeviceD3D12::CreateBufferFromD3DResource(). - virtual void CreateBufferFromD3DResource(ID3D12Resource* pd3d12Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) override final; - - DescriptorHeapAllocation AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1); - DescriptorHeapAllocation AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1); - - /// Implementation of IRenderDevice::IdleGPU() in Direct3D12 backend. - virtual void IdleGPU() override final; - - using PooledCommandContext = std::unique_ptr>; - PooledCommandContext AllocateCommandContext(const Char* ID = ""); - - void CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx); - - Uint64 CloseAndExecuteCommandContext(Uint32 QueueIndex, - PooledCommandContext&& Ctx, - bool DiscardStaleObjects, - std::vector>>* pSignalFences); - - void SignalFences(Uint32 QueueIndex, std::vector>>& SignalFences); - - // Disposes an unused command context - void DisposeCommandContext(PooledCommandContext&& Ctx); - - void FlushStaleResources(Uint32 CmdQueueIndex); - - /// Implementation of IRenderDevice::() in Direct3D12 backend. - virtual void ReleaseStaleResources(bool ForceRelease = false) override final; - - D3D12DynamicMemoryManager& GetDynamicMemoryManager() { return m_DynamicMemoryManager; } - - GPUDescriptorHeap& GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE Type) - { - VERIFY_EXPR(Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - return m_GPUDescriptorHeaps[Type]; - } - - const GenerateMipsHelper& GetMipsGenerator() const { return m_MipsGenerator; } - QueryManagerD3D12& GetQueryManager() { return m_QueryMgr; } - - D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; - -private: - virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; - void FreeCommandContext(PooledCommandContext&& Ctx); - - CComPtr m_pd3d12Device; - - EngineD3D12CreateInfo m_EngineAttribs; - - CPUDescriptorHeap m_CPUDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; - GPUDescriptorHeap m_GPUDescriptorHeaps[2]; // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == 0 - // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER == 1 - - CommandListManager m_CmdListManager; - - std::mutex m_ContextPoolMutex; - std::vector> m_ContextPool; -#ifdef DEVELOPMENT - Atomics::AtomicLong m_AllocatedCtxCounter = 0; -#endif - - D3D12DynamicMemoryManager m_DynamicMemoryManager; - - // Note: mips generator must be released after the device has been idled - GenerateMipsHelper m_MipsGenerator; - - QueryManagerD3D12 m_QueryMgr; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp new file mode 100644 index 00000000..3c4746c8 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -0,0 +1,163 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::RenderDeviceD3D12Impl class +#include "RenderDeviceD3D12.h" +#include "RenderDeviceD3DBase.hpp" +#include "RenderDeviceNextGenBase.h" +#include "DescriptorHeap.hpp" +#include "CommandListManager.hpp" +#include "CommandContext.hpp" +#include "D3D12DynamicHeap.hpp" +#include "Atomics.h" +#include "CommandQueueD3D12.h" +#include "GenerateMips.hpp" +#include "QueryManagerD3D12.hpp" + +namespace Diligent +{ + +/// Render device implementation in Direct3D12 backend. +class RenderDeviceD3D12Impl final : public RenderDeviceNextGenBase, ICommandQueueD3D12> +{ +public: + using TRenderDeviceBase = RenderDeviceNextGenBase, ICommandQueueD3D12>; + + RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + IEngineFactory* pEngineFactory, + const EngineD3D12CreateInfo& EngineCI, + ID3D12Device* pD3D12Device, + size_t CommandQueueCount, + ICommandQueueD3D12** ppCmdQueues); + ~RenderDeviceD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D12 backend. + virtual void CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateBuffer() in Direct3D12 backend. + virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer) override final; + + /// Implementation of IRenderDevice::CreateShader() in Direct3D12 backend. + virtual void CreateShader(const ShaderCreateInfo& ShaderCreateInfo, IShader** ppShader) override final; + + /// Implementation of IRenderDevice::CreateTexture() in Direct3D12 backend. + virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture) override final; + + void CreateTexture(const TextureDesc& TexDesc, ID3D12Resource* pd3d12Texture, RESOURCE_STATE InitialState, class TextureD3D12Impl** ppTexture); + + /// Implementation of IRenderDevice::CreateSampler() in Direct3D12 backend. + virtual void CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; + + /// Implementation of IRenderDevice::CreateFence() in Direct3D12 backend. + virtual void CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; + + /// Implementation of IRenderDevice::CreateQuery() in Direct3D12 backend. + virtual void CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) override final; + + /// Implementation of IRenderDeviceD3D12::GetD3D12Device(). + virtual ID3D12Device* GetD3D12Device() override final { return m_pd3d12Device; } + + /// Implementation of IRenderDeviceD3D12::CreateTextureFromD3DResource(). + virtual void CreateTextureFromD3DResource(ID3D12Resource* pd3d12Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) override final; + + /// Implementation of IRenderDeviceD3D12::CreateBufferFromD3DResource(). + virtual void CreateBufferFromD3DResource(ID3D12Resource* pd3d12Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) override final; + + DescriptorHeapAllocation AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1); + DescriptorHeapAllocation AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1); + + /// Implementation of IRenderDevice::IdleGPU() in Direct3D12 backend. + virtual void IdleGPU() override final; + + using PooledCommandContext = std::unique_ptr>; + PooledCommandContext AllocateCommandContext(const Char* ID = ""); + + void CloseAndExecuteTransientCommandContext(Uint32 CommandQueueIndex, PooledCommandContext&& Ctx); + + Uint64 CloseAndExecuteCommandContext(Uint32 QueueIndex, + PooledCommandContext&& Ctx, + bool DiscardStaleObjects, + std::vector>>* pSignalFences); + + void SignalFences(Uint32 QueueIndex, std::vector>>& SignalFences); + + // Disposes an unused command context + void DisposeCommandContext(PooledCommandContext&& Ctx); + + void FlushStaleResources(Uint32 CmdQueueIndex); + + /// Implementation of IRenderDevice::() in Direct3D12 backend. + virtual void ReleaseStaleResources(bool ForceRelease = false) override final; + + D3D12DynamicMemoryManager& GetDynamicMemoryManager() { return m_DynamicMemoryManager; } + + GPUDescriptorHeap& GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE Type) + { + VERIFY_EXPR(Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + return m_GPUDescriptorHeaps[Type]; + } + + const GenerateMipsHelper& GetMipsGenerator() const { return m_MipsGenerator; } + QueryManagerD3D12& GetQueryManager() { return m_QueryMgr; } + + D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; + +private: + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; + void FreeCommandContext(PooledCommandContext&& Ctx); + + CComPtr m_pd3d12Device; + + EngineD3D12CreateInfo m_EngineAttribs; + + CPUDescriptorHeap m_CPUDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; + GPUDescriptorHeap m_GPUDescriptorHeaps[2]; // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == 0 + // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER == 1 + + CommandListManager m_CmdListManager; + + std::mutex m_ContextPoolMutex; + std::vector> m_ContextPool; +#ifdef DEVELOPMENT + Atomics::AtomicLong m_AllocatedCtxCounter = 0; +#endif + + D3D12DynamicMemoryManager m_DynamicMemoryManager; + + // Note: mips generator must be released after the device has been idled + GenerateMipsHelper m_MipsGenerator; + + QueryManagerD3D12 m_QueryMgr; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.h b/Graphics/GraphicsEngineD3D12/include/RootSignature.h deleted file mode 100644 index fd2aff02..00000000 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.h +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::RootSignature class -#include -#include "ShaderD3DBase.h" -#include "ShaderResourceLayoutD3D12.h" -#include "BufferD3D12Impl.h" - -namespace Diligent -{ - -SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility); -D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType); -D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE RangeType); - -class RootParameter -{ -public: - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : - // clang-format off - m_RootIndex {RootIndex}, - m_ShaderVarType{VarType } - // clang-format on - { - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list"); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.Descriptor.ShaderRegister = Register; - m_RootParam.Descriptor.RegisterSpace = RegisterSpace; - } - - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - UINT NumDwords, - D3D12_SHADER_VISIBILITY Visibility, - SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : - // clang-format off - m_RootIndex {RootIndex}, - m_ShaderVarType{VarType } - // clang-format on - { - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list"); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.Constants.Num32BitValues = NumDwords; - m_RootParam.Constants.ShaderRegister = Register; - m_RootParam.Constants.RegisterSpace = RegisterSpace; - } - - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges, - D3D12_SHADER_VISIBILITY Visibility, - SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : - // clang-format off - m_RootIndex {RootIndex}, - m_ShaderVarType{VarType } - // clang-format on - { - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list"); - VERIFY_EXPR(pRanges != nullptr); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges; - m_RootParam.DescriptorTable.pDescriptorRanges = pRanges; -#ifdef _DEBUG - for (Uint32 r = 0; r < NumRanges; ++r) - pRanges[r].RangeType = static_cast(-1); -#endif - } - - RootParameter(const RootParameter& RP) noexcept : - // clang-format off - m_RootParam {RP.m_RootParam }, - m_DescriptorTableSize{RP.m_DescriptorTableSize}, - m_ShaderVarType {RP.m_ShaderVarType }, - m_RootIndex {RP.m_RootIndex } - // clang-format on - { - VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table"); - } - - RootParameter(const RootParameter& RP, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges) noexcept : - // clang-format off - m_RootParam {RP.m_RootParam }, - m_DescriptorTableSize{RP.m_DescriptorTableSize}, - m_ShaderVarType {RP.m_ShaderVarType }, - m_RootIndex {RP.m_RootIndex } - // clang-format on - { - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table"); - VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one"); - auto& DstTbl = m_RootParam.DescriptorTable; - DstTbl.NumDescriptorRanges = NumRanges; - DstTbl.pDescriptorRanges = pRanges; - const auto& SrcTbl = RP.m_RootParam.DescriptorTable; - memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); -#ifdef _DEBUG - { - Uint32 dbgTableSize = 0; - for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r) - { - const auto& Range = SrcTbl.pDescriptorRanges[r]; - dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); - } - VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size"); - - for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r) - pRanges[r].RangeType = static_cast(-1); - } -#endif - } - - RootParameter& operator=(const RootParameter&) = delete; - RootParameter& operator=(RootParameter&&) = delete; - - void SetDescriptorRange(UINT RangeIndex, - D3D12_DESCRIPTOR_RANGE_TYPE Type, - UINT Register, - UINT Count, - UINT Space = 0, - UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) - { - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); - auto& Tbl = m_RootParam.DescriptorTable; - VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index"); - D3D12_DESCRIPTOR_RANGE& range = const_cast(Tbl.pDescriptorRanges[RangeIndex]); - VERIFY(range.RangeType == static_cast(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly"); - range.RangeType = Type; - range.NumDescriptors = Count; - range.BaseShaderRegister = Register; - range.RegisterSpace = Space; - range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart; - m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count); - } - - SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType() const { return m_ShaderVarType; } - - Uint32 GetDescriptorTableSize() const - { - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); - return m_DescriptorTableSize; - } - - D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_RootParam.ShaderVisibility; } - D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_RootParam.ParameterType; } - - Uint32 GetRootIndex() const { return m_RootIndex; } - - operator const D3D12_ROOT_PARAMETER&() const { return m_RootParam; } - - bool operator==(const RootParameter& rhs) const - { - if (m_ShaderVarType != rhs.m_ShaderVarType || - m_DescriptorTableSize != rhs.m_DescriptorTableSize || - m_RootIndex != rhs.m_RootIndex) - return false; - - if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType || - m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility) - return false; - - switch (m_RootParam.ParameterType) - { - case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - { - const auto& tbl0 = m_RootParam.DescriptorTable; - const auto& tbl1 = rhs.m_RootParam.DescriptorTable; - if (tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges) - return false; - for (UINT r = 0; r < tbl0.NumDescriptorRanges; ++r) - { - const auto& rng0 = tbl0.pDescriptorRanges[r]; - const auto& rng1 = tbl1.pDescriptorRanges[r]; - if (memcmp(&rng0, &rng1, sizeof(rng0)) != 0) - return false; - } - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - { - const auto& cnst0 = m_RootParam.Constants; - const auto& cnst1 = rhs.m_RootParam.Constants; - if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0) - return false; - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_CBV: - case D3D12_ROOT_PARAMETER_TYPE_SRV: - case D3D12_ROOT_PARAMETER_TYPE_UAV: - { - const auto& dscr0 = m_RootParam.Descriptor; - const auto& dscr1 = rhs.m_RootParam.Descriptor; - if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0) - return false; - } - break; - - default: UNEXPECTED("Unexpected root parameter type"); - } - - return true; - } - - bool operator!=(const RootParameter& rhs) const - { - return !(*this == rhs); - } - - size_t GetHash() const - { - size_t hash = ComputeHash(m_ShaderVarType, m_DescriptorTableSize, m_RootIndex); - HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility); - - switch (m_RootParam.ParameterType) - { - case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - { - const auto& tbl = m_RootParam.DescriptorTable; - HashCombine(hash, tbl.NumDescriptorRanges); - for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) - { - const auto& rng = tbl.pDescriptorRanges[r]; - HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace); - } - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - { - const auto& cnst = m_RootParam.Constants; - HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister); - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_CBV: - case D3D12_ROOT_PARAMETER_TYPE_SRV: - case D3D12_ROOT_PARAMETER_TYPE_UAV: - { - const auto& dscr = m_RootParam.Descriptor; - HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister); - } - break; - - default: UNEXPECTED("Unexpected root parameter type"); - } - - return hash; - } - -private: - SHADER_RESOURCE_VARIABLE_TYPE m_ShaderVarType = static_cast(-1); - D3D12_ROOT_PARAMETER m_RootParam = {}; - Uint32 m_DescriptorTableSize = 0; - Uint32 m_RootIndex = static_cast(-1); -}; - - - -/// Implementation of the Diligent::RootSignature class -class RootSignature -{ -public: - RootSignature(); - - void AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout); - - void Finalize(ID3D12Device* pd3d12Device); - - ID3D12RootSignature* GetD3D12RootSignature() const { return m_pd3d12RootSignature; } - - size_t GetResourceCacheRequiredMemSize() const; - - void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator) const; - - void InitStaticSampler(SHADER_TYPE ShaderType, - const char* SamplerName, - const char* SamplerSuffix, - const D3DShaderResourceAttribs& ShaderResAttribs); - - void AllocateResourceSlot(SHADER_TYPE ShaderType, - const D3DShaderResourceAttribs& ShaderResAttribs, - SHADER_RESOURCE_VARIABLE_TYPE VariableType, - D3D12_DESCRIPTOR_RANGE_TYPE RangeType, - Uint32& RootIndex, - Uint32& OffsetFromTableStart); - - // This method should be thread-safe as it does not modify any object state - void (RootSignature::*CommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, - ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& Ctx, - bool IsCompute, - bool ValidateStates) const = nullptr; - - void (RootSignature::*TransitionAndCommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, - ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& Ctx, - bool IsCompute, - bool ValidateStates) const = nullptr; - - void TransitionResources(ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& Ctx) const; - - __forceinline void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& CmdCtx, - bool IsCompute, - Uint32 DeviceCtxId, - class DeviceContextD3D12Impl* pDeviceCtx, - bool CommitViews, - bool ProcessDynamicBuffers, - bool ProcessNonDynamicBuffers, - bool TransitionStates, - bool ValidateStates) const; - - Uint32 GetTotalSrvCbvUavSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const - { - return m_TotalSrvCbvUavSlots[VarType]; - } - Uint32 GetTotalSamplerSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const - { - return m_TotalSamplerSlots[VarType]; - } - Uint32 GetTotalRootViews(SHADER_RESOURCE_VARIABLE_TYPE VarType) const - { - return m_TotalRootViews[VarType]; - } - - bool IsSameAs(const RootSignature& RS) const - { - return m_RootParams == RS.m_RootParams; - } - size_t GetHash() const - { - return m_RootParams.GetHash(); - } - -private: -#ifdef _DEBUG - void dbgVerifyRootParameters() const; -#endif - -#ifdef DEVELOPMENT - static void DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resource& Res, - D3D12_DESCRIPTOR_RANGE_TYPE RangeType); -#endif - - std::vector> GetCacheTableSizes() const; - - std::array m_TotalSrvCbvUavSlots = {}; - std::array m_TotalSamplerSlots = {}; - std::array m_TotalRootViews = {}; - - CComPtr m_pd3d12RootSignature; - - class RootParamsManager - { - public: - RootParamsManager(IMemoryAllocator& MemAllocator); - - // clang-format off - RootParamsManager (const RootParamsManager&) = delete; - RootParamsManager& operator=(const RootParamsManager&) = delete; - RootParamsManager (RootParamsManager&&) = delete; - RootParamsManager& operator=(RootParamsManager&&) = delete; - // clang-format on - - Uint32 GetNumRootTables() const { return m_NumRootTables; } - Uint32 GetNumRootViews() const { return m_NumRootViews; } - - const RootParameter& GetRootTable(Uint32 TableInd) const - { - VERIFY_EXPR(TableInd < m_NumRootTables); - return m_pRootTables[TableInd]; - } - - RootParameter& GetRootTable(Uint32 TableInd) - { - VERIFY_EXPR(TableInd < m_NumRootTables); - return m_pRootTables[TableInd]; - } - - const RootParameter& GetRootView(Uint32 ViewInd) const - { - VERIFY_EXPR(ViewInd < m_NumRootViews); - return m_pRootViews[ViewInd]; - } - - RootParameter& GetRootView(Uint32 ViewInd) - { - VERIFY_EXPR(ViewInd < m_NumRootViews); - return m_pRootViews[ViewInd]; - } - - void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - D3D12_SHADER_VISIBILITY Visibility, - SHADER_RESOURCE_VARIABLE_TYPE VarType); - - void AddRootTable(Uint32 RootIndex, - D3D12_SHADER_VISIBILITY Visibility, - SHADER_RESOURCE_VARIABLE_TYPE VarType, - Uint32 NumRangesInNewTable = 1); - - void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1); - - template - void ProcessRootTables(TOperation) const; - - bool operator==(const RootParamsManager& RootParams) const; - size_t GetHash() const; - - private: - size_t GetRequiredMemorySize(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges) const; - - D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges, - Uint32 RootTableToAddRanges = static_cast(-1)); - - IMemoryAllocator& m_MemAllocator; - std::unique_ptr> m_pMemory; - Uint32 m_NumRootTables = 0; - Uint32 m_NumRootViews = 0; - Uint32 m_TotalDescriptorRanges = 0; - RootParameter* m_pRootTables = nullptr; - RootParameter* m_pRootViews = nullptr; - }; - - static constexpr Uint8 InvalidRootTableIndex = static_cast(-1); - - // The array below contains array index of a CBV/SRV/UAV root table - // in m_RootParams (NOT the Root Index!), for every variable type - // (static, mutable, dynamic) and every shader type, - // or -1, if the table is not yet assigned to the combination - std::array m_SrvCbvUavRootTablesMap; - // This array contains the same data for Sampler root table - std::array m_SamplerRootTablesMap; - - RootParamsManager m_RootParams; - - struct StaticSamplerAttribs - { - StaticSamplerDesc SamplerDesc; - UINT ShaderRegister = static_cast(-1); - UINT ArraySize = 0; - UINT RegisterSpace = 0; - D3D12_SHADER_VISIBILITY ShaderVisibility = static_cast(-1); - - StaticSamplerAttribs() noexcept {} - StaticSamplerAttribs(const StaticSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept : - SamplerDesc(SamDesc), - ShaderVisibility(Visibility) - {} - }; - // Note: sizeof(m_StaticSamplers) == 56 (MS compiler, release x64) - std::vector> m_StaticSamplers; - - IMemoryAllocator& m_MemAllocator; - - // Commits descriptor handles for static and mutable variables - template - void CommitDescriptorHandlesInternal_SM(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, - ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& Ctx, - bool IsCompute, - bool ValidateStates) const; - template - // Commits descriptor handles for static, mutable, and dynamic variables - void CommitDescriptorHandlesInternal_SMD(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, - ShaderResourceCacheD3D12& ResourceCache, - class CommandContext& Ctx, - bool IsCompute, - bool ValidateStates) const; -}; - -void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, - CommandContext& CmdCtx, - bool IsCompute, - Uint32 DeviceCtxId, - DeviceContextD3D12Impl* pDeviceCtx, - bool CommitViews, - bool ProcessDynamicBuffers, - bool ProcessNonDynamicBuffers, - bool TransitionStates, - bool ValidateStates) const -{ - for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) - { - auto& RootView = m_RootParams.GetRootView(rv); - auto RootInd = RootView.GetRootIndex(); - - SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN; -#ifdef _DEBUG - { - auto& Param = static_cast(RootView); - VERIFY_EXPR(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); - dbgShaderType = ShaderTypeFromShaderVisibility(Param.ShaderVisibility); - } -#endif - - auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType); - if (auto* pBuffToTransition = Res.pObject.RawPtr()) - { - bool IsDynamic = pBuffToTransition->GetDesc().Usage == USAGE_DYNAMIC; - if (IsDynamic && ProcessDynamicBuffers || !IsDynamic && ProcessNonDynamicBuffers) - { - if (IsDynamic) - { -#ifdef _DEBUG - if (pBuffToTransition->IsInKnownState()) - { - VERIFY(pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER), - "Dynamic buffers must always have RESOURCE_STATE_CONSTANT_BUFFER state flag set"); - } -#endif - } - else - { - if (TransitionStates) - { - if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) - { - CmdCtx.TransitionResource(pBuffToTransition, RESOURCE_STATE_CONSTANT_BUFFER); - } - } -#ifdef DEVELOPMENT - else if (ValidateStates) - { - - DvpVerifyResourceState(Res, D3D12_DESCRIPTOR_RANGE_TYPE_CBV); - } -#endif - } - - if (CommitViews) - { - D3D12_GPU_VIRTUAL_ADDRESS CBVAddress = pBuffToTransition->GetGPUAddress(DeviceCtxId, pDeviceCtx); - if (IsCompute) - CmdCtx.GetCommandList()->SetComputeRootConstantBufferView(RootInd, CBVAddress); - else - CmdCtx.GetCommandList()->SetGraphicsRootConstantBufferView(RootInd, CBVAddress); - } - } - } - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp new file mode 100644 index 00000000..e723896a --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp @@ -0,0 +1,591 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::RootSignature class +#include +#include "ShaderD3DBase.hpp" +#include "ShaderResourceLayoutD3D12.hpp" +#include "BufferD3D12Impl.hpp" + +namespace Diligent +{ + +SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility); +D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType); +D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE RangeType); + +class RootParameter +{ +public: + RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT Register, + UINT RegisterSpace, + D3D12_SHADER_VISIBILITY Visibility, + SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : + // clang-format off + m_RootIndex {RootIndex}, + m_ShaderVarType{VarType } + // clang-format on + { + VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list"); + m_RootParam.ParameterType = ParameterType; + m_RootParam.ShaderVisibility = Visibility; + m_RootParam.Descriptor.ShaderRegister = Register; + m_RootParam.Descriptor.RegisterSpace = RegisterSpace; + } + + RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT Register, + UINT RegisterSpace, + UINT NumDwords, + D3D12_SHADER_VISIBILITY Visibility, + SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : + // clang-format off + m_RootIndex {RootIndex}, + m_ShaderVarType{VarType } + // clang-format on + { + VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list"); + m_RootParam.ParameterType = ParameterType; + m_RootParam.ShaderVisibility = Visibility; + m_RootParam.Constants.Num32BitValues = NumDwords; + m_RootParam.Constants.ShaderRegister = Register; + m_RootParam.Constants.RegisterSpace = RegisterSpace; + } + + RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT NumRanges, + D3D12_DESCRIPTOR_RANGE* pRanges, + D3D12_SHADER_VISIBILITY Visibility, + SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept : + // clang-format off + m_RootIndex {RootIndex}, + m_ShaderVarType{VarType } + // clang-format on + { + VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list"); + VERIFY_EXPR(pRanges != nullptr); + m_RootParam.ParameterType = ParameterType; + m_RootParam.ShaderVisibility = Visibility; + m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges; + m_RootParam.DescriptorTable.pDescriptorRanges = pRanges; +#ifdef _DEBUG + for (Uint32 r = 0; r < NumRanges; ++r) + pRanges[r].RangeType = static_cast(-1); +#endif + } + + RootParameter(const RootParameter& RP) noexcept : + // clang-format off + m_RootParam {RP.m_RootParam }, + m_DescriptorTableSize{RP.m_DescriptorTableSize}, + m_ShaderVarType {RP.m_ShaderVarType }, + m_RootIndex {RP.m_RootIndex } + // clang-format on + { + VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table"); + } + + RootParameter(const RootParameter& RP, + UINT NumRanges, + D3D12_DESCRIPTOR_RANGE* pRanges) noexcept : + // clang-format off + m_RootParam {RP.m_RootParam }, + m_DescriptorTableSize{RP.m_DescriptorTableSize}, + m_ShaderVarType {RP.m_ShaderVarType }, + m_RootIndex {RP.m_RootIndex } + // clang-format on + { + VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table"); + VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one"); + auto& DstTbl = m_RootParam.DescriptorTable; + DstTbl.NumDescriptorRanges = NumRanges; + DstTbl.pDescriptorRanges = pRanges; + const auto& SrcTbl = RP.m_RootParam.DescriptorTable; + memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); +#ifdef _DEBUG + { + Uint32 dbgTableSize = 0; + for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r) + { + const auto& Range = SrcTbl.pDescriptorRanges[r]; + dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); + } + VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size"); + + for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r) + pRanges[r].RangeType = static_cast(-1); + } +#endif + } + + RootParameter& operator=(const RootParameter&) = delete; + RootParameter& operator=(RootParameter&&) = delete; + + void SetDescriptorRange(UINT RangeIndex, + D3D12_DESCRIPTOR_RANGE_TYPE Type, + UINT Register, + UINT Count, + UINT Space = 0, + UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + { + VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); + auto& Tbl = m_RootParam.DescriptorTable; + VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index"); + D3D12_DESCRIPTOR_RANGE& range = const_cast(Tbl.pDescriptorRanges[RangeIndex]); + VERIFY(range.RangeType == static_cast(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly"); + range.RangeType = Type; + range.NumDescriptors = Count; + range.BaseShaderRegister = Register; + range.RegisterSpace = Space; + range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart; + m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count); + } + + SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType() const { return m_ShaderVarType; } + + Uint32 GetDescriptorTableSize() const + { + VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); + return m_DescriptorTableSize; + } + + D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_RootParam.ShaderVisibility; } + D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_RootParam.ParameterType; } + + Uint32 GetRootIndex() const { return m_RootIndex; } + + operator const D3D12_ROOT_PARAMETER&() const { return m_RootParam; } + + bool operator==(const RootParameter& rhs) const + { + if (m_ShaderVarType != rhs.m_ShaderVarType || + m_DescriptorTableSize != rhs.m_DescriptorTableSize || + m_RootIndex != rhs.m_RootIndex) + return false; + + if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType || + m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility) + return false; + + switch (m_RootParam.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + { + const auto& tbl0 = m_RootParam.DescriptorTable; + const auto& tbl1 = rhs.m_RootParam.DescriptorTable; + if (tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges) + return false; + for (UINT r = 0; r < tbl0.NumDescriptorRanges; ++r) + { + const auto& rng0 = tbl0.pDescriptorRanges[r]; + const auto& rng1 = tbl1.pDescriptorRanges[r]; + if (memcmp(&rng0, &rng1, sizeof(rng0)) != 0) + return false; + } + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + { + const auto& cnst0 = m_RootParam.Constants; + const auto& cnst1 = rhs.m_RootParam.Constants; + if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0) + return false; + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + { + const auto& dscr0 = m_RootParam.Descriptor; + const auto& dscr1 = rhs.m_RootParam.Descriptor; + if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0) + return false; + } + break; + + default: UNEXPECTED("Unexpected root parameter type"); + } + + return true; + } + + bool operator!=(const RootParameter& rhs) const + { + return !(*this == rhs); + } + + size_t GetHash() const + { + size_t hash = ComputeHash(m_ShaderVarType, m_DescriptorTableSize, m_RootIndex); + HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility); + + switch (m_RootParam.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + { + const auto& tbl = m_RootParam.DescriptorTable; + HashCombine(hash, tbl.NumDescriptorRanges); + for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) + { + const auto& rng = tbl.pDescriptorRanges[r]; + HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace); + } + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + { + const auto& cnst = m_RootParam.Constants; + HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister); + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + { + const auto& dscr = m_RootParam.Descriptor; + HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister); + } + break; + + default: UNEXPECTED("Unexpected root parameter type"); + } + + return hash; + } + +private: + SHADER_RESOURCE_VARIABLE_TYPE m_ShaderVarType = static_cast(-1); + D3D12_ROOT_PARAMETER m_RootParam = {}; + Uint32 m_DescriptorTableSize = 0; + Uint32 m_RootIndex = static_cast(-1); +}; + + + +/// Implementation of the Diligent::RootSignature class +class RootSignature +{ +public: + RootSignature(); + + void AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout); + + void Finalize(ID3D12Device* pd3d12Device); + + ID3D12RootSignature* GetD3D12RootSignature() const { return m_pd3d12RootSignature; } + + size_t GetResourceCacheRequiredMemSize() const; + + void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator) const; + + void InitStaticSampler(SHADER_TYPE ShaderType, + const char* SamplerName, + const char* SamplerSuffix, + const D3DShaderResourceAttribs& ShaderResAttribs); + + void AllocateResourceSlot(SHADER_TYPE ShaderType, + const D3DShaderResourceAttribs& ShaderResAttribs, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + D3D12_DESCRIPTOR_RANGE_TYPE RangeType, + Uint32& RootIndex, + Uint32& OffsetFromTableStart); + + // This method should be thread-safe as it does not modify any object state + void (RootSignature::*CommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, + ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& Ctx, + bool IsCompute, + bool ValidateStates) const = nullptr; + + void (RootSignature::*TransitionAndCommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, + ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& Ctx, + bool IsCompute, + bool ValidateStates) const = nullptr; + + void TransitionResources(ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& Ctx) const; + + __forceinline void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& CmdCtx, + bool IsCompute, + Uint32 DeviceCtxId, + class DeviceContextD3D12Impl* pDeviceCtx, + bool CommitViews, + bool ProcessDynamicBuffers, + bool ProcessNonDynamicBuffers, + bool TransitionStates, + bool ValidateStates) const; + + Uint32 GetTotalSrvCbvUavSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const + { + return m_TotalSrvCbvUavSlots[VarType]; + } + Uint32 GetTotalSamplerSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const + { + return m_TotalSamplerSlots[VarType]; + } + Uint32 GetTotalRootViews(SHADER_RESOURCE_VARIABLE_TYPE VarType) const + { + return m_TotalRootViews[VarType]; + } + + bool IsSameAs(const RootSignature& RS) const + { + return m_RootParams == RS.m_RootParams; + } + size_t GetHash() const + { + return m_RootParams.GetHash(); + } + +private: +#ifdef _DEBUG + void dbgVerifyRootParameters() const; +#endif + +#ifdef DEVELOPMENT + static void DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resource& Res, + D3D12_DESCRIPTOR_RANGE_TYPE RangeType); +#endif + + std::vector> GetCacheTableSizes() const; + + std::array m_TotalSrvCbvUavSlots = {}; + std::array m_TotalSamplerSlots = {}; + std::array m_TotalRootViews = {}; + + CComPtr m_pd3d12RootSignature; + + class RootParamsManager + { + public: + RootParamsManager(IMemoryAllocator& MemAllocator); + + // clang-format off + RootParamsManager (const RootParamsManager&) = delete; + RootParamsManager& operator=(const RootParamsManager&) = delete; + RootParamsManager (RootParamsManager&&) = delete; + RootParamsManager& operator=(RootParamsManager&&) = delete; + // clang-format on + + Uint32 GetNumRootTables() const { return m_NumRootTables; } + Uint32 GetNumRootViews() const { return m_NumRootViews; } + + const RootParameter& GetRootTable(Uint32 TableInd) const + { + VERIFY_EXPR(TableInd < m_NumRootTables); + return m_pRootTables[TableInd]; + } + + RootParameter& GetRootTable(Uint32 TableInd) + { + VERIFY_EXPR(TableInd < m_NumRootTables); + return m_pRootTables[TableInd]; + } + + const RootParameter& GetRootView(Uint32 ViewInd) const + { + VERIFY_EXPR(ViewInd < m_NumRootViews); + return m_pRootViews[ViewInd]; + } + + RootParameter& GetRootView(Uint32 ViewInd) + { + VERIFY_EXPR(ViewInd < m_NumRootViews); + return m_pRootViews[ViewInd]; + } + + void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT Register, + D3D12_SHADER_VISIBILITY Visibility, + SHADER_RESOURCE_VARIABLE_TYPE VarType); + + void AddRootTable(Uint32 RootIndex, + D3D12_SHADER_VISIBILITY Visibility, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 NumRangesInNewTable = 1); + + void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1); + + template + void ProcessRootTables(TOperation) const; + + bool operator==(const RootParamsManager& RootParams) const; + size_t GetHash() const; + + private: + size_t GetRequiredMemorySize(Uint32 NumExtraRootTables, + Uint32 NumExtraRootViews, + Uint32 NumExtraDescriptorRanges) const; + + D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables, + Uint32 NumExtraRootViews, + Uint32 NumExtraDescriptorRanges, + Uint32 RootTableToAddRanges = static_cast(-1)); + + IMemoryAllocator& m_MemAllocator; + std::unique_ptr> m_pMemory; + Uint32 m_NumRootTables = 0; + Uint32 m_NumRootViews = 0; + Uint32 m_TotalDescriptorRanges = 0; + RootParameter* m_pRootTables = nullptr; + RootParameter* m_pRootViews = nullptr; + }; + + static constexpr Uint8 InvalidRootTableIndex = static_cast(-1); + + // The array below contains array index of a CBV/SRV/UAV root table + // in m_RootParams (NOT the Root Index!), for every variable type + // (static, mutable, dynamic) and every shader type, + // or -1, if the table is not yet assigned to the combination + std::array m_SrvCbvUavRootTablesMap; + // This array contains the same data for Sampler root table + std::array m_SamplerRootTablesMap; + + RootParamsManager m_RootParams; + + struct StaticSamplerAttribs + { + StaticSamplerDesc SamplerDesc; + UINT ShaderRegister = static_cast(-1); + UINT ArraySize = 0; + UINT RegisterSpace = 0; + D3D12_SHADER_VISIBILITY ShaderVisibility = static_cast(-1); + + StaticSamplerAttribs() noexcept {} + StaticSamplerAttribs(const StaticSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept : + SamplerDesc(SamDesc), + ShaderVisibility(Visibility) + {} + }; + // Note: sizeof(m_StaticSamplers) == 56 (MS compiler, release x64) + std::vector> m_StaticSamplers; + + IMemoryAllocator& m_MemAllocator; + + // Commits descriptor handles for static and mutable variables + template + void CommitDescriptorHandlesInternal_SM(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, + ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& Ctx, + bool IsCompute, + bool ValidateStates) const; + template + // Commits descriptor handles for static, mutable, and dynamic variables + void CommitDescriptorHandlesInternal_SMD(class RenderDeviceD3D12Impl* pRenderDeviceD3D12, + ShaderResourceCacheD3D12& ResourceCache, + class CommandContext& Ctx, + bool IsCompute, + bool ValidateStates) const; +}; + +void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, + CommandContext& CmdCtx, + bool IsCompute, + Uint32 DeviceCtxId, + DeviceContextD3D12Impl* pDeviceCtx, + bool CommitViews, + bool ProcessDynamicBuffers, + bool ProcessNonDynamicBuffers, + bool TransitionStates, + bool ValidateStates) const +{ + for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) + { + auto& RootView = m_RootParams.GetRootView(rv); + auto RootInd = RootView.GetRootIndex(); + + SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN; +#ifdef _DEBUG + { + auto& Param = static_cast(RootView); + VERIFY_EXPR(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); + dbgShaderType = ShaderTypeFromShaderVisibility(Param.ShaderVisibility); + } +#endif + + auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType); + if (auto* pBuffToTransition = Res.pObject.RawPtr()) + { + bool IsDynamic = pBuffToTransition->GetDesc().Usage == USAGE_DYNAMIC; + if (IsDynamic && ProcessDynamicBuffers || !IsDynamic && ProcessNonDynamicBuffers) + { + if (IsDynamic) + { +#ifdef _DEBUG + if (pBuffToTransition->IsInKnownState()) + { + VERIFY(pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER), + "Dynamic buffers must always have RESOURCE_STATE_CONSTANT_BUFFER state flag set"); + } +#endif + } + else + { + if (TransitionStates) + { + if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) + { + CmdCtx.TransitionResource(pBuffToTransition, RESOURCE_STATE_CONSTANT_BUFFER); + } + } +#ifdef DEVELOPMENT + else if (ValidateStates) + { + + DvpVerifyResourceState(Res, D3D12_DESCRIPTOR_RANGE_TYPE_CBV); + } +#endif + } + + if (CommitViews) + { + D3D12_GPU_VIRTUAL_ADDRESS CBVAddress = pBuffToTransition->GetGPUAddress(DeviceCtxId, pDeviceCtx); + if (IsCompute) + CmdCtx.GetCommandList()->SetComputeRootConstantBufferView(RootInd, CBVAddress); + else + CmdCtx.GetCommandList()->SetGraphicsRootConstantBufferView(RootInd, CBVAddress); + } + } + } + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h deleted file mode 100644 index c52f7c17..00000000 --- a/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::SamplerD3D12Impl class - -#include "SamplerD3D12.h" -#include "RenderDeviceD3D12.h" -#include "SamplerBase.h" -#include "DescriptorHeap.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Sampler object implementation in Direct3D12 backend. -class SamplerD3D12Impl final : public SamplerBase -{ -public: - using TSamplerBase = SamplerBase; - - SamplerD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pRenderDeviceD3D12, - const SamplerDesc& SamplerDesc); - ~SamplerD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ISamplerD3D12::GetCPUDescriptorHandle(). - virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override { return m_Descriptor.GetCpuHandle(); } - -private: - friend class ShaderD3D12Impl; - /// D3D12 sampler - DescriptorHeapAllocation m_Descriptor; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.hpp new file mode 100644 index 00000000..5633b5dc --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/SamplerD3D12Impl.hpp @@ -0,0 +1,66 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::SamplerD3D12Impl class + +#include "SamplerD3D12.h" +#include "RenderDeviceD3D12.h" +#include "SamplerBase.hpp" +#include "DescriptorHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Sampler object implementation in Direct3D12 backend. +class SamplerD3D12Impl final : public SamplerBase +{ +public: + using TSamplerBase = SamplerBase; + + SamplerD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pRenderDeviceD3D12, + const SamplerDesc& SamplerDesc); + ~SamplerD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ISamplerD3D12::GetCPUDescriptorHandle(). + virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override { return m_Descriptor.GetCpuHandle(); } + +private: + friend class ShaderD3D12Impl; + /// D3D12 sampler + DescriptorHeapAllocation m_Descriptor; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h deleted file mode 100644 index a5be1a03..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderD3D12Impl class - -#include "RenderDeviceD3D12.h" -#include "ShaderD3D12.h" -#include "ShaderBase.h" -#include "ShaderD3DBase.h" -#include "ShaderResourceLayoutD3D12.h" -#include "RenderDeviceD3D12Impl.h" -#include "ShaderVariableD3D12.h" - -namespace Diligent -{ - -class ResourceMapping; - -/// Implementation of a shader object in Direct3D12 backend. -class ShaderD3D12Impl final : public ShaderBase, public ShaderD3DBase -{ -public: - using TShaderBase = ShaderBase; - - ShaderD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pRenderDeviceD3D12, - const ShaderCreateInfo& ShaderCI); - ~ShaderD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IShader::GetResourceCount() in Direct3D12 backend. - virtual Uint32 GetResourceCount() const override final - { - return m_pShaderResources->GetTotalResources(); - } - - /// Implementation of IShader::GetResource() in Direct3D12 backend. - virtual void GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final - { - ResourceDesc = GetHLSLResource(Index); - } - - /// Implementation of IShaderD3D::GetHLSLResource() in Direct3D12 backend. - virtual HLSLShaderResourceDesc GetHLSLResource(Uint32 Index) const override final - { - return m_pShaderResources->GetHLSLShaderResourceDesc(Index); - } - - ID3DBlob* GetShaderByteCode() { return m_pShaderByteCode; } - - const std::shared_ptr& GetShaderResources() const { return m_pShaderResources; } - -private: - // ShaderResources class instance must be referenced through the shared pointer, because - // it is referenced by ShaderResourceLayoutD3D12 class instances - std::shared_ptr m_pShaderResources; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp new file mode 100644 index 00000000..6eb8e5d8 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp @@ -0,0 +1,87 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderD3D12Impl class + +#include "RenderDeviceD3D12.h" +#include "ShaderD3D12.h" +#include "ShaderBase.hpp" +#include "ShaderD3DBase.hpp" +#include "ShaderResourceLayoutD3D12.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "ShaderVariableD3D12.hpp" + +namespace Diligent +{ + +class ResourceMapping; + +/// Implementation of a shader object in Direct3D12 backend. +class ShaderD3D12Impl final : public ShaderBase, public ShaderD3DBase +{ +public: + using TShaderBase = ShaderBase; + + ShaderD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pRenderDeviceD3D12, + const ShaderCreateInfo& ShaderCI); + ~ShaderD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IShader::GetResourceCount() in Direct3D12 backend. + virtual Uint32 GetResourceCount() const override final + { + return m_pShaderResources->GetTotalResources(); + } + + /// Implementation of IShader::GetResource() in Direct3D12 backend. + virtual void GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final + { + ResourceDesc = GetHLSLResource(Index); + } + + /// Implementation of IShaderD3D::GetHLSLResource() in Direct3D12 backend. + virtual HLSLShaderResourceDesc GetHLSLResource(Uint32 Index) const override final + { + return m_pShaderResources->GetHLSLShaderResourceDesc(Index); + } + + ID3DBlob* GetShaderByteCode() { return m_pShaderByteCode; } + + const std::shared_ptr& GetShaderResources() const { return m_pShaderResources; } + +private: + // ShaderResources class instance must be referenced through the shared pointer, because + // it is referenced by ShaderResourceLayoutD3D12 class instances + std::shared_ptr m_pShaderResources; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h deleted file mode 100644 index c89a31e7..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceBindingD3D12Impl class - -#include "ShaderResourceBindingD3D12.h" -#include "RenderDeviceD3D12.h" -#include "ShaderResourceBindingBase.h" -#include "ShaderBase.h" -#include "ShaderResourceCacheD3D12.h" -#include "ShaderResourceLayoutD3D12.h" -#include "ShaderVariableD3D12.h" - -namespace Diligent -{ - -/// Implementation of the Diligent::IShaderResourceBindingD3D12 interface -// sizeof(ShaderResourceBindingD3D12Impl) == 152 (x64, msvc, Release) -class ShaderResourceBindingD3D12Impl final : public ShaderResourceBindingBase -{ -public: - using TBase = ShaderResourceBindingBase; - - ShaderResourceBindingD3D12Impl(IReferenceCounters* pRefCounters, - class PipelineStateD3D12Impl* pPSO, - bool IsPSOInternal); - ~ShaderResourceBindingD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) override; - - virtual IShaderResourceVariable* GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override; - - virtual Uint32 GetVariableCount(SHADER_TYPE ShaderType) const override final; - - virtual IShaderResourceVariable* GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; - - virtual void InitializeStaticResources(const IPipelineState* pPipelineState) override final; - - ShaderResourceCacheD3D12& GetResourceCache() { return m_ShaderResourceCache; } - -#ifdef DEVELOPMENT - void dvpVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) const; -#endif - - bool StaticResourcesInitialized() const - { - return m_bStaticResourcesInitialized; - } - -private: - ShaderResourceCacheD3D12 m_ShaderResourceCache; - ShaderVariableManagerD3D12* m_pShaderVarMgrs = nullptr; - // Resource layout index in m_ResourceLayouts[] array for every shader stage - Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; - bool m_bStaticResourcesInitialized = false; - const Uint8 m_NumShaders = 0; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp new file mode 100644 index 00000000..2fde8ed1 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp @@ -0,0 +1,88 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceBindingD3D12Impl class + +#include "ShaderResourceBindingD3D12.h" +#include "RenderDeviceD3D12.h" +#include "ShaderResourceBindingBase.hpp" +#include "ShaderBase.hpp" +#include "ShaderResourceCacheD3D12.hpp" +#include "ShaderResourceLayoutD3D12.hpp" +#include "ShaderVariableD3D12.hpp" + +namespace Diligent +{ + +/// Implementation of the Diligent::IShaderResourceBindingD3D12 interface +// sizeof(ShaderResourceBindingD3D12Impl) == 152 (x64, msvc, Release) +class ShaderResourceBindingD3D12Impl final : public ShaderResourceBindingBase +{ +public: + using TBase = ShaderResourceBindingBase; + + ShaderResourceBindingD3D12Impl(IReferenceCounters* pRefCounters, + class PipelineStateD3D12Impl* pPSO, + bool IsPSOInternal); + ~ShaderResourceBindingD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) override; + + virtual IShaderResourceVariable* GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override; + + virtual Uint32 GetVariableCount(SHADER_TYPE ShaderType) const override final; + + virtual IShaderResourceVariable* GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; + + virtual void InitializeStaticResources(const IPipelineState* pPipelineState) override final; + + ShaderResourceCacheD3D12& GetResourceCache() { return m_ShaderResourceCache; } + +#ifdef DEVELOPMENT + void dvpVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) const; +#endif + + bool StaticResourcesInitialized() const + { + return m_bStaticResourcesInitialized; + } + +private: + ShaderResourceCacheD3D12 m_ShaderResourceCache; + ShaderVariableManagerD3D12* m_pShaderVarMgrs = nullptr; + // Resource layout index in m_ResourceLayouts[] array for every shader stage + Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; + bool m_bStaticResourcesInitialized = false; + const Uint8 m_NumShaders = 0; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h deleted file mode 100644 index 692214dc..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceCacheD3D12 class - -// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache/ - -// Shader resource cache stores D3D12 resources in a continuous chunk of memory: -// -// -// __________________________________________________________ -// m_pMemory | m_pResources, m_NumResources == m | -// | | | -// V | V -// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | -// | A \ -// | | \ -// |________________________________________________| \RefCntAutoPtr -// m_pResources, m_NumResources == n \_________ -// | Object | -// --------- -// -// Nrt = m_NumTables -// -// -// The cache is also assigned decriptor heap space to store shader visible descriptor handles (for non-dynamic resources). -// -// -// DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV -// | DescrptHndl[0] ... DescrptHndl[n-1] | DescrptHndl[0] ... DescrptHndl[m-1] | -// A A -// | | -// | TableStartOffset | TableStartOffset -// | | -// | RootTable[0] | RootTable[1] | RootTable[2] | .... | RootTable[Nrt] | -// | | -// | TableStartOffset | InvalidDescriptorOffset -// | | -// V V -// | DescrptHndl[0] ... DescrptHndl[n-1] | X -// DESCRIPTOR_HEAP_TYPE_SAMPLER -// -// -// -// The allocation is inexed by the offset from the beginning of the root table -// Each root table is assigned the space to store exactly m_NumResources resources -// Dynamic resources are not assigned space in the descriptor heap allocation. -// -// -// -// | RootTable[i] | Res[0] ... Res[n-1] | -// \ -// TableStartOffset\____ -// \ -// V -// ..... | DescrptHndl[0] ... DescrptHndl[n-1] | .... -// - -#include "DescriptorHeap.h" - -namespace Diligent -{ - -enum class CachedResourceType : Int32 -{ - Unknown = -1, - CBV = 0, - TexSRV, - BufSRV, - TexUAV, - BufUAV, - Sampler, - NumTypes -}; - -class ShaderResourceCacheD3D12 -{ -public: - // This enum is used for debug purposes only - enum DbgCacheContentType - { - StaticShaderResources, - SRBResources - }; - - ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) - // clang-format off -#ifdef _DEBUG - : m_DbgContentType - { - dbgContentType - } -#endif - // clang-format on - { - } - - ~ShaderResourceCacheD3D12(); - - static size_t GetRequiredMemorySize(Uint32 NumTables, - Uint32 TableSizes[]); - - void Initialize(IMemoryAllocator& MemAllocator, - Uint32 NumTables, - Uint32 TableSizes[]); - - static constexpr Uint32 InvalidDescriptorOffset = static_cast(-1); - - //http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Cache-Structure - struct Resource - { - Resource() noexcept {} - - CachedResourceType Type = CachedResourceType::Unknown; - // CPU descriptor handle of a cached resource in CPU-only descriptor heap - // Note that for dynamic resources, this is the only available CPU descriptor handle - D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; - RefCntAutoPtr pObject; - }; - - class RootTable - { - public: - RootTable(Uint32 NumResources, Resource* pResources) noexcept : - // clang-format off - m_NumResources{NumResources}, - m_pResources {pResources } - // clang-format on - {} - - inline const Resource& GetResource(Uint32 OffsetFromTableStart) const - { - VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); - return m_pResources[OffsetFromTableStart]; - } - - inline const Resource& GetResource(Uint32 OffsetFromTableStart, - const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) const - { - VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type"); - VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type"); - - VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); - return m_pResources[OffsetFromTableStart]; - } - inline Resource& GetResource(Uint32 OffsetFromTableStart, - const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) - { - return const_cast(const_cast(this)->GetResource(OffsetFromTableStart, dbgDescriptorHeapType, dbgRefShaderType)); - } - - inline Uint32 GetSize() const { return m_NumResources; } - - // Offset from the start of the descriptor heap allocation to the start of the table - Uint32 m_TableStartOffset = InvalidDescriptorOffset; - -#ifdef _DEBUG - void SetDebugAttribs(Uint32 MaxOffset, - const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) - { - VERIFY_EXPR(m_NumResources == MaxOffset); - m_dbgHeapType = dbgDescriptorHeapType; - m_dbgShaderType = dbgRefShaderType; - } - - D3D12_DESCRIPTOR_HEAP_TYPE DbgGetHeapType() const { return m_dbgHeapType; } -#endif - - const Uint32 m_NumResources = 0; - - private: -#ifdef _DEBUG - D3D12_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; - SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN; -#endif - - Resource* const m_pResources = nullptr; - }; - - inline RootTable& GetRootTable(Uint32 RootIndex) - { - VERIFY_EXPR(RootIndex < m_NumTables); - return reinterpret_cast(m_pMemory)[RootIndex]; - } - inline const RootTable& GetRootTable(Uint32 RootIndex) const - { - VERIFY_EXPR(RootIndex < m_NumTables); - return reinterpret_cast(m_pMemory)[RootIndex]; - } - - inline Uint32 GetNumRootTables() const { return m_NumTables; } - - void SetDescriptorHeapSpace(DescriptorHeapAllocation&& CbcSrvUavHeapSpace, DescriptorHeapAllocation&& SamplerHeapSpace) - { - VERIFY(m_SamplerHeapSpace.GetCpuHandle().ptr == 0 && m_CbvSrvUavHeapSpace.GetCpuHandle().ptr == 0, "Space has already been allocated in GPU descriptor heaps"); -#ifdef _DEBUG - Uint32 NumSamplerDescriptors = 0, NumSrvCbvUavDescriptors = 0; - for (Uint32 rt = 0; rt < m_NumTables; ++rt) - { - auto& Tbl = GetRootTable(rt); - if (Tbl.m_TableStartOffset != InvalidDescriptorOffset) - { - if (Tbl.DbgGetHeapType() == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - VERIFY(Tbl.m_TableStartOffset == NumSrvCbvUavDescriptors, "Descriptor space allocation is not continuous"); - NumSrvCbvUavDescriptors = std::max(NumSrvCbvUavDescriptors, Tbl.m_TableStartOffset + Tbl.GetSize()); - } - else - { - VERIFY(Tbl.m_TableStartOffset == NumSamplerDescriptors, "Descriptor space allocation is not continuous"); - NumSamplerDescriptors = std::max(NumSamplerDescriptors, Tbl.m_TableStartOffset + Tbl.GetSize()); - } - } - } - VERIFY(NumSrvCbvUavDescriptors == CbcSrvUavHeapSpace.GetNumHandles() || NumSrvCbvUavDescriptors == 0 && CbcSrvUavHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size"); - VERIFY(NumSamplerDescriptors == SamplerHeapSpace.GetNumHandles() || NumSamplerDescriptors == 0 && SamplerHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size"); -#endif - - m_CbvSrvUavHeapSpace = std::move(CbcSrvUavHeapSpace); - m_SamplerHeapSpace = std::move(SamplerHeapSpace); - } - - ID3D12DescriptorHeap* GetSrvCbvUavDescriptorHeap() { return m_CbvSrvUavHeapSpace.GetDescriptorHeap(); } - ID3D12DescriptorHeap* GetSamplerDescriptorHeap() { return m_SamplerHeapSpace.GetDescriptorHeap(); } - - // Returns CPU descriptor handle of a shader visible descriptor heap allocation - template - D3D12_CPU_DESCRIPTOR_HANDLE GetShaderVisibleTableCPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) const - { - const auto& RootParam = GetRootTable(RootParamInd); - VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type"); - - D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; - // Descriptor heap allocation is not assigned for dynamic resources or - // in a special case when resource cache is used to store static - // variable assignments for a shader. It is also not assigned to root views - if (RootParam.m_TableStartOffset != InvalidDescriptorOffset) - { - VERIFY(OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range"); - if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) - { - VERIFY_EXPR(!m_SamplerHeapSpace.IsNull()); - CPUDescriptorHandle = m_SamplerHeapSpace.GetCpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); - } - else if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - VERIFY_EXPR(!m_CbvSrvUavHeapSpace.IsNull()); - CPUDescriptorHandle = m_CbvSrvUavHeapSpace.GetCpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); - } - else - { - UNEXPECTED("Unexpected descriptor heap type"); - } - } - - return CPUDescriptorHandle; - } - - // Returns GPU descriptor handle of a shader visible descriptor table - template - D3D12_GPU_DESCRIPTOR_HANDLE GetShaderVisibleTableGPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) const - { - const auto& RootParam = GetRootTable(RootParamInd); - VERIFY(RootParam.m_TableStartOffset != InvalidDescriptorOffset, "GPU descriptor handle must never be requested for dynamic resources"); - VERIFY(OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range"); - - D3D12_GPU_DESCRIPTOR_HANDLE GPUDescriptorHandle = {0}; - VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type"); - if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) - { - VERIFY_EXPR(!m_SamplerHeapSpace.IsNull()); - GPUDescriptorHandle = m_SamplerHeapSpace.GetGpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); - } - else if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - VERIFY_EXPR(!m_CbvSrvUavHeapSpace.IsNull()); - GPUDescriptorHandle = m_CbvSrvUavHeapSpace.GetGpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); - } - else - { - UNEXPECTED("Unexpected descriptor heap type"); - } - - return GPUDescriptorHandle; - } - - Uint32& GetBoundDynamicCBsCounter() { return m_NumDynamicCBsBound; } - - // Returns the number of dynamic constant buffers bound in the cache regardless of their variable types - Uint32 GetNumDynamicCBsBound() const { return m_NumDynamicCBsBound; } - -#ifdef _DEBUG - // Only for debug purposes: indicates what types of resources are stored in the cache - DbgCacheContentType DbgGetContentType() const { return m_DbgContentType; } - void DbgVerifyBoundDynamicCBsCounter() const; -#endif - -private: - // clang-format off - ShaderResourceCacheD3D12 (const ShaderResourceCacheD3D12&) = delete; - ShaderResourceCacheD3D12 (ShaderResourceCacheD3D12&&) = delete; - ShaderResourceCacheD3D12& operator = (const ShaderResourceCacheD3D12&) = delete; - ShaderResourceCacheD3D12& operator = (ShaderResourceCacheD3D12&&) = delete; - // clang-format on - - // Allocation in a GPU-visible sampler descriptor heap - DescriptorHeapAllocation m_SamplerHeapSpace; - - // Allocation in a GPU-visible CBV/SRV/UAV descriptor heap - DescriptorHeapAllocation m_CbvSrvUavHeapSpace; - - IMemoryAllocator* m_pAllocator = nullptr; - void* m_pMemory = nullptr; - Uint32 m_NumTables = 0; - // The number of the dynamic buffers bound in the resource cache regardless of their variable type - Uint32 m_NumDynamicCBsBound = 0; - -#ifdef _DEBUG - // Only for debug purposes: indicates what types of resources are stored in the cache - const DbgCacheContentType m_DbgContentType; -#endif -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp new file mode 100644 index 00000000..9f24d2d4 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -0,0 +1,354 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceCacheD3D12 class + +// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache/ + +// Shader resource cache stores D3D12 resources in a continuous chunk of memory: +// +// +// __________________________________________________________ +// m_pMemory | m_pResources, m_NumResources == m | +// | | | +// V | V +// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | +// | A \ +// | | \ +// |________________________________________________| \RefCntAutoPtr +// m_pResources, m_NumResources == n \_________ +// | Object | +// --------- +// +// Nrt = m_NumTables +// +// +// The cache is also assigned decriptor heap space to store shader visible descriptor handles (for non-dynamic resources). +// +// +// DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV +// | DescrptHndl[0] ... DescrptHndl[n-1] | DescrptHndl[0] ... DescrptHndl[m-1] | +// A A +// | | +// | TableStartOffset | TableStartOffset +// | | +// | RootTable[0] | RootTable[1] | RootTable[2] | .... | RootTable[Nrt] | +// | | +// | TableStartOffset | InvalidDescriptorOffset +// | | +// V V +// | DescrptHndl[0] ... DescrptHndl[n-1] | X +// DESCRIPTOR_HEAP_TYPE_SAMPLER +// +// +// +// The allocation is inexed by the offset from the beginning of the root table +// Each root table is assigned the space to store exactly m_NumResources resources +// Dynamic resources are not assigned space in the descriptor heap allocation. +// +// +// +// | RootTable[i] | Res[0] ... Res[n-1] | +// \ +// TableStartOffset\____ +// \ +// V +// ..... | DescrptHndl[0] ... DescrptHndl[n-1] | .... +// + +#include "DescriptorHeap.hpp" + +namespace Diligent +{ + +enum class CachedResourceType : Int32 +{ + Unknown = -1, + CBV = 0, + TexSRV, + BufSRV, + TexUAV, + BufUAV, + Sampler, + NumTypes +}; + +class ShaderResourceCacheD3D12 +{ +public: + // This enum is used for debug purposes only + enum DbgCacheContentType + { + StaticShaderResources, + SRBResources + }; + + ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) + // clang-format off +#ifdef _DEBUG + : m_DbgContentType + { + dbgContentType + } +#endif + // clang-format on + { + } + + ~ShaderResourceCacheD3D12(); + + static size_t GetRequiredMemorySize(Uint32 NumTables, + Uint32 TableSizes[]); + + void Initialize(IMemoryAllocator& MemAllocator, + Uint32 NumTables, + Uint32 TableSizes[]); + + static constexpr Uint32 InvalidDescriptorOffset = static_cast(-1); + + //http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Cache-Structure + struct Resource + { + Resource() noexcept {} + + CachedResourceType Type = CachedResourceType::Unknown; + // CPU descriptor handle of a cached resource in CPU-only descriptor heap + // Note that for dynamic resources, this is the only available CPU descriptor handle + D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; + RefCntAutoPtr pObject; + }; + + class RootTable + { + public: + RootTable(Uint32 NumResources, Resource* pResources) noexcept : + // clang-format off + m_NumResources{NumResources}, + m_pResources {pResources } + // clang-format on + {} + + inline const Resource& GetResource(Uint32 OffsetFromTableStart) const + { + VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); + return m_pResources[OffsetFromTableStart]; + } + + inline const Resource& GetResource(Uint32 OffsetFromTableStart, + const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, + const SHADER_TYPE dbgRefShaderType) const + { + VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type"); + VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type"); + + VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); + return m_pResources[OffsetFromTableStart]; + } + inline Resource& GetResource(Uint32 OffsetFromTableStart, + const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, + const SHADER_TYPE dbgRefShaderType) + { + return const_cast(const_cast(this)->GetResource(OffsetFromTableStart, dbgDescriptorHeapType, dbgRefShaderType)); + } + + inline Uint32 GetSize() const { return m_NumResources; } + + // Offset from the start of the descriptor heap allocation to the start of the table + Uint32 m_TableStartOffset = InvalidDescriptorOffset; + +#ifdef _DEBUG + void SetDebugAttribs(Uint32 MaxOffset, + const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, + const SHADER_TYPE dbgRefShaderType) + { + VERIFY_EXPR(m_NumResources == MaxOffset); + m_dbgHeapType = dbgDescriptorHeapType; + m_dbgShaderType = dbgRefShaderType; + } + + D3D12_DESCRIPTOR_HEAP_TYPE DbgGetHeapType() const { return m_dbgHeapType; } +#endif + + const Uint32 m_NumResources = 0; + + private: +#ifdef _DEBUG + D3D12_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; + SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN; +#endif + + Resource* const m_pResources = nullptr; + }; + + inline RootTable& GetRootTable(Uint32 RootIndex) + { + VERIFY_EXPR(RootIndex < m_NumTables); + return reinterpret_cast(m_pMemory)[RootIndex]; + } + inline const RootTable& GetRootTable(Uint32 RootIndex) const + { + VERIFY_EXPR(RootIndex < m_NumTables); + return reinterpret_cast(m_pMemory)[RootIndex]; + } + + inline Uint32 GetNumRootTables() const { return m_NumTables; } + + void SetDescriptorHeapSpace(DescriptorHeapAllocation&& CbcSrvUavHeapSpace, DescriptorHeapAllocation&& SamplerHeapSpace) + { + VERIFY(m_SamplerHeapSpace.GetCpuHandle().ptr == 0 && m_CbvSrvUavHeapSpace.GetCpuHandle().ptr == 0, "Space has already been allocated in GPU descriptor heaps"); +#ifdef _DEBUG + Uint32 NumSamplerDescriptors = 0, NumSrvCbvUavDescriptors = 0; + for (Uint32 rt = 0; rt < m_NumTables; ++rt) + { + auto& Tbl = GetRootTable(rt); + if (Tbl.m_TableStartOffset != InvalidDescriptorOffset) + { + if (Tbl.DbgGetHeapType() == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + VERIFY(Tbl.m_TableStartOffset == NumSrvCbvUavDescriptors, "Descriptor space allocation is not continuous"); + NumSrvCbvUavDescriptors = std::max(NumSrvCbvUavDescriptors, Tbl.m_TableStartOffset + Tbl.GetSize()); + } + else + { + VERIFY(Tbl.m_TableStartOffset == NumSamplerDescriptors, "Descriptor space allocation is not continuous"); + NumSamplerDescriptors = std::max(NumSamplerDescriptors, Tbl.m_TableStartOffset + Tbl.GetSize()); + } + } + } + VERIFY(NumSrvCbvUavDescriptors == CbcSrvUavHeapSpace.GetNumHandles() || NumSrvCbvUavDescriptors == 0 && CbcSrvUavHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size"); + VERIFY(NumSamplerDescriptors == SamplerHeapSpace.GetNumHandles() || NumSamplerDescriptors == 0 && SamplerHeapSpace.GetCpuHandle(0).ptr == 0, "Unexpected descriptor heap allocation size"); +#endif + + m_CbvSrvUavHeapSpace = std::move(CbcSrvUavHeapSpace); + m_SamplerHeapSpace = std::move(SamplerHeapSpace); + } + + ID3D12DescriptorHeap* GetSrvCbvUavDescriptorHeap() { return m_CbvSrvUavHeapSpace.GetDescriptorHeap(); } + ID3D12DescriptorHeap* GetSamplerDescriptorHeap() { return m_SamplerHeapSpace.GetDescriptorHeap(); } + + // Returns CPU descriptor handle of a shader visible descriptor heap allocation + template + D3D12_CPU_DESCRIPTOR_HANDLE GetShaderVisibleTableCPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) const + { + const auto& RootParam = GetRootTable(RootParamInd); + VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type"); + + D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; + // Descriptor heap allocation is not assigned for dynamic resources or + // in a special case when resource cache is used to store static + // variable assignments for a shader. It is also not assigned to root views + if (RootParam.m_TableStartOffset != InvalidDescriptorOffset) + { + VERIFY(OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range"); + if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + VERIFY_EXPR(!m_SamplerHeapSpace.IsNull()); + CPUDescriptorHandle = m_SamplerHeapSpace.GetCpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); + } + else if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + VERIFY_EXPR(!m_CbvSrvUavHeapSpace.IsNull()); + CPUDescriptorHandle = m_CbvSrvUavHeapSpace.GetCpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); + } + else + { + UNEXPECTED("Unexpected descriptor heap type"); + } + } + + return CPUDescriptorHandle; + } + + // Returns GPU descriptor handle of a shader visible descriptor table + template + D3D12_GPU_DESCRIPTOR_HANDLE GetShaderVisibleTableGPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) const + { + const auto& RootParam = GetRootTable(RootParamInd); + VERIFY(RootParam.m_TableStartOffset != InvalidDescriptorOffset, "GPU descriptor handle must never be requested for dynamic resources"); + VERIFY(OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range"); + + D3D12_GPU_DESCRIPTOR_HANDLE GPUDescriptorHandle = {0}; + VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type"); + if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + VERIFY_EXPR(!m_SamplerHeapSpace.IsNull()); + GPUDescriptorHandle = m_SamplerHeapSpace.GetGpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); + } + else if (HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + VERIFY_EXPR(!m_CbvSrvUavHeapSpace.IsNull()); + GPUDescriptorHandle = m_CbvSrvUavHeapSpace.GetGpuHandle(RootParam.m_TableStartOffset + OffsetFromTableStart); + } + else + { + UNEXPECTED("Unexpected descriptor heap type"); + } + + return GPUDescriptorHandle; + } + + Uint32& GetBoundDynamicCBsCounter() { return m_NumDynamicCBsBound; } + + // Returns the number of dynamic constant buffers bound in the cache regardless of their variable types + Uint32 GetNumDynamicCBsBound() const { return m_NumDynamicCBsBound; } + +#ifdef _DEBUG + // Only for debug purposes: indicates what types of resources are stored in the cache + DbgCacheContentType DbgGetContentType() const { return m_DbgContentType; } + void DbgVerifyBoundDynamicCBsCounter() const; +#endif + +private: + // clang-format off + ShaderResourceCacheD3D12 (const ShaderResourceCacheD3D12&) = delete; + ShaderResourceCacheD3D12 (ShaderResourceCacheD3D12&&) = delete; + ShaderResourceCacheD3D12& operator = (const ShaderResourceCacheD3D12&) = delete; + ShaderResourceCacheD3D12& operator = (ShaderResourceCacheD3D12&&) = delete; + // clang-format on + + // Allocation in a GPU-visible sampler descriptor heap + DescriptorHeapAllocation m_SamplerHeapSpace; + + // Allocation in a GPU-visible CBV/SRV/UAV descriptor heap + DescriptorHeapAllocation m_CbvSrvUavHeapSpace; + + IMemoryAllocator* m_pAllocator = nullptr; + void* m_pMemory = nullptr; + Uint32 m_NumTables = 0; + // The number of the dynamic buffers bound in the resource cache regardless of their variable type + Uint32 m_NumDynamicCBsBound = 0; + +#ifdef _DEBUG + // Only for debug purposes: indicates what types of resources are stored in the cache + const DbgCacheContentType m_DbgContentType; +#endif +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h deleted file mode 100644 index 75c2837f..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourceLayoutD3D12 class - -// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout/ - -// All resources are stored in a single continuous chunk of memory using the following layout: -// -// m_ResourceBuffer -// | | | -// | D3D12Resource[0] ... | D3D12Resource[s] ... | D3D12Resource[s+m] ... | D3D12Resource[smd] ... | D3D12Resource[smd+s'] ... | D3D12Resource[smd+s'+m'] ... D3D12Resource[s+m+d+s'+m'+d'-1] || -// | | | | | | || -// | SRV/CBV/UAV - STATIC | SRV/CBV/UAV - MUTABLE | SRV/CBV/UAV - DYNAMIC | Samplers - STATIC | Samplers - MUTABLE | Samplers - DYNAMIC || -// | | | | -// -// s == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] -// m == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] -// d == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] -// smd = s+m+d -// -// s' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] -// m' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] -// d' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] -// -// Every D3D12Resource structure holds a reference to D3DShaderResourceAttribs structure from ShaderResourcesD3D12. -// ShaderResourceLayoutD3D12 holds shared pointer to ShaderResourcesD3D12 instance. Note that ShaderResourcesD3D12::SamplerId -// references a sampler in ShaderResourcesD3D12, while D3D12Resource::SamplerId references a sampler in ShaderResourceLayoutD3D12, -// and the two are not necessarily the same -// -// -// ________________SamplerId____________________ -// | | -// _____________________ ______________|_____________________________________________V________ -// | | unique_ptr | | | | | | | -// |ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | -// |_____________________| |________|___________|___________|___________|___________|____________| -// A A A A -// | \ / \ -// |shared_ptr Ref Ref Ref -// ________|__________________ ________\________________________/_________________________\________________________________________________ -// | | unique_ptr | | | | | | | -// | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[smd] | D3D12Resource[smd+1] | ... | -// |___________________________| |__________________|__________________|_______________|____________________|______________________|__________| -// A A | A A -// | \ |______________\____SamplerId________________________| -// | \ \ -// | Ref Ref -// | \ \_____ -// | \ \ -// ____________|_______________ ________\_______________________\__________________________________________ -// | | | | | | -// | ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | -// |____________________________| |____________________________|____________________________|_________________| - -// -// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Figure2 -// Resources in the resource cache are identified by the root index and offset in the descriptor table -// -// -// ShaderResourceLayoutD3D12 is used as follows: -// * Every pipeline state object (PipelineStateD3D12Impl) maintains shader resource layout for every active shader stage -// ** These resource layouts are used as reference layouts for shader resource binding objects -// ** All variable types are preserved -// ** Root indices and descriptor table offsets are assigned during the initialization -// * Every pipeline state object also contains shader resource layout that facilitates management of static shader resources -// ** The resource layout defines artificial layout where root index matches the resource type (CBV/SRV/UAV/SAM) -// ** Only static variables are referenced -// -// * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader variable -// manager (ShaderVariableManagerD3D12) for every active shader stage in the parent pipeline state that -// handles mutable and dynamic resources - -#include - -#include "ShaderBase.h" -#include "ShaderResourcesD3D12.h" -#include "ShaderResourceCacheD3D12.h" - -namespace Diligent -{ - -/// Diligent::ShaderResourceLayoutD3D12 class -// sizeof(ShaderResourceLayoutD3D12) == 64 (MS compiler, x64) -class ShaderResourceLayoutD3D12 final -{ -public: - // There are two modes a layout can be constructed: - // - initialize static resource layout and initialize shader resource cache to hold static resources - // - initialize reference layouts that address all types of resources (static, mutable, dynamic). - // Root indices and descriptor table offsets are assigned during the initialization; - // no shader resource cache is provided - ShaderResourceLayoutD3D12(IObject& Owner, - ID3D12Device* pd3d12Device, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - class RootSignature* pRootSig); - - // clang-format off - ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; - ShaderResourceLayoutD3D12 (ShaderResourceLayoutD3D12&&) = delete; - ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete; - ShaderResourceLayoutD3D12& operator =(ShaderResourceLayoutD3D12&&) = delete; - // clang-format on - - ~ShaderResourceLayoutD3D12(); - - // sizeof(D3D12Resource) == 24 (x64) - struct D3D12Resource final - { - // clang-format off - - D3D12Resource (const D3D12Resource&) = delete; - D3D12Resource ( D3D12Resource&&) = delete; - D3D12Resource& operator = (const D3D12Resource&) = delete; - D3D12Resource& operator = ( D3D12Resource&&) = delete; - - static constexpr const Uint32 ResourceTypeBits = 3; - static constexpr const Uint32 VariableTypeBits = 2; - static constexpr const Uint32 RootIndexBits = 16 - ResourceTypeBits - VariableTypeBits; - - static constexpr const Uint32 InvalidRootIndex = (1 << RootIndexBits) - 1; - static constexpr const Uint32 MaxRootIndex = InvalidRootIndex - 1; - - static constexpr const Uint32 InvalidSamplerId = 0xFFFF; - static constexpr const Uint32 MaxSamplerId = InvalidSamplerId-1; - static constexpr const Uint32 InvalidOffset = static_cast(-1); - - static_assert( SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES < (1 << VariableTypeBits), "2 bits is not enough to store SHADER_RESOURCE_VARIABLE_TYPE"); - static_assert( static_cast(CachedResourceType::NumTypes) < (1 << ResourceTypeBits), "3 bits is not enough to store CachedResourceType"); - -/* 0 */ const ShaderResourceLayoutD3D12& ParentResLayout; -/* 8 */ const D3DShaderResourceAttribs& Attribs; -/*16 */ const Uint32 OffsetFromTableStart; -/*20.0*/ const Uint16 ResourceType : ResourceTypeBits; // | 0 1 2 | -/*20.3*/ const Uint16 VariableType : VariableTypeBits; // | 3 4 | -/*20.5*/ const Uint16 RootIndex : RootIndexBits; // | 5 6 7 ... 15 | -/*22 */ const Uint16 SamplerId; -/*24 */ // End of data - - // clang-format on - - D3D12Resource(const ShaderResourceLayoutD3D12& _ParentLayout, - const D3DShaderResourceAttribs& _Attribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - CachedResourceType _ResType, - Uint32 _RootIndex, - Uint32 _OffsetFromTableStart, - Uint32 _SamplerId) noexcept : - // clang-format off - ParentResLayout {_ParentLayout }, - Attribs {_Attribs }, - ResourceType {static_cast(_ResType) }, - VariableType {static_cast(_VariableType)}, - RootIndex {static_cast(_RootIndex) }, - SamplerId {static_cast(_SamplerId) }, - OffsetFromTableStart{ _OffsetFromTableStart } - // clang-format on - { - VERIFY(IsValidOffset(), "Offset must be valid"); - VERIFY(IsValidRootIndex(), "Root index must be valid"); - VERIFY(_RootIndex <= MaxRootIndex, "Root index (", _RootIndex, ") exceeds max allowed value (", MaxRootIndex, ")"); - VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of representable range"); - VERIFY(_SamplerId == InvalidSamplerId || _SamplerId <= MaxSamplerId, "Sampler id (", _SamplerId, ") exceeds max allowed value (", MaxSamplerId, ")"); - VERIFY(_SamplerId == InvalidSamplerId || GetResType() == CachedResourceType::TexSRV, "A sampler can only be assigned to a Texture SRV"); - } - - bool IsBound(Uint32 ArrayIndex, - const ShaderResourceCacheD3D12& ResourceCache) const; - - void BindResource(IDeviceObject* pObject, - Uint32 ArrayIndex, - ShaderResourceCacheD3D12& ResourceCache) const; - - // clang-format off - bool ValidSamplerAssigned()const { return SamplerId != InvalidSamplerId; } - bool IsValidRootIndex() const { return RootIndex != InvalidRootIndex; } - bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } - // clang-format on - - CachedResourceType GetResType() const { return static_cast(ResourceType); } - SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const { return static_cast(VariableType); } - - private: - void CacheCB(IDeviceObject* pBuffer, - ShaderResourceCacheD3D12::Resource& DstRes, - Uint32 ArrayInd, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, - Uint32& BoundDynamicCBsCounter) const; - - template - void CacheResourceView(IDeviceObject* pView, - ShaderResourceCacheD3D12::Resource& DstRes, - Uint32 ArrayIndex, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, - TViewTypeEnum dbgExpectedViewType, - TBindSamplerProcType BindSamplerProc) const; - - void CacheSampler(IDeviceObject* pSampler, - ShaderResourceCacheD3D12::Resource& DstSam, - Uint32 ArrayIndex, - D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const; - }; - - void CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, - const ShaderResourceLayoutD3D12& DstLayout, - ShaderResourceCacheD3D12& DstCache) const; - -#ifdef DEVELOPMENT - bool dvpVerifyBindings(const ShaderResourceCacheD3D12& ResourceCache) const; -#endif - - IObject& GetOwner() - { - return m_Owner; - } - - Uint32 GetCbvSrvUavCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const - { - return m_CbvSrvUavOffsets[VarType + 1] - m_CbvSrvUavOffsets[VarType]; - } - Uint32 GetSamplerCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const - { - return m_SamplersOffsets[VarType + 1] - m_SamplersOffsets[VarType]; - } - - const D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const - { - VERIFY_EXPR(r < GetCbvSrvUavCount(VarType)); - return GetResource(GetSrvCbvUavOffset(VarType, r)); - } - const D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const - { - VERIFY_EXPR(s < GetSamplerCount(VarType)); - return GetResource(GetSamplerOffset(VarType, s)); - } - - const bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedTextureSamplers(); } - - SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } - -private: - const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const; - D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv); - - const Char* GetShaderName() const - { - return m_pResources->GetShaderName(); - } - - - Uint32 GetTotalSrvCbvUavCount() const - { - VERIFY_EXPR(m_CbvSrvUavOffsets[0] == 0); - return m_CbvSrvUavOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; - } - Uint32 GetTotalSamplerCount() const - { - return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] - m_SamplersOffsets[0]; - } - Uint32 GetTotalResourceCount() const - { - return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; - } - - D3D12Resource& GetResource(Uint32 r) - { - VERIFY_EXPR(r < GetTotalResourceCount()); - auto* Resource = reinterpret_cast(m_ResourceBuffer.get()); - return Resource[r]; - } - const D3D12Resource& GetResource(Uint32 r) const - { - VERIFY_EXPR(r < GetTotalResourceCount()); - auto* Resource = reinterpret_cast(m_ResourceBuffer.get()); - return Resource[r]; - } - - Uint32 GetSrvCbvUavOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const - { - Uint32 Offset = m_CbvSrvUavOffsets[VarType] + r; - VERIFY_EXPR(Offset < m_CbvSrvUavOffsets[VarType + 1]); - return Offset; - } - D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) - { - VERIFY_EXPR(r < GetCbvSrvUavCount(VarType)); - return GetResource(GetSrvCbvUavOffset(VarType, r)); - } - - Uint32 GetSamplerOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const - { - auto Offset = m_SamplersOffsets[VarType] + s; - VERIFY_EXPR(Offset < m_SamplersOffsets[VarType + 1]); - return Offset; - } - D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) - { - VERIFY_EXPR(s < GetSamplerCount(VarType)); - return GetResource(GetSamplerOffset(VarType, s)); - } - const D3D12Resource& GetSampler(Uint32 s) const - { - VERIFY_EXPR(s < GetTotalSamplerCount()); - return GetResource(m_SamplersOffsets[0] + s); - } - - void AllocateMemory(IMemoryAllocator& Allocator, - const std::array& CbvSrvUavCount, - const std::array& SamplerCount); - // clang-format off - -/* 0 */ std::unique_ptr > m_ResourceBuffer; -/* 16 */ std::array m_CbvSrvUavOffsets = {}; -/* 24 */ std::array m_SamplersOffsets = {}; - -/* 32 */ IObject& m_Owner; -/* 48 */ CComPtr m_pd3d12Device; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources -/* 48 */ std::shared_ptr m_pResources; -/* 64 */ // End of data - - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp new file mode 100644 index 00000000..56889271 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp @@ -0,0 +1,360 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourceLayoutD3D12 class + +// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout/ + +// All resources are stored in a single continuous chunk of memory using the following layout: +// +// m_ResourceBuffer +// | | | +// | D3D12Resource[0] ... | D3D12Resource[s] ... | D3D12Resource[s+m] ... | D3D12Resource[smd] ... | D3D12Resource[smd+s'] ... | D3D12Resource[smd+s'+m'] ... D3D12Resource[s+m+d+s'+m'+d'-1] || +// | | | | | | || +// | SRV/CBV/UAV - STATIC | SRV/CBV/UAV - MUTABLE | SRV/CBV/UAV - DYNAMIC | Samplers - STATIC | Samplers - MUTABLE | Samplers - DYNAMIC || +// | | | | +// +// s == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] +// m == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] +// d == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] +// smd = s+m+d +// +// s' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] +// m' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] +// d' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] +// +// Every D3D12Resource structure holds a reference to D3DShaderResourceAttribs structure from ShaderResourcesD3D12. +// ShaderResourceLayoutD3D12 holds shared pointer to ShaderResourcesD3D12 instance. Note that ShaderResourcesD3D12::SamplerId +// references a sampler in ShaderResourcesD3D12, while D3D12Resource::SamplerId references a sampler in ShaderResourceLayoutD3D12, +// and the two are not necessarily the same +// +// +// ________________SamplerId____________________ +// | | +// _____________________ ______________|_____________________________________________V________ +// | | unique_ptr | | | | | | | +// |ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |_____________________| |________|___________|___________|___________|___________|____________| +// A A A A +// | \ / \ +// |shared_ptr Ref Ref Ref +// ________|__________________ ________\________________________/_________________________\________________________________________________ +// | | unique_ptr | | | | | | | +// | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[smd] | D3D12Resource[smd+1] | ... | +// |___________________________| |__________________|__________________|_______________|____________________|______________________|__________| +// A A | A A +// | \ |______________\____SamplerId________________________| +// | \ \ +// | Ref Ref +// | \ \_____ +// | \ \ +// ____________|_______________ ________\_______________________\__________________________________________ +// | | | | | | +// | ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | +// |____________________________| |____________________________|____________________________|_________________| + +// +// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Figure2 +// Resources in the resource cache are identified by the root index and offset in the descriptor table +// +// +// ShaderResourceLayoutD3D12 is used as follows: +// * Every pipeline state object (PipelineStateD3D12Impl) maintains shader resource layout for every active shader stage +// ** These resource layouts are used as reference layouts for shader resource binding objects +// ** All variable types are preserved +// ** Root indices and descriptor table offsets are assigned during the initialization +// * Every pipeline state object also contains shader resource layout that facilitates management of static shader resources +// ** The resource layout defines artificial layout where root index matches the resource type (CBV/SRV/UAV/SAM) +// ** Only static variables are referenced +// +// * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader variable +// manager (ShaderVariableManagerD3D12) for every active shader stage in the parent pipeline state that +// handles mutable and dynamic resources + +#include + +#include "ShaderBase.hpp" +#include "ShaderResourcesD3D12.hpp" +#include "ShaderResourceCacheD3D12.hpp" + +namespace Diligent +{ + +/// Diligent::ShaderResourceLayoutD3D12 class +// sizeof(ShaderResourceLayoutD3D12) == 64 (MS compiler, x64) +class ShaderResourceLayoutD3D12 final +{ +public: + // There are two modes a layout can be constructed: + // - initialize static resource layout and initialize shader resource cache to hold static resources + // - initialize reference layouts that address all types of resources (static, mutable, dynamic). + // Root indices and descriptor table offsets are assigned during the initialization; + // no shader resource cache is provided + ShaderResourceLayoutD3D12(IObject& Owner, + ID3D12Device* pd3d12Device, + const PipelineResourceLayoutDesc& ResourceLayout, + std::shared_ptr pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + class RootSignature* pRootSig); + + // clang-format off + ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; + ShaderResourceLayoutD3D12 (ShaderResourceLayoutD3D12&&) = delete; + ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete; + ShaderResourceLayoutD3D12& operator =(ShaderResourceLayoutD3D12&&) = delete; + // clang-format on + + ~ShaderResourceLayoutD3D12(); + + // sizeof(D3D12Resource) == 24 (x64) + struct D3D12Resource final + { + // clang-format off + + D3D12Resource (const D3D12Resource&) = delete; + D3D12Resource ( D3D12Resource&&) = delete; + D3D12Resource& operator = (const D3D12Resource&) = delete; + D3D12Resource& operator = ( D3D12Resource&&) = delete; + + static constexpr const Uint32 ResourceTypeBits = 3; + static constexpr const Uint32 VariableTypeBits = 2; + static constexpr const Uint32 RootIndexBits = 16 - ResourceTypeBits - VariableTypeBits; + + static constexpr const Uint32 InvalidRootIndex = (1 << RootIndexBits) - 1; + static constexpr const Uint32 MaxRootIndex = InvalidRootIndex - 1; + + static constexpr const Uint32 InvalidSamplerId = 0xFFFF; + static constexpr const Uint32 MaxSamplerId = InvalidSamplerId-1; + static constexpr const Uint32 InvalidOffset = static_cast(-1); + + static_assert( SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES < (1 << VariableTypeBits), "2 bits is not enough to store SHADER_RESOURCE_VARIABLE_TYPE"); + static_assert( static_cast(CachedResourceType::NumTypes) < (1 << ResourceTypeBits), "3 bits is not enough to store CachedResourceType"); + +/* 0 */ const ShaderResourceLayoutD3D12& ParentResLayout; +/* 8 */ const D3DShaderResourceAttribs& Attribs; +/*16 */ const Uint32 OffsetFromTableStart; +/*20.0*/ const Uint16 ResourceType : ResourceTypeBits; // | 0 1 2 | +/*20.3*/ const Uint16 VariableType : VariableTypeBits; // | 3 4 | +/*20.5*/ const Uint16 RootIndex : RootIndexBits; // | 5 6 7 ... 15 | +/*22 */ const Uint16 SamplerId; +/*24 */ // End of data + + // clang-format on + + D3D12Resource(const ShaderResourceLayoutD3D12& _ParentLayout, + const D3DShaderResourceAttribs& _Attribs, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + CachedResourceType _ResType, + Uint32 _RootIndex, + Uint32 _OffsetFromTableStart, + Uint32 _SamplerId) noexcept : + // clang-format off + ParentResLayout {_ParentLayout }, + Attribs {_Attribs }, + ResourceType {static_cast(_ResType) }, + VariableType {static_cast(_VariableType)}, + RootIndex {static_cast(_RootIndex) }, + SamplerId {static_cast(_SamplerId) }, + OffsetFromTableStart{ _OffsetFromTableStart } + // clang-format on + { + VERIFY(IsValidOffset(), "Offset must be valid"); + VERIFY(IsValidRootIndex(), "Root index must be valid"); + VERIFY(_RootIndex <= MaxRootIndex, "Root index (", _RootIndex, ") exceeds max allowed value (", MaxRootIndex, ")"); + VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of representable range"); + VERIFY(_SamplerId == InvalidSamplerId || _SamplerId <= MaxSamplerId, "Sampler id (", _SamplerId, ") exceeds max allowed value (", MaxSamplerId, ")"); + VERIFY(_SamplerId == InvalidSamplerId || GetResType() == CachedResourceType::TexSRV, "A sampler can only be assigned to a Texture SRV"); + } + + bool IsBound(Uint32 ArrayIndex, + const ShaderResourceCacheD3D12& ResourceCache) const; + + void BindResource(IDeviceObject* pObject, + Uint32 ArrayIndex, + ShaderResourceCacheD3D12& ResourceCache) const; + + // clang-format off + bool ValidSamplerAssigned()const { return SamplerId != InvalidSamplerId; } + bool IsValidRootIndex() const { return RootIndex != InvalidRootIndex; } + bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } + // clang-format on + + CachedResourceType GetResType() const { return static_cast(ResourceType); } + SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const { return static_cast(VariableType); } + + private: + void CacheCB(IDeviceObject* pBuffer, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayInd, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, + Uint32& BoundDynamicCBsCounter) const; + + template + void CacheResourceView(IDeviceObject* pView, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, + TViewTypeEnum dbgExpectedViewType, + TBindSamplerProcType BindSamplerProc) const; + + void CacheSampler(IDeviceObject* pSampler, + ShaderResourceCacheD3D12::Resource& DstSam, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const; + }; + + void CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, + const ShaderResourceLayoutD3D12& DstLayout, + ShaderResourceCacheD3D12& DstCache) const; + +#ifdef DEVELOPMENT + bool dvpVerifyBindings(const ShaderResourceCacheD3D12& ResourceCache) const; +#endif + + IObject& GetOwner() + { + return m_Owner; + } + + Uint32 GetCbvSrvUavCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const + { + return m_CbvSrvUavOffsets[VarType + 1] - m_CbvSrvUavOffsets[VarType]; + } + Uint32 GetSamplerCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const + { + return m_SamplersOffsets[VarType + 1] - m_SamplersOffsets[VarType]; + } + + const D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const + { + VERIFY_EXPR(r < GetCbvSrvUavCount(VarType)); + return GetResource(GetSrvCbvUavOffset(VarType, r)); + } + const D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const + { + VERIFY_EXPR(s < GetSamplerCount(VarType)); + return GetResource(GetSamplerOffset(VarType, s)); + } + + const bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedTextureSamplers(); } + + SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } + +private: + const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const; + D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv); + + const Char* GetShaderName() const + { + return m_pResources->GetShaderName(); + } + + + Uint32 GetTotalSrvCbvUavCount() const + { + VERIFY_EXPR(m_CbvSrvUavOffsets[0] == 0); + return m_CbvSrvUavOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; + } + Uint32 GetTotalSamplerCount() const + { + return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] - m_SamplersOffsets[0]; + } + Uint32 GetTotalResourceCount() const + { + return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; + } + + D3D12Resource& GetResource(Uint32 r) + { + VERIFY_EXPR(r < GetTotalResourceCount()); + auto* Resource = reinterpret_cast(m_ResourceBuffer.get()); + return Resource[r]; + } + const D3D12Resource& GetResource(Uint32 r) const + { + VERIFY_EXPR(r < GetTotalResourceCount()); + auto* Resource = reinterpret_cast(m_ResourceBuffer.get()); + return Resource[r]; + } + + Uint32 GetSrvCbvUavOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const + { + Uint32 Offset = m_CbvSrvUavOffsets[VarType] + r; + VERIFY_EXPR(Offset < m_CbvSrvUavOffsets[VarType + 1]); + return Offset; + } + D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) + { + VERIFY_EXPR(r < GetCbvSrvUavCount(VarType)); + return GetResource(GetSrvCbvUavOffset(VarType, r)); + } + + Uint32 GetSamplerOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const + { + auto Offset = m_SamplersOffsets[VarType] + s; + VERIFY_EXPR(Offset < m_SamplersOffsets[VarType + 1]); + return Offset; + } + D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) + { + VERIFY_EXPR(s < GetSamplerCount(VarType)); + return GetResource(GetSamplerOffset(VarType, s)); + } + const D3D12Resource& GetSampler(Uint32 s) const + { + VERIFY_EXPR(s < GetTotalSamplerCount()); + return GetResource(m_SamplersOffsets[0] + s); + } + + void AllocateMemory(IMemoryAllocator& Allocator, + const std::array& CbvSrvUavCount, + const std::array& SamplerCount); + // clang-format off + +/* 0 */ std::unique_ptr > m_ResourceBuffer; +/* 16 */ std::array m_CbvSrvUavOffsets = {}; +/* 24 */ std::array m_SamplersOffsets = {}; + +/* 32 */ IObject& m_Owner; +/* 48 */ CComPtr m_pd3d12Device; + // We must use shared_ptr to reference ShaderResources instance, because + // there may be multiple objects referencing the same set of resources +/* 48 */ std::shared_ptr m_pResources; +/* 64 */ // End of data + + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h deleted file mode 100644 index e9672d10..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResourcesD3D12 class - -// ShaderResourcesD3D12 are created by ShaderD3D12Impl instances. They are then referenced by ShaderResourceLayoutD3D12 objects, which are in turn -// created by instances of PipelineStatesD3D12Impl and ShaderD3D12Impl -// -// _________________ -// | | -// | ShaderD3D12Impl | -// |_________________| -// | -// |shared_ptr -// ________V_____________ _____________________________________________________________________ -// | | unique_ptr | | | | | | | -// | ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | -// |______________________| |________|___________|___________|___________|___________|____________| -// A A A A -// | \ / \ -// |shared_ptr Ref Ref Ref -// ________|__________________ ________\________________________/_________________________\_________________________________________ -// | | unique_ptr | | | | | | | -// | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... | -// |___________________________| |___________________|_________________|_______________|__________________|_________________|__________| -// A | A -// | |___________________SamplerId________________________| -// | -// __________|_____________ -// | | -// | PipelineStateD3D12Impl | -// |________________________| -// -// -// -// One ShaderResourcesD3D12 instance can be referenced by multiple objects -// -// -// ________________________ __ __________ ________________________________ -// | | | | | | | | -// | PipelineStateD3D12Impl |========>| ShaderResourceLayoutD3D12 |<-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | -// |________________________| |____________________________| |____________________________| |________________________________| -// | A -// |shared_ptr \ -// _________________ ___________V__________ \ __________ ________________________________ -// | | shared_ptr | | \ | | | | -// | ShaderD3D12Impl |---------------->| ShaderResourcesD3D12 | '-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | -// |_________________| |______________________| |____________________________| |________________________________| -// | |___________________ A -// | | | -// V V |shared_ptr -// ___________ ____|___ -// | | | | -// | ShaderVariableManagerD3D12 |------>| ShaderResourceLayoutD3D12 | -// |____________________________| |___________________________| -// - -#include "ShaderResources.h" - -namespace Diligent -{ - -/// Diligent::ShaderResourcesD3D12 class -class ShaderResourcesD3D12 final : public ShaderResources -{ -public: - // Loads shader resources from the compiled shader bytecode - ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix); - - // clang-format off - ShaderResourcesD3D12 (const ShaderResourcesD3D12&) = delete; - ShaderResourcesD3D12 ( ShaderResourcesD3D12&&) = delete; - ShaderResourcesD3D12& operator = (const ShaderResourcesD3D12&) = delete; - ShaderResourcesD3D12& operator = ( ShaderResourcesD3D12&&) = delete; - // clang-format on -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp new file mode 100644 index 00000000..23f9882b --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp @@ -0,0 +1,105 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResourcesD3D12 class + +// ShaderResourcesD3D12 are created by ShaderD3D12Impl instances. They are then referenced by ShaderResourceLayoutD3D12 objects, which are in turn +// created by instances of PipelineStatesD3D12Impl and ShaderD3D12Impl +// +// _________________ +// | | +// | ShaderD3D12Impl | +// |_________________| +// | +// |shared_ptr +// ________V_____________ _____________________________________________________________________ +// | | unique_ptr | | | | | | | +// | ShaderResourcesD3D12 |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | +// |______________________| |________|___________|___________|___________|___________|____________| +// A A A A +// | \ / \ +// |shared_ptr Ref Ref Ref +// ________|__________________ ________\________________________/_________________________\_________________________________________ +// | | unique_ptr | | | | | | | +// | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... | +// |___________________________| |___________________|_________________|_______________|__________________|_________________|__________| +// A | A +// | |___________________SamplerId________________________| +// | +// __________|_____________ +// | | +// | PipelineStateD3D12Impl | +// |________________________| +// +// +// +// One ShaderResourcesD3D12 instance can be referenced by multiple objects +// +// +// ________________________ __ __________ ________________________________ +// | | | | | | | | +// | PipelineStateD3D12Impl |========>| ShaderResourceLayoutD3D12 |<-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | +// |________________________| |____________________________| |____________________________| |________________________________| +// | A +// |shared_ptr \ +// _________________ ___________V__________ \ __________ ________________________________ +// | | shared_ptr | | \ | | | | +// | ShaderD3D12Impl |---------------->| ShaderResourcesD3D12 | '-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl | +// |_________________| |______________________| |____________________________| |________________________________| +// | |___________________ A +// | | | +// V V |shared_ptr +// ___________ ____|___ +// | | | | +// | ShaderVariableManagerD3D12 |------>| ShaderResourceLayoutD3D12 | +// |____________________________| |___________________________| +// + +#include "ShaderResources.hpp" + +namespace Diligent +{ + +/// Diligent::ShaderResourcesD3D12 class +class ShaderResourcesD3D12 final : public ShaderResources +{ +public: + // Loads shader resources from the compiled shader bytecode + ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix); + + // clang-format off + ShaderResourcesD3D12 (const ShaderResourcesD3D12&) = delete; + ShaderResourcesD3D12 ( ShaderResourcesD3D12&&) = delete; + ShaderResourcesD3D12& operator = (const ShaderResourcesD3D12&) = delete; + ShaderResourcesD3D12& operator = ( ShaderResourcesD3D12&&) = delete; + // clang-format on +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h deleted file mode 100644 index f7a1f8c8..00000000 --- a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderVariableManagerD3D12 and Diligent::ShaderVariableD3D12Impl classes - -// -// * ShaderVariableManagerD3D12 keeps list of variables of specific types -// * Every ShaderVariableD3D12Impl references D3D12Resource from ShaderResourceLayoutD3D12 -// * ShaderVariableManagerD3D12 keeps pointer to ShaderResourceCacheD3D12 -// * ShaderVariableManagerD3D12 is used by PipelineStateD3D12Impl to manage static resources and by -// ShaderResourceBindingD3D12Impl to manage mutable and dynamic resources -// -// _____________________________ ________________________________________________________________________________ -// | | | | | | -// .----| ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | -// | |_____________________________| |______________________________|_______________________________|_________________| -// | | \ | -// | | Ref Ref -// | | \ | -// | ___________V_______________ ______________________V_______________________V_____________________________ -// | | | unique_ptr | | | | | -// | | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[s+m+d-1] | -// | |___________________________| |__________________|__________________|_____________|________________________| -// | | | -// | | | -// | | (RootTable, Offset) / (RootTable, Offset) -// | \ / -// | __________________________ ________V_______________________________________________________V_______ -// | | | | | -// '--->| ShaderResourceCacheD3D12 |---------------->| Resources | -// |__________________________| |________________________________________________________________________| -// -// Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block -// memory allocator is used. This ensures that all resources from different shader resource bindings reside in -// continuous memory. If allocation granularity == 1, raw allocator is used. - -#include - -#include "ShaderResourceVariableD3D.h" -#include "ShaderResourceLayoutD3D12.h" -#include "ShaderResourceVariableBase.h" - -namespace Diligent -{ - -class ShaderVariableD3D12Impl; - -// sizeof(ShaderVariableManagerD3D12) == 32 (x64, msvc, Release) -class ShaderVariableManagerD3D12 -{ -public: - ShaderVariableManagerD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& Layout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache); - ~ShaderVariableManagerD3D12(); - - void Destroy(IMemoryAllocator& Allocator); - - ShaderVariableD3D12Impl* GetVariable(const Char* Name); - ShaderVariableD3D12Impl* GetVariable(Uint32 Index); - - void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); - - static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& Layout, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumVariables); - - Uint32 GetVariableCount() const { return m_NumVariables; } - -private: - friend ShaderVariableD3D12Impl; - - Uint32 GetVariableIndex(const ShaderVariableD3D12Impl& Variable); - - // clang-format off - - IObject& m_Owner; - - // Variable mgr is owned by either Pipeline state object (in which case m_ResourceCache references - // static resource cache owned by the same PSO object), or by SRB object (in which case - // m_ResourceCache references the cache in the SRB). Thus the cache and the resource layout - // (which the variables reference) are guaranteed to be alive while the manager is alive. - ShaderResourceCacheD3D12& m_ResourceCache; - - // Memory is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block - // memory allocator is used. This ensures that all resources from different shader resource bindings reside in - // continuous memory. If allocation granularity == 1, raw allocator is used. - ShaderVariableD3D12Impl* m_pVariables = nullptr; - Uint32 m_NumVariables = 0; - -#ifdef _DEBUG - IMemoryAllocator& m_DbgAllocator; -#endif - // clang-format on -}; - -// sizeof(ShaderVariableD3D12Impl) == 24 (x64) -class ShaderVariableD3D12Impl final : public IShaderResourceVariableD3D -{ -public: - ShaderVariableD3D12Impl(ShaderVariableManagerD3D12& ParentManager, - const ShaderResourceLayoutD3D12::D3D12Resource& Resource) : - m_ParentManager{ParentManager}, - m_Resource{Resource} - {} - - // clang-format off - ShaderVariableD3D12Impl (const ShaderVariableD3D12Impl&) = delete; - ShaderVariableD3D12Impl (ShaderVariableD3D12Impl&&) = delete; - ShaderVariableD3D12Impl& operator= (const ShaderVariableD3D12Impl&) = delete; - ShaderVariableD3D12Impl& operator= (ShaderVariableD3D12Impl&&) = delete; - // clang-format on - - virtual IReferenceCounters* GetReferenceCounters() const override final - { - return m_ParentManager.m_Owner.GetReferenceCounters(); - } - - virtual Atomics::Long AddRef() override final - { - return m_ParentManager.m_Owner.AddRef(); - } - - virtual Atomics::Long Release() override final - { - return m_ParentManager.m_Owner.Release(); - } - - void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final - { - if (ppInterface == nullptr) - return; - - *ppInterface = nullptr; - if (IID == IID_ShaderResourceVariableD3D || IID == IID_ShaderResourceVariable || IID == IID_Unknown) - { - *ppInterface = this; - (*ppInterface)->AddRef(); - } - } - - virtual SHADER_RESOURCE_VARIABLE_TYPE GetType() const override final - { - return m_Resource.GetVariableType(); - } - - virtual void Set(IDeviceObject* pObject) override final - { - m_Resource.BindResource(pObject, 0, m_ParentManager.m_ResourceCache); - } - - virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Resource.Attribs.Name, m_Resource.Attribs.BindCount, FirstElement, NumElements); - for (Uint32 Elem = 0; Elem < NumElements; ++Elem) - m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); - } - - virtual void GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final - { - ResourceDesc = GetHLSLResourceDesc(); - } - - virtual HLSLShaderResourceDesc GetHLSLResourceDesc() const override final - { - return m_Resource.Attribs.GetHLSLResourceDesc(); - } - - virtual Uint32 GetIndex() const override final - { - return m_ParentManager.GetVariableIndex(*this); - } - - virtual bool IsBound(Uint32 ArrayIndex) const override final - { - return m_Resource.IsBound(ArrayIndex, m_ParentManager.m_ResourceCache); - } - - const ShaderResourceLayoutD3D12::D3D12Resource& GetResource() const - { - return m_Resource; - } - -private: - friend ShaderVariableManagerD3D12; - - ShaderVariableManagerD3D12& m_ParentManager; - const ShaderResourceLayoutD3D12::D3D12Resource& m_Resource; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp new file mode 100644 index 00000000..749de7f2 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp @@ -0,0 +1,222 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderVariableManagerD3D12 and Diligent::ShaderVariableD3D12Impl classes + +// +// * ShaderVariableManagerD3D12 keeps list of variables of specific types +// * Every ShaderVariableD3D12Impl references D3D12Resource from ShaderResourceLayoutD3D12 +// * ShaderVariableManagerD3D12 keeps pointer to ShaderResourceCacheD3D12 +// * ShaderVariableManagerD3D12 is used by PipelineStateD3D12Impl to manage static resources and by +// ShaderResourceBindingD3D12Impl to manage mutable and dynamic resources +// +// _____________________________ ________________________________________________________________________________ +// | | | | | | +// .----| ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... | +// | |_____________________________| |______________________________|_______________________________|_________________| +// | | \ | +// | | Ref Ref +// | | \ | +// | ___________V_______________ ______________________V_______________________V_____________________________ +// | | | unique_ptr | | | | | +// | | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[s+m+d-1] | +// | |___________________________| |__________________|__________________|_____________|________________________| +// | | | +// | | | +// | | (RootTable, Offset) / (RootTable, Offset) +// | \ / +// | __________________________ ________V_______________________________________________________V_______ +// | | | | | +// '--->| ShaderResourceCacheD3D12 |---------------->| Resources | +// |__________________________| |________________________________________________________________________| +// +// Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block +// memory allocator is used. This ensures that all resources from different shader resource bindings reside in +// continuous memory. If allocation granularity == 1, raw allocator is used. + +#include + +#include "ShaderResourceVariableD3D.h" +#include "ShaderResourceLayoutD3D12.hpp" +#include "ShaderResourceVariableBase.hpp" + +namespace Diligent +{ + +class ShaderVariableD3D12Impl; + +// sizeof(ShaderVariableManagerD3D12) == 32 (x64, msvc, Release) +class ShaderVariableManagerD3D12 +{ +public: + ShaderVariableManagerD3D12(IObject& Owner, + const ShaderResourceLayoutD3D12& Layout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12& ResourceCache); + ~ShaderVariableManagerD3D12(); + + void Destroy(IMemoryAllocator& Allocator); + + ShaderVariableD3D12Impl* GetVariable(const Char* Name); + ShaderVariableD3D12Impl* GetVariable(Uint32 Index); + + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); + + static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& Layout, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables); + + Uint32 GetVariableCount() const { return m_NumVariables; } + +private: + friend ShaderVariableD3D12Impl; + + Uint32 GetVariableIndex(const ShaderVariableD3D12Impl& Variable); + + // clang-format off + + IObject& m_Owner; + + // Variable mgr is owned by either Pipeline state object (in which case m_ResourceCache references + // static resource cache owned by the same PSO object), or by SRB object (in which case + // m_ResourceCache references the cache in the SRB). Thus the cache and the resource layout + // (which the variables reference) are guaranteed to be alive while the manager is alive. + ShaderResourceCacheD3D12& m_ResourceCache; + + // Memory is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block + // memory allocator is used. This ensures that all resources from different shader resource bindings reside in + // continuous memory. If allocation granularity == 1, raw allocator is used. + ShaderVariableD3D12Impl* m_pVariables = nullptr; + Uint32 m_NumVariables = 0; + +#ifdef _DEBUG + IMemoryAllocator& m_DbgAllocator; +#endif + // clang-format on +}; + +// sizeof(ShaderVariableD3D12Impl) == 24 (x64) +class ShaderVariableD3D12Impl final : public IShaderResourceVariableD3D +{ +public: + ShaderVariableD3D12Impl(ShaderVariableManagerD3D12& ParentManager, + const ShaderResourceLayoutD3D12::D3D12Resource& Resource) : + m_ParentManager{ParentManager}, + m_Resource{Resource} + {} + + // clang-format off + ShaderVariableD3D12Impl (const ShaderVariableD3D12Impl&) = delete; + ShaderVariableD3D12Impl (ShaderVariableD3D12Impl&&) = delete; + ShaderVariableD3D12Impl& operator= (const ShaderVariableD3D12Impl&) = delete; + ShaderVariableD3D12Impl& operator= (ShaderVariableD3D12Impl&&) = delete; + // clang-format on + + virtual IReferenceCounters* GetReferenceCounters() const override final + { + return m_ParentManager.m_Owner.GetReferenceCounters(); + } + + virtual Atomics::Long AddRef() override final + { + return m_ParentManager.m_Owner.AddRef(); + } + + virtual Atomics::Long Release() override final + { + return m_ParentManager.m_Owner.Release(); + } + + void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final + { + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (IID == IID_ShaderResourceVariableD3D || IID == IID_ShaderResourceVariable || IID == IID_Unknown) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } + } + + virtual SHADER_RESOURCE_VARIABLE_TYPE GetType() const override final + { + return m_Resource.GetVariableType(); + } + + virtual void Set(IDeviceObject* pObject) override final + { + m_Resource.BindResource(pObject, 0, m_ParentManager.m_ResourceCache); + } + + virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final + { + VerifyAndCorrectSetArrayArguments(m_Resource.Attribs.Name, m_Resource.Attribs.BindCount, FirstElement, NumElements); + for (Uint32 Elem = 0; Elem < NumElements; ++Elem) + m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); + } + + virtual void GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final + { + ResourceDesc = GetHLSLResourceDesc(); + } + + virtual HLSLShaderResourceDesc GetHLSLResourceDesc() const override final + { + return m_Resource.Attribs.GetHLSLResourceDesc(); + } + + virtual Uint32 GetIndex() const override final + { + return m_ParentManager.GetVariableIndex(*this); + } + + virtual bool IsBound(Uint32 ArrayIndex) const override final + { + return m_Resource.IsBound(ArrayIndex, m_ParentManager.m_ResourceCache); + } + + const ShaderResourceLayoutD3D12::D3D12Resource& GetResource() const + { + return m_Resource; + } + +private: + friend ShaderVariableManagerD3D12; + + ShaderVariableManagerD3D12& m_ParentManager; + const ShaderResourceLayoutD3D12::D3D12Resource& m_Resource; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h deleted file mode 100644 index 1b833029..00000000 --- a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::SwapChainD3D12Impl class - -#include -#include "SwapChainD3D12.h" -#include "SwapChainD3DBase.h" - -namespace Diligent -{ - -class ITextureViewD3D12; -class IMemoryAllocator; - -/// Swap chain implementation in Direct3D12 backend. -class SwapChainD3D12Impl final : public SwapChainD3DBase -{ -public: - using TSwapChainBase = SwapChainD3DBase; - - SwapChainD3D12Impl(IReferenceCounters* pRefCounters, - const SwapChainDesc& SwapChainDesc, - const FullScreenModeDesc& FSDesc, - class RenderDeviceD3D12Impl* pRenderDeviceD3D12, - class DeviceContextD3D12Impl* pDeviceContextD3D12, - void* pNativeWndHandle); - ~SwapChainD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ISwapChain::Present() in Direct3D12 backend. - virtual void Present(Uint32 SyncInterval) override final; - - /// Implementation of ISwapChain::Resize() in Direct3D12 backend. - virtual void Resize(Uint32 NewWidth, Uint32 NewHeight) override final; - - /// Implementation of ISwapChainD3D12::GetDXGISwapChain(). - virtual IDXGISwapChain* GetDXGISwapChain() override final { return m_pSwapChain; } - - /// Implementation of ISwapChain::GetCurrentBackBufferRTV() in Direct3D12 backend. - virtual ITextureViewD3D12* GetCurrentBackBufferRTV() override final - { - auto CurrentBackBufferIndex = m_pSwapChain->GetCurrentBackBufferIndex(); - VERIFY_EXPR(CurrentBackBufferIndex >= 0 && CurrentBackBufferIndex < m_SwapChainDesc.BufferCount); - return m_pBackBufferRTV[CurrentBackBufferIndex]; - } - - /// Implementation of ISwapChain::GetDepthBufferDSV() in Direct3D12 backend. - virtual ITextureViewD3D12* GetDepthBufferDSV() override final { return m_pDepthBufferDSV; } - -private: - virtual void UpdateSwapChain(bool CreateNew) override final; - void InitBuffersAndViews(); - - std::vector, STDAllocatorRawMem>> m_pBackBufferRTV; - RefCntAutoPtr m_pDepthBufferDSV; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp new file mode 100644 index 00000000..0c45d915 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/SwapChainD3D12Impl.hpp @@ -0,0 +1,87 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::SwapChainD3D12Impl class + +#include +#include "SwapChainD3D12.h" +#include "SwapChainD3DBase.hpp" + +namespace Diligent +{ + +class ITextureViewD3D12; +class IMemoryAllocator; + +/// Swap chain implementation in Direct3D12 backend. +class SwapChainD3D12Impl final : public SwapChainD3DBase +{ +public: + using TSwapChainBase = SwapChainD3DBase; + + SwapChainD3D12Impl(IReferenceCounters* pRefCounters, + const SwapChainDesc& SwapChainDesc, + const FullScreenModeDesc& FSDesc, + class RenderDeviceD3D12Impl* pRenderDeviceD3D12, + class DeviceContextD3D12Impl* pDeviceContextD3D12, + void* pNativeWndHandle); + ~SwapChainD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ISwapChain::Present() in Direct3D12 backend. + virtual void Present(Uint32 SyncInterval) override final; + + /// Implementation of ISwapChain::Resize() in Direct3D12 backend. + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight) override final; + + /// Implementation of ISwapChainD3D12::GetDXGISwapChain(). + virtual IDXGISwapChain* GetDXGISwapChain() override final { return m_pSwapChain; } + + /// Implementation of ISwapChain::GetCurrentBackBufferRTV() in Direct3D12 backend. + virtual ITextureViewD3D12* GetCurrentBackBufferRTV() override final + { + auto CurrentBackBufferIndex = m_pSwapChain->GetCurrentBackBufferIndex(); + VERIFY_EXPR(CurrentBackBufferIndex >= 0 && CurrentBackBufferIndex < m_SwapChainDesc.BufferCount); + return m_pBackBufferRTV[CurrentBackBufferIndex]; + } + + /// Implementation of ISwapChain::GetDepthBufferDSV() in Direct3D12 backend. + virtual ITextureViewD3D12* GetDepthBufferDSV() override final { return m_pDepthBufferDSV; } + +private: + virtual void UpdateSwapChain(bool CreateNew) override final; + void InitBuffersAndViews(); + + std::vector, STDAllocatorRawMem>> m_pBackBufferRTV; + RefCntAutoPtr m_pDepthBufferDSV; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h deleted file mode 100644 index a4ab0b08..00000000 --- a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::TextureD3D12Impl class - -#include "TextureD3D12.h" -#include "RenderDeviceD3D12.h" -#include "TextureBase.h" -#include "TextureViewD3D12Impl.h" -#include "D3D12ResourceBase.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Implementation of a texture object in Direct3D12 backend. -class TextureD3D12Impl final : public TextureBase, public D3D12ResourceBase -{ -public: - using TTextureBase = TextureBase; - using ViewImplType = TextureViewD3D12Impl; - - // Creates a new D3D12 resource - TextureD3D12Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - RenderDeviceD3D12Impl* pDeviceD3D12, - const TextureDesc& TexDesc, - const TextureData* pInitData = nullptr); - - // Attaches to an existing D3D12 resource - TextureD3D12Impl(IReferenceCounters* pRefCounters, - FixedBlockMemoryAllocator& TexViewObjAllocator, - class RenderDeviceD3D12Impl* pDeviceD3D12, - const TextureDesc& TexDesc, - RESOURCE_STATE InitialState, - ID3D12Resource* pTexture); - ~TextureD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ITextureD3D12::GetD3D12Texture(). - virtual ID3D12Resource* GetD3D12Texture() override final { return GetD3D12Resource(); } - - /// Implementation of ITexture::GetNativeHandle() in Direct3D12 backend. - virtual void* GetNativeHandle() override final { return GetD3D12Texture(); } - - /// Implementation of ITextureD3D12::SetD3D12ResourceState(). - virtual void SetD3D12ResourceState(D3D12_RESOURCE_STATES state) override final; - - /// Implementation of ITextureD3D12::GetD3D12ResourceState(). - virtual D3D12_RESOURCE_STATES GetD3D12ResourceState() const override final; - - D3D12_RESOURCE_DESC GetD3D12TextureDesc() const; - - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& GetStagingFootprint(Uint32 Subresource) - { - VERIFY_EXPR(m_StagingFootprints != nullptr); - VERIFY_EXPR(Subresource <= (Uint32{m_Desc.MipLevels} * (m_Desc.Type == RESOURCE_DIM_TEX_3D ? 1 : Uint32{m_Desc.ArraySize}))); - return m_StagingFootprints[Subresource]; - } - -protected: - void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override final; - //void PrepareD3D12InitData(const TextureData &InitData, Uint32 NumSubresources, std::vector &D3D12InitData); - - void CreateSRV(TextureViewDesc& SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle); - void CreateRTV(TextureViewDesc& RTVDesc, D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle); - void CreateDSV(TextureViewDesc& DSVDesc, D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle); - void CreateUAV(TextureViewDesc& UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle); - - D3D12_PLACED_SUBRESOURCE_FOOTPRINT* m_StagingFootprints = nullptr; - - friend class RenderDeviceD3D12Impl; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.hpp new file mode 100644 index 00000000..7c1c041b --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.hpp @@ -0,0 +1,105 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::TextureD3D12Impl class + +#include "TextureD3D12.h" +#include "RenderDeviceD3D12.h" +#include "TextureBase.hpp" +#include "TextureViewD3D12Impl.hpp" +#include "D3D12ResourceBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Implementation of a texture object in Direct3D12 backend. +class TextureD3D12Impl final : public TextureBase, public D3D12ResourceBase +{ +public: + using TTextureBase = TextureBase; + using ViewImplType = TextureViewD3D12Impl; + + // Creates a new D3D12 resource + TextureD3D12Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + RenderDeviceD3D12Impl* pDeviceD3D12, + const TextureDesc& TexDesc, + const TextureData* pInitData = nullptr); + + // Attaches to an existing D3D12 resource + TextureD3D12Impl(IReferenceCounters* pRefCounters, + FixedBlockMemoryAllocator& TexViewObjAllocator, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const TextureDesc& TexDesc, + RESOURCE_STATE InitialState, + ID3D12Resource* pTexture); + ~TextureD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ITextureD3D12::GetD3D12Texture(). + virtual ID3D12Resource* GetD3D12Texture() override final { return GetD3D12Resource(); } + + /// Implementation of ITexture::GetNativeHandle() in Direct3D12 backend. + virtual void* GetNativeHandle() override final { return GetD3D12Texture(); } + + /// Implementation of ITextureD3D12::SetD3D12ResourceState(). + virtual void SetD3D12ResourceState(D3D12_RESOURCE_STATES state) override final; + + /// Implementation of ITextureD3D12::GetD3D12ResourceState(). + virtual D3D12_RESOURCE_STATES GetD3D12ResourceState() const override final; + + D3D12_RESOURCE_DESC GetD3D12TextureDesc() const; + + const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& GetStagingFootprint(Uint32 Subresource) + { + VERIFY_EXPR(m_StagingFootprints != nullptr); + VERIFY_EXPR(Subresource <= (Uint32{m_Desc.MipLevels} * (m_Desc.Type == RESOURCE_DIM_TEX_3D ? 1 : Uint32{m_Desc.ArraySize}))); + return m_StagingFootprints[Subresource]; + } + +protected: + void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override final; + //void PrepareD3D12InitData(const TextureData &InitData, Uint32 NumSubresources, std::vector &D3D12InitData); + + void CreateSRV(TextureViewDesc& SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle); + void CreateRTV(TextureViewDesc& RTVDesc, D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle); + void CreateDSV(TextureViewDesc& DSVDesc, D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle); + void CreateUAV(TextureViewDesc& UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle); + + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* m_StagingFootprints = nullptr; + + friend class RenderDeviceD3D12Impl; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h deleted file mode 100644 index fb8b7499..00000000 --- a/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::TextureViewD3D12Impl class - -#include "TextureViewD3D12.h" -#include "RenderDeviceD3D12.h" -#include "TextureViewBase.h" -#include "DescriptorHeap.h" -#include "RenderDeviceD3D12Impl.h" - -namespace Diligent -{ - -class FixedBlockMemoryAllocator; - -/// Texture view object implementation in Direct3D12 backend. -class TextureViewD3D12Impl final : public TextureViewBase -{ -public: - using TTextureViewBase = TextureViewBase; - - TextureViewD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDevice, - const TextureViewDesc& ViewDesc, - class ITexture* pTexture, - DescriptorHeapAllocation&& Descriptor, - DescriptorHeapAllocation&& TexArraySRVDescriptor, - DescriptorHeapAllocation&& MipLevelUAVDescriptors, - bool bIsDefaultView); - ~TextureViewD3D12Impl(); - - virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of ITextureViewD3D12::GetCPUDescriptorHandle(). - virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override final - { - return m_Descriptor.GetCpuHandle(); - } - - D3D12_CPU_DESCRIPTOR_HANDLE GetMipLevelUAV(Uint32 Mip) - { - VERIFY_EXPR((m_Desc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 && m_MipGenerationDescriptors != nullptr && Mip < m_Desc.NumMipLevels); - return m_MipGenerationDescriptors[1].GetCpuHandle(Mip); - } - - D3D12_CPU_DESCRIPTOR_HANDLE GetTexArraySRV() - { - VERIFY_EXPR((m_Desc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 && m_MipGenerationDescriptors != nullptr); - return m_MipGenerationDescriptors[0].GetCpuHandle(); - } - -protected: - /// D3D12 view descriptor handle - DescriptorHeapAllocation m_Descriptor; - - // Extra descriptors used for mipmap generation - // [0] == texture array SRV used for mipmap generation - // [1] == mip level UAVs used for mipmap generation - DescriptorHeapAllocation* m_MipGenerationDescriptors = nullptr; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.hpp new file mode 100644 index 00000000..2c2529ae --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/TextureViewD3D12Impl.hpp @@ -0,0 +1,90 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::TextureViewD3D12Impl class + +#include "TextureViewD3D12.h" +#include "RenderDeviceD3D12.h" +#include "TextureViewBase.hpp" +#include "DescriptorHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +class FixedBlockMemoryAllocator; + +/// Texture view object implementation in Direct3D12 backend. +class TextureViewD3D12Impl final : public TextureViewBase +{ +public: + using TTextureViewBase = TextureViewBase; + + TextureViewD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDevice, + const TextureViewDesc& ViewDesc, + class ITexture* pTexture, + DescriptorHeapAllocation&& Descriptor, + DescriptorHeapAllocation&& TexArraySRVDescriptor, + DescriptorHeapAllocation&& MipLevelUAVDescriptors, + bool bIsDefaultView); + ~TextureViewD3D12Impl(); + + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ITextureViewD3D12::GetCPUDescriptorHandle(). + virtual D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() override final + { + return m_Descriptor.GetCpuHandle(); + } + + D3D12_CPU_DESCRIPTOR_HANDLE GetMipLevelUAV(Uint32 Mip) + { + VERIFY_EXPR((m_Desc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 && m_MipGenerationDescriptors != nullptr && Mip < m_Desc.NumMipLevels); + return m_MipGenerationDescriptors[1].GetCpuHandle(Mip); + } + + D3D12_CPU_DESCRIPTOR_HANDLE GetTexArraySRV() + { + VERIFY_EXPR((m_Desc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 && m_MipGenerationDescriptors != nullptr); + return m_MipGenerationDescriptors[0].GetCpuHandle(); + } + +protected: + /// D3D12 view descriptor handle + DescriptorHeapAllocation m_Descriptor; + + // Extra descriptors used for mipmap generation + // [0] == texture array SRV used for mipmap generation + // [1] == mip level UAVs used for mipmap generation + DescriptorHeapAllocation* m_MipGenerationDescriptors = nullptr; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/pch.h b/Graphics/GraphicsEngineD3D12/include/pch.h index 101ffbdf..1554e6f6 100644 --- a/Graphics/GraphicsEngineD3D12/include/pch.h +++ b/Graphics/GraphicsEngineD3D12/include/pch.h @@ -50,13 +50,13 @@ #include "Errors.h" #include "RefCntAutoPtr.h" #include "DebugUtilities.h" -#include "D3DErrors.h" -#include "RenderDeviceBase.h" +#include "D3DErrors.hpp" +#include "RenderDeviceBase.hpp" #include "ValidatedCast.h" #include #if USE_D3D12_LOADER // On Win32 we manually load d3d12.dll and get entry points, // but UWP does not support that, so we link with d3d12.lib -# include "D3D12Loader.h" +# include "D3D12Loader.hpp" #endif diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp index dc23ff41..876a8bac 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp @@ -26,11 +26,11 @@ */ #include "pch.h" -#include "BufferD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" +#include "BufferD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" #include "D3D12TypeConversions.h" -#include "BufferViewD3D12Impl.h" +#include "BufferViewD3D12Impl.hpp" #include "GraphicsAccessories.hpp" #include "DXGITypeConversions.h" #include "EngineMemory.h" diff --git a/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp index 1b394931..731d4da2 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferViewD3D12Impl.cpp @@ -26,7 +26,7 @@ */ #include "pch.h" -#include "BufferViewD3D12Impl.h" +#include "BufferViewD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp index 2dbb5190..ebc46582 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp @@ -27,10 +27,10 @@ #include "pch.h" #include "d3dx12_win.h" -#include "CommandContext.h" -#include "TextureD3D12Impl.h" -#include "BufferD3D12Impl.h" -#include "CommandListManager.h" +#include "CommandContext.hpp" +#include "TextureD3D12Impl.hpp" +#include "BufferD3D12Impl.hpp" +#include "CommandListManager.hpp" #include "D3D12TypeConversions.h" diff --git a/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp b/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp index d1dadddc..53827add 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandListManager.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "CommandListManager.h" -#include "RenderDeviceD3D12Impl.h" +#include "CommandListManager.hpp" +#include "RenderDeviceD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp index 68a7d257..74e65559 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp @@ -26,7 +26,7 @@ */ #include "pch.h" -#include "CommandQueueD3D12Impl.h" +#include "CommandQueueD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp index 0c27214a..2c010f84 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "D3D12DynamicHeap.h" -#include "RenderDeviceD3D12Impl.h" +#include "D3D12DynamicHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp index f4f56281..f0cf9e3b 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp @@ -26,7 +26,7 @@ */ -#include "D3D12Loader.h" +#include "D3D12Loader.hpp" #include "Errors.h" #ifndef NOMINMAX diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp index e0e8d3f7..dfb01d88 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp @@ -33,8 +33,8 @@ #include "DXGITypeConversions.h" #include "D3D12TypeDefinitions.h" -#include "D3DTypeConversionImpl.h" -#include "D3DViewDescConversionImpl.h" +#include "D3DTypeConversionImpl.hpp" +#include "D3DViewDescConversionImpl.hpp" #include "PlatformMisc.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp index 39d9d119..be598856 100644 --- a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "DescriptorHeap.h" -#include "RenderDeviceD3D12Impl.h" +#include "DescriptorHeap.hpp" +#include "RenderDeviceD3D12Impl.hpp" #include "D3D12Utils.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 51d4c945..ba509cd5 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -27,17 +27,17 @@ #include "pch.h" #include -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" -#include "PipelineStateD3D12Impl.h" -#include "CommandContext.h" -#include "TextureD3D12Impl.h" -#include "BufferD3D12Impl.h" -#include "FenceD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "PipelineStateD3D12Impl.hpp" +#include "CommandContext.hpp" +#include "TextureD3D12Impl.hpp" +#include "BufferD3D12Impl.hpp" +#include "FenceD3D12Impl.hpp" #include "D3D12TypeConversions.h" #include "d3dx12_win.h" -#include "D3D12DynamicHeap.h" -#include "CommandListD3D12Impl.h" +#include "D3D12DynamicHeap.hpp" +#include "CommandListD3D12Impl.hpp" #include "DXGITypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp index 5b7a555e..77f2805e 100644 --- a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp @@ -34,14 +34,14 @@ #include #include "EngineFactoryD3D12.h" -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" -#include "SwapChainD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "SwapChainD3D12Impl.hpp" #include "D3D12TypeConversions.h" -#include "EngineFactoryD3DBase.h" +#include "EngineFactoryD3DBase.hpp" #include "StringTools.h" #include "EngineMemory.h" -#include "CommandQueueD3D12Impl.h" +#include "CommandQueueD3D12Impl.hpp" #ifndef NOMINMAX # define NOMINMAX diff --git a/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp index bf7703cd..a9e1c7d8 100644 --- a/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp @@ -29,9 +29,9 @@ #include #include -#include "FenceD3D12Impl.h" +#include "FenceD3D12Impl.hpp" #include "EngineMemory.h" -#include "RenderDeviceD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp index 8518da94..be5c68eb 100644 --- a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp +++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp @@ -45,11 +45,11 @@ #include "pch.h" #include "d3dx12_win.h" -#include "RenderDeviceD3D12Impl.h" -#include "GenerateMips.h" -#include "CommandContext.h" -#include "TextureViewD3D12Impl.h" -#include "TextureD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" +#include "GenerateMips.hpp" +#include "CommandContext.hpp" +#include "TextureViewD3D12Impl.hpp" +#include "TextureD3D12Impl.hpp" #include "GenerateMips/GenerateMipsLinearCS.h" #include "GenerateMips/GenerateMipsLinearOddCS.h" diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 5d3c022b..ce1e2dc6 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -27,16 +27,16 @@ #include "pch.h" #include -#include "PipelineStateD3D12Impl.h" -#include "ShaderD3D12Impl.h" +#include "PipelineStateD3D12Impl.hpp" +#include "ShaderD3D12Impl.hpp" #include "D3D12TypeConversions.h" -#include "RenderDeviceD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" #include "DXGITypeConversions.h" -#include "ShaderResourceBindingD3D12Impl.h" -#include "CommandContext.h" +#include "ShaderResourceBindingD3D12Impl.hpp" +#include "CommandContext.hpp" #include "EngineMemory.h" #include "StringTools.h" -#include "ShaderVariableD3D12.h" +#include "ShaderVariableD3D12.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp index 2dd1a299..e7b5c1ee 100644 --- a/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp @@ -28,10 +28,10 @@ #include "pch.h" #include -#include "QueryD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" +#include "QueryD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" #include "GraphicsAccessories.hpp" -#include "DeviceContextD3D12Impl.h" +#include "DeviceContextD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp index 4f542448..c8fd5110 100644 --- a/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp @@ -28,10 +28,10 @@ #include "pch.h" #include -#include "QueryManagerD3D12.h" +#include "QueryManagerD3D12.hpp" #include "D3D12TypeConversions.h" #include "GraphicsAccessories.hpp" -#include "CommandContext.h" +#include "CommandContext.hpp" #include "Align.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 4b1474d7..73be3632 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -27,17 +27,17 @@ #include "pch.h" #include -#include "RenderDeviceD3D12Impl.h" -#include "PipelineStateD3D12Impl.h" -#include "ShaderD3D12Impl.h" -#include "TextureD3D12Impl.h" +#include "RenderDeviceD3D12Impl.hpp" +#include "PipelineStateD3D12Impl.hpp" +#include "ShaderD3D12Impl.hpp" +#include "TextureD3D12Impl.hpp" #include "DXGITypeConversions.h" -#include "SamplerD3D12Impl.h" -#include "BufferD3D12Impl.h" -#include "ShaderResourceBindingD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" -#include "FenceD3D12Impl.h" -#include "QueryD3D12Impl.h" +#include "SamplerD3D12Impl.hpp" +#include "BufferD3D12Impl.hpp" +#include "ShaderResourceBindingD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "FenceD3D12Impl.hpp" +#include "QueryD3D12Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index d80983cc..201a5354 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -27,12 +27,12 @@ #include "pch.h" -#include "RootSignature.h" -#include "ShaderResourceLayoutD3D12.h" -#include "ShaderD3D12Impl.h" -#include "CommandContext.h" -#include "RenderDeviceD3D12Impl.h" -#include "TextureD3D12Impl.h" +#include "RootSignature.hpp" +#include "ShaderResourceLayoutD3D12.hpp" +#include "ShaderD3D12Impl.hpp" +#include "CommandContext.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "TextureD3D12Impl.hpp" #include "D3D12TypeConversions.h" #include "HashUtils.h" diff --git a/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp index 0c654cc7..e53fa1b5 100644 --- a/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SamplerD3D12Impl.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "SamplerD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" +#include "SamplerD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" #include "D3D12TypeConversions.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp index 89850809..e9729b80 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp @@ -29,8 +29,8 @@ #include -#include "ShaderD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" +#include "ShaderD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" #include "DataBlobImpl.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 5ac1f492..93d444d7 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -26,10 +26,10 @@ */ #include "pch.h" -#include "ShaderResourceBindingD3D12Impl.h" -#include "PipelineStateD3D12Impl.h" -#include "ShaderD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" +#include "ShaderResourceBindingD3D12Impl.hpp" +#include "PipelineStateD3D12Impl.hpp" +#include "ShaderD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp index a6679231..482443a7 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceCacheD3D12.cpp @@ -27,8 +27,8 @@ #include "pch.h" -#include "ShaderResourceCacheD3D12.h" -#include "BufferD3D12Impl.h" +#include "ShaderResourceCacheD3D12.hpp" +#include "BufferD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 8316ff5e..ce7c81f8 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -27,17 +27,17 @@ #include "pch.h" -#include "ShaderResourceLayoutD3D12.h" -#include "ShaderResourceCacheD3D12.h" -#include "BufferD3D12Impl.h" +#include "ShaderResourceLayoutD3D12.hpp" +#include "ShaderResourceCacheD3D12.hpp" +#include "BufferD3D12Impl.hpp" #include "BufferViewD3D12.h" -#include "TextureD3D12Impl.h" -#include "TextureViewD3D12Impl.h" -#include "SamplerD3D12Impl.h" -#include "ShaderD3D12Impl.h" -#include "RootSignature.h" -#include "PipelineStateD3D12Impl.h" -#include "ShaderResourceVariableBase.h" +#include "TextureD3D12Impl.hpp" +#include "TextureViewD3D12Impl.hpp" +#include "SamplerD3D12Impl.hpp" +#include "ShaderD3D12Impl.hpp" +#include "RootSignature.hpp" +#include "PipelineStateD3D12Impl.hpp" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp index f9a67288..edf818cc 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp @@ -28,9 +28,9 @@ #include "pch.h" #include -#include "ShaderResourcesD3D12.h" -#include "ShaderD3DBase.h" -#include "ShaderBase.h" +#include "ShaderResourcesD3D12.hpp" +#include "ShaderD3DBase.hpp" +#include "ShaderBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp index ecdf2bc7..1c825a15 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -27,8 +27,8 @@ #include "pch.h" -#include "ShaderVariableD3D12.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderVariableD3D12.hpp" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp index 531bf4c1..ac24533c 100644 --- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp @@ -26,11 +26,11 @@ */ #include "pch.h" -#include "SwapChainD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" +#include "SwapChainD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" #include "DXGITypeConversions.h" -#include "TextureD3D12Impl.h" +#include "TextureD3D12Impl.hpp" #include "EngineMemory.h" namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index be64e1db..90a583cc 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -26,11 +26,11 @@ */ #include "pch.h" -#include "TextureD3D12Impl.h" -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" +#include "TextureD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" #include "D3D12TypeConversions.h" -#include "TextureViewD3D12Impl.h" +#include "TextureViewD3D12Impl.hpp" #include "DXGITypeConversions.h" #include "d3dx12_win.h" #include "EngineMemory.h" diff --git a/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp index dc871bf6..d1287c57 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureViewD3D12Impl.cpp @@ -26,8 +26,8 @@ */ #include "pch.h" -#include "TextureViewD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" +#include "TextureViewD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt index 2a4daae2..a60f000f 100644 --- a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt @@ -3,18 +3,18 @@ cmake_minimum_required (VERSION 3.10) project(Diligent-GraphicsEngineD3DBase CXX) set(INCLUDE - include/D3DErrors.h - include/D3DShaderResourceLoader.h - include/D3DTypeConversionImpl.h - include/D3DViewDescConversionImpl.h + include/D3DErrors.hpp + include/D3DShaderResourceLoader.hpp + include/D3DTypeConversionImpl.hpp + include/D3DViewDescConversionImpl.hpp include/DXGITypeConversions.h - include/EngineFactoryD3DBase.h + include/EngineFactoryD3DBase.hpp include/HLSLDefinitions.fxh - include/RenderDeviceD3DBase.h - include/ShaderD3DBase.h - include/ShaderResources.h - include/ShaderVariableD3DBase.h - include/SwapChainD3DBase.h + include/RenderDeviceD3DBase.hpp + include/ShaderD3DBase.hpp + include/ShaderResources.hpp + include/ShaderVariableD3DBase.hpp + include/SwapChainD3DBase.hpp ) set(INTERFACE diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DErrors.h b/Graphics/GraphicsEngineD3DBase/include/D3DErrors.h deleted file mode 100644 index 51863b7a..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/D3DErrors.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include - -#include "Errors.h" - -/// \file -/// Declaration of Diligent::ComErrorDesc class - -namespace Diligent -{ - -/// Helper class that provides description of a COM error -class ComErrorDesc -{ -public: - ComErrorDesc(HRESULT hr) - { - auto NumCharsWritten = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - hr, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - m_Msg, - _countof(m_Msg), - NULL); - - if (NumCharsWritten == 0) - { - strcpy_s(m_Msg, _countof(m_Msg), "Unknown error"); - } - else - { - auto nLen = strlen(m_Msg); - if (nLen > 1 && m_Msg[nLen - 1] == '\n') - { - m_Msg[nLen - 1] = 0; - if (m_Msg[nLen - 2] == '\r') - { - m_Msg[nLen - 2] = 0; - } - } - } - } - - const char* Get() { return m_Msg; } - -private: - char m_Msg[4096]; -}; - -} // namespace Diligent - - -#define CHECK_D3D_RESULT_THROW(Expr, Message) \ - do \ - { \ - HRESULT _hr_ = Expr; \ - if (FAILED(_hr_)) \ - { \ - ComErrorDesc ErrDesc(_hr_); \ - LOG_ERROR_AND_THROW(Message, "\nHRESULT Desc: ", ErrDesc.Get()); \ - } \ - } while (false) - -#define CHECK_D3D_RESULT_THROW_EX(Expr, ...) \ - do \ - { \ - HRESULT _hr_ = Expr; \ - if (FAILED(_hr_)) \ - { \ - auto msg = Diligent::FormatString(__VA_ARGS__); \ - ComErrorDesc ErrDesc(_hr_); \ - LOG_ERROR_AND_THROW(msg, "\nHRESULT Desc: ", ErrDesc.Get()); \ - } \ - } while (false) - -#define LOG_D3D_ERROR(Expr, Message) \ - do \ - { \ - HRESULT _hr_ = Expr; \ - if (FAILED(_hr_)) \ - { \ - ComErrorDesc ErrDesc(_hr_); \ - LOG_ERROR_MESSAGE(Message, "\nHRESULT Desc: ", ErrDesc.Get()); \ - } \ - } while (false) diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DErrors.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DErrors.hpp new file mode 100644 index 00000000..51863b7a --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/D3DErrors.hpp @@ -0,0 +1,114 @@ +/* + * Copyright 2019-2020 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 + +#include + +#include "Errors.h" + +/// \file +/// Declaration of Diligent::ComErrorDesc class + +namespace Diligent +{ + +/// Helper class that provides description of a COM error +class ComErrorDesc +{ +public: + ComErrorDesc(HRESULT hr) + { + auto NumCharsWritten = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + m_Msg, + _countof(m_Msg), + NULL); + + if (NumCharsWritten == 0) + { + strcpy_s(m_Msg, _countof(m_Msg), "Unknown error"); + } + else + { + auto nLen = strlen(m_Msg); + if (nLen > 1 && m_Msg[nLen - 1] == '\n') + { + m_Msg[nLen - 1] = 0; + if (m_Msg[nLen - 2] == '\r') + { + m_Msg[nLen - 2] = 0; + } + } + } + } + + const char* Get() { return m_Msg; } + +private: + char m_Msg[4096]; +}; + +} // namespace Diligent + + +#define CHECK_D3D_RESULT_THROW(Expr, Message) \ + do \ + { \ + HRESULT _hr_ = Expr; \ + if (FAILED(_hr_)) \ + { \ + ComErrorDesc ErrDesc(_hr_); \ + LOG_ERROR_AND_THROW(Message, "\nHRESULT Desc: ", ErrDesc.Get()); \ + } \ + } while (false) + +#define CHECK_D3D_RESULT_THROW_EX(Expr, ...) \ + do \ + { \ + HRESULT _hr_ = Expr; \ + if (FAILED(_hr_)) \ + { \ + auto msg = Diligent::FormatString(__VA_ARGS__); \ + ComErrorDesc ErrDesc(_hr_); \ + LOG_ERROR_AND_THROW(msg, "\nHRESULT Desc: ", ErrDesc.Get()); \ + } \ + } while (false) + +#define LOG_D3D_ERROR(Expr, Message) \ + do \ + { \ + HRESULT _hr_ = Expr; \ + if (FAILED(_hr_)) \ + { \ + ComErrorDesc ErrDesc(_hr_); \ + LOG_ERROR_MESSAGE(Message, "\nHRESULT Desc: ", ErrDesc.Get()); \ + } \ + } while (false) diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h deleted file mode 100644 index 64e08580..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include -#include -#include - -#include "Shader.h" -#include "StringTools.h" - -/// \file -/// D3D shader resource loading - -namespace Diligent -{ - -struct D3DShaderResourceCounters -{ - Uint32 NumCBs = 0; - Uint32 NumTexSRVs = 0; - Uint32 NumTexUAVs = 0; - Uint32 NumBufSRVs = 0; - Uint32 NumBufUAVs = 0; - Uint32 NumSamplers = 0; -}; - -template -void LoadD3DShaderResources(ID3DBlob* pShaderByteCode, - THandleShaderDesc HandleShaderDesc, - TOnResourcesCounted OnResourcesCounted, - TOnNewCB OnNewCB, - TOnNewTexUAV OnNewTexUAV, - TOnNewBuffUAV OnNewBuffUAV, - TOnNewBuffSRV OnNewBuffSRV, - TOnNewSampler OnNewSampler, - TOnNewTexSRV OnNewTexSRV) -{ - CComPtr pShaderReflection; - - auto hr = D3DReflect(pShaderByteCode->GetBufferPointer(), pShaderByteCode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast(static_cast(&pShaderReflection))); - CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection"); - - D3D_SHADER_DESC shaderDesc = {}; - pShaderReflection->GetDesc(&shaderDesc); - - HandleShaderDesc(shaderDesc); - - std::vector> Resources(STD_ALLOCATOR_RAW_MEM(D3DShaderResourceAttribs, GetRawAllocator(), "Allocator for vector")); - Resources.reserve(shaderDesc.BoundResources); - std::unordered_set ResourceNamesTmpPool; - - D3DShaderResourceCounters RC; - - size_t ResourceNamesPoolSize = 0; - // Number of resources to skip (used for array resources) - UINT SkipCount = 1; - for (UINT Res = 0; Res < shaderDesc.BoundResources; Res += SkipCount) - { - D3D_SHADER_INPUT_BIND_DESC BindingDesc = {}; - pShaderReflection->GetResourceBindingDesc(Res, &BindingDesc); - - std::string Name(BindingDesc.Name); - - SkipCount = 1; - - UINT BindCount = BindingDesc.BindCount; - - // Handle arrays - // For shader models 5_0 and before, every resource array element is enumerated individually. - // For instance, if the following texture array is defined in the shader: - // - // Texture2D g_tex2DDiffuse[4]; - // - // The reflection system will enumerate 4 resources with the following names: - // "g_tex2DDiffuse[0]" - // "g_tex2DDiffuse[1]" - // "g_tex2DDiffuse[2]" - // "g_tex2DDiffuse[3]" - // - // Notice that if some array element is not used by the shader, it will not be enumerated - - auto OpenBracketPos = Name.find('['); - if (String::npos != OpenBracketPos) - { - VERIFY(BindCount == 1, "When array elements are enumerated individually, BindCount is expected to always be 1"); - - // Name == "g_tex2DDiffuse[0]" - // ^ - // OpenBracketPos - Name.erase(OpenBracketPos, Name.length() - OpenBracketPos); - // Name == "g_tex2DDiffuse" - VERIFY_EXPR(Name.length() == OpenBracketPos); -#ifdef _DEBUG - for (const auto& ExistingRes : Resources) - { - VERIFY(Name.compare(ExistingRes.Name) != 0, "Resource with the same name has already been enumerated. All array elements are expected to be enumerated one after another"); - } -#endif - for (UINT ArrElem = Res + 1; ArrElem < shaderDesc.BoundResources; ++ArrElem) - { - D3D_SHADER_INPUT_BIND_DESC ArrElemBindingDesc = {}; - pShaderReflection->GetResourceBindingDesc(ArrElem, &ArrElemBindingDesc); - - // Make sure this case is handled correctly: - // "g_tex2DDiffuse[.]" != "g_tex2DDiffuse2[.]" - if (strncmp(Name.c_str(), ArrElemBindingDesc.Name, OpenBracketPos) == 0 && ArrElemBindingDesc.Name[OpenBracketPos] == '[') - { - //g_tex2DDiffuse[2] - // ^ - UINT Ind = atoi(ArrElemBindingDesc.Name + OpenBracketPos + 1); - BindCount = std::max(BindCount, Ind + 1); - VERIFY(ArrElemBindingDesc.BindPoint == BindingDesc.BindPoint + Ind, - "Array elements are expected to use contigous bind points.\n", - BindingDesc.Name, " uses slot ", BindingDesc.BindPoint, ", so ", ArrElemBindingDesc.Name, - " is expected to use slot ", BindingDesc.BindPoint + Ind, " while ", ArrElemBindingDesc.BindPoint, - " is actually used"); - - // Note that skip count may not necessarily be the same as BindCount. - // If some array elements are not used by the shader, the reflection system skips them - ++SkipCount; - } - else - { - break; - } - } - } - - switch (BindingDesc.Type) - { - // clang-format off - case D3D_SIT_CBUFFER: ++RC.NumCBs; break; - case D3D_SIT_TBUFFER: UNSUPPORTED( "TBuffers are not supported" ); break; - case D3D_SIT_TEXTURE: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufSRVs : RC.NumTexSRVs); break; - case D3D_SIT_SAMPLER: ++RC.NumSamplers; break; - case D3D_SIT_UAV_RWTYPED: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufUAVs : RC.NumTexUAVs); break; - case D3D_SIT_STRUCTURED: ++RC.NumBufSRVs; break; - case D3D_SIT_UAV_RWSTRUCTURED: ++RC.NumBufUAVs; break; - case D3D_SIT_BYTEADDRESS: ++RC.NumBufSRVs; break; - case D3D_SIT_UAV_RWBYTEADDRESS: ++RC.NumBufUAVs; break; - case D3D_SIT_UAV_APPEND_STRUCTURED: UNSUPPORTED( "Append structured buffers are not supported" ); break; - case D3D_SIT_UAV_CONSUME_STRUCTURED: UNSUPPORTED( "Consume structured buffers are not supported" ); break; - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; - // clang-format on - default: UNEXPECTED("Unexpected resource type"); - } - ResourceNamesPoolSize += Name.length() + 1; - auto it = ResourceNamesTmpPool.emplace(std::move(Name)); - Resources.emplace_back( - it.first->c_str(), - BindingDesc.BindPoint, - BindCount, - BindingDesc.Type, - BindingDesc.Dimension, - D3DShaderResourceAttribs::InvalidSamplerId); - } - - OnResourcesCounted(RC, ResourceNamesPoolSize); - - std::vector> TexSRVInds(STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for vector")); - TexSRVInds.reserve(RC.NumTexSRVs); - - for (size_t ResInd = 0; ResInd < Resources.size(); ++ResInd) - { - const auto& Res = Resources[ResInd]; - switch (Res.GetInputType()) - { - case D3D_SIT_CBUFFER: - { - OnNewCB(Res); - break; - } - - case D3D_SIT_TBUFFER: - { - UNSUPPORTED("TBuffers are not supported"); - break; - } - - case D3D_SIT_TEXTURE: - { - if (Res.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) - { - OnNewBuffSRV(Res); - } - else - { - // Texture SRVs must be processed all samplers are initialized - TexSRVInds.push_back(ResInd); - } - break; - } - - case D3D_SIT_SAMPLER: - { - OnNewSampler(Res); - break; - } - - case D3D_SIT_UAV_RWTYPED: - { - if (Res.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) - { - OnNewBuffUAV(Res); - } - else - { - OnNewTexUAV(Res); - } - break; - } - - case D3D_SIT_STRUCTURED: - { - OnNewBuffSRV(Res); - break; - } - - case D3D_SIT_UAV_RWSTRUCTURED: - { - OnNewBuffUAV(Res); - break; - } - - case D3D_SIT_BYTEADDRESS: - { - OnNewBuffSRV(Res); - break; - } - - case D3D_SIT_UAV_RWBYTEADDRESS: - { - OnNewBuffUAV(Res); - break; - } - - case D3D_SIT_UAV_APPEND_STRUCTURED: - { - UNSUPPORTED("Append structured buffers are not supported"); - break; - } - - case D3D_SIT_UAV_CONSUME_STRUCTURED: - { - UNSUPPORTED("Consume structured buffers are not supported"); - break; - } - - case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: - { - UNSUPPORTED("RW structured buffers with counter are not supported"); - break; - } - - default: - { - UNEXPECTED("Unexpected resource input type"); - } - } - } - - // Process texture SRVs. We need to do this after all samplers are initialized - for (auto TexSRVInd : TexSRVInds) - { - OnNewTexSRV(Resources[TexSRVInd]); - } -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp new file mode 100644 index 00000000..64e08580 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp @@ -0,0 +1,306 @@ +/* + * Copyright 2019-2020 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 + +#include +#include +#include + +#include "Shader.h" +#include "StringTools.h" + +/// \file +/// D3D shader resource loading + +namespace Diligent +{ + +struct D3DShaderResourceCounters +{ + Uint32 NumCBs = 0; + Uint32 NumTexSRVs = 0; + Uint32 NumTexUAVs = 0; + Uint32 NumBufSRVs = 0; + Uint32 NumBufUAVs = 0; + Uint32 NumSamplers = 0; +}; + +template +void LoadD3DShaderResources(ID3DBlob* pShaderByteCode, + THandleShaderDesc HandleShaderDesc, + TOnResourcesCounted OnResourcesCounted, + TOnNewCB OnNewCB, + TOnNewTexUAV OnNewTexUAV, + TOnNewBuffUAV OnNewBuffUAV, + TOnNewBuffSRV OnNewBuffSRV, + TOnNewSampler OnNewSampler, + TOnNewTexSRV OnNewTexSRV) +{ + CComPtr pShaderReflection; + + auto hr = D3DReflect(pShaderByteCode->GetBufferPointer(), pShaderByteCode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast(static_cast(&pShaderReflection))); + CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection"); + + D3D_SHADER_DESC shaderDesc = {}; + pShaderReflection->GetDesc(&shaderDesc); + + HandleShaderDesc(shaderDesc); + + std::vector> Resources(STD_ALLOCATOR_RAW_MEM(D3DShaderResourceAttribs, GetRawAllocator(), "Allocator for vector")); + Resources.reserve(shaderDesc.BoundResources); + std::unordered_set ResourceNamesTmpPool; + + D3DShaderResourceCounters RC; + + size_t ResourceNamesPoolSize = 0; + // Number of resources to skip (used for array resources) + UINT SkipCount = 1; + for (UINT Res = 0; Res < shaderDesc.BoundResources; Res += SkipCount) + { + D3D_SHADER_INPUT_BIND_DESC BindingDesc = {}; + pShaderReflection->GetResourceBindingDesc(Res, &BindingDesc); + + std::string Name(BindingDesc.Name); + + SkipCount = 1; + + UINT BindCount = BindingDesc.BindCount; + + // Handle arrays + // For shader models 5_0 and before, every resource array element is enumerated individually. + // For instance, if the following texture array is defined in the shader: + // + // Texture2D g_tex2DDiffuse[4]; + // + // The reflection system will enumerate 4 resources with the following names: + // "g_tex2DDiffuse[0]" + // "g_tex2DDiffuse[1]" + // "g_tex2DDiffuse[2]" + // "g_tex2DDiffuse[3]" + // + // Notice that if some array element is not used by the shader, it will not be enumerated + + auto OpenBracketPos = Name.find('['); + if (String::npos != OpenBracketPos) + { + VERIFY(BindCount == 1, "When array elements are enumerated individually, BindCount is expected to always be 1"); + + // Name == "g_tex2DDiffuse[0]" + // ^ + // OpenBracketPos + Name.erase(OpenBracketPos, Name.length() - OpenBracketPos); + // Name == "g_tex2DDiffuse" + VERIFY_EXPR(Name.length() == OpenBracketPos); +#ifdef _DEBUG + for (const auto& ExistingRes : Resources) + { + VERIFY(Name.compare(ExistingRes.Name) != 0, "Resource with the same name has already been enumerated. All array elements are expected to be enumerated one after another"); + } +#endif + for (UINT ArrElem = Res + 1; ArrElem < shaderDesc.BoundResources; ++ArrElem) + { + D3D_SHADER_INPUT_BIND_DESC ArrElemBindingDesc = {}; + pShaderReflection->GetResourceBindingDesc(ArrElem, &ArrElemBindingDesc); + + // Make sure this case is handled correctly: + // "g_tex2DDiffuse[.]" != "g_tex2DDiffuse2[.]" + if (strncmp(Name.c_str(), ArrElemBindingDesc.Name, OpenBracketPos) == 0 && ArrElemBindingDesc.Name[OpenBracketPos] == '[') + { + //g_tex2DDiffuse[2] + // ^ + UINT Ind = atoi(ArrElemBindingDesc.Name + OpenBracketPos + 1); + BindCount = std::max(BindCount, Ind + 1); + VERIFY(ArrElemBindingDesc.BindPoint == BindingDesc.BindPoint + Ind, + "Array elements are expected to use contigous bind points.\n", + BindingDesc.Name, " uses slot ", BindingDesc.BindPoint, ", so ", ArrElemBindingDesc.Name, + " is expected to use slot ", BindingDesc.BindPoint + Ind, " while ", ArrElemBindingDesc.BindPoint, + " is actually used"); + + // Note that skip count may not necessarily be the same as BindCount. + // If some array elements are not used by the shader, the reflection system skips them + ++SkipCount; + } + else + { + break; + } + } + } + + switch (BindingDesc.Type) + { + // clang-format off + case D3D_SIT_CBUFFER: ++RC.NumCBs; break; + case D3D_SIT_TBUFFER: UNSUPPORTED( "TBuffers are not supported" ); break; + case D3D_SIT_TEXTURE: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufSRVs : RC.NumTexSRVs); break; + case D3D_SIT_SAMPLER: ++RC.NumSamplers; break; + case D3D_SIT_UAV_RWTYPED: ++(BindingDesc.Dimension == D3D_SRV_DIMENSION_BUFFER ? RC.NumBufUAVs : RC.NumTexUAVs); break; + case D3D_SIT_STRUCTURED: ++RC.NumBufSRVs; break; + case D3D_SIT_UAV_RWSTRUCTURED: ++RC.NumBufUAVs; break; + case D3D_SIT_BYTEADDRESS: ++RC.NumBufSRVs; break; + case D3D_SIT_UAV_RWBYTEADDRESS: ++RC.NumBufUAVs; break; + case D3D_SIT_UAV_APPEND_STRUCTURED: UNSUPPORTED( "Append structured buffers are not supported" ); break; + case D3D_SIT_UAV_CONSUME_STRUCTURED: UNSUPPORTED( "Consume structured buffers are not supported" ); break; + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; + // clang-format on + default: UNEXPECTED("Unexpected resource type"); + } + ResourceNamesPoolSize += Name.length() + 1; + auto it = ResourceNamesTmpPool.emplace(std::move(Name)); + Resources.emplace_back( + it.first->c_str(), + BindingDesc.BindPoint, + BindCount, + BindingDesc.Type, + BindingDesc.Dimension, + D3DShaderResourceAttribs::InvalidSamplerId); + } + + OnResourcesCounted(RC, ResourceNamesPoolSize); + + std::vector> TexSRVInds(STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for vector")); + TexSRVInds.reserve(RC.NumTexSRVs); + + for (size_t ResInd = 0; ResInd < Resources.size(); ++ResInd) + { + const auto& Res = Resources[ResInd]; + switch (Res.GetInputType()) + { + case D3D_SIT_CBUFFER: + { + OnNewCB(Res); + break; + } + + case D3D_SIT_TBUFFER: + { + UNSUPPORTED("TBuffers are not supported"); + break; + } + + case D3D_SIT_TEXTURE: + { + if (Res.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) + { + OnNewBuffSRV(Res); + } + else + { + // Texture SRVs must be processed all samplers are initialized + TexSRVInds.push_back(ResInd); + } + break; + } + + case D3D_SIT_SAMPLER: + { + OnNewSampler(Res); + break; + } + + case D3D_SIT_UAV_RWTYPED: + { + if (Res.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) + { + OnNewBuffUAV(Res); + } + else + { + OnNewTexUAV(Res); + } + break; + } + + case D3D_SIT_STRUCTURED: + { + OnNewBuffSRV(Res); + break; + } + + case D3D_SIT_UAV_RWSTRUCTURED: + { + OnNewBuffUAV(Res); + break; + } + + case D3D_SIT_BYTEADDRESS: + { + OnNewBuffSRV(Res); + break; + } + + case D3D_SIT_UAV_RWBYTEADDRESS: + { + OnNewBuffUAV(Res); + break; + } + + case D3D_SIT_UAV_APPEND_STRUCTURED: + { + UNSUPPORTED("Append structured buffers are not supported"); + break; + } + + case D3D_SIT_UAV_CONSUME_STRUCTURED: + { + UNSUPPORTED("Consume structured buffers are not supported"); + break; + } + + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + { + UNSUPPORTED("RW structured buffers with counter are not supported"); + break; + } + + default: + { + UNEXPECTED("Unexpected resource input type"); + } + } + } + + // Process texture SRVs. We need to do this after all samplers are initialized + for (auto TexSRVInd : TexSRVInds) + { + OnNewTexSRV(Resources[TexSRVInd]); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.h b/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.h deleted file mode 100644 index 0e2c684d..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.h +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include - -/// \file -/// Implementation of D3D type conversions - -/// This file must be included after D3D11TypeDefinitions.h or D3D12TypeDefinitions.h - -namespace Diligent -{ - -template -inline D3D_COMPARISON_FUNC ComparisonFuncToD3DComparisonFunc(COMPARISON_FUNCTION Func) -{ - // D3D12_COMPARISON_FUNC is equal to D3D11_COMPARISON_FUNC - switch (Func) - { - // clang-format off - case COMPARISON_FUNC_UNKNOWN: UNEXPECTED("Comparison function is not specified" ); return D3D_COMPARISON_FUNC_ALWAYS; - case COMPARISON_FUNC_NEVER: return D3D_COMPARISON_FUNC_NEVER; - case COMPARISON_FUNC_LESS: return D3D_COMPARISON_FUNC_LESS; - case COMPARISON_FUNC_EQUAL: return D3D_COMPARISON_FUNC_EQUAL; - case COMPARISON_FUNC_LESS_EQUAL: return D3D_COMPARISON_FUNC_LESS_EQUAL; - case COMPARISON_FUNC_GREATER: return D3D_COMPARISON_FUNC_GREATER; - case COMPARISON_FUNC_NOT_EQUAL: return D3D_COMPARISON_FUNC_NOT_EQUAL; - case COMPARISON_FUNC_GREATER_EQUAL: return D3D_COMPARISON_FUNC_GREATER_EQUAL; - case COMPARISON_FUNC_ALWAYS: return D3D_COMPARISON_FUNC_ALWAYS; - default: UNEXPECTED("Unknown comparison function" ); return D3D_COMPARISON_FUNC_ALWAYS; - // clang-format on - } -} - - -template -D3D_TEXTURE_ADDRESS_MODE TexAddressModeToD3DAddressMode(TEXTURE_ADDRESS_MODE Mode) -{ - switch (Mode) - { - // clang-format off - case TEXTURE_ADDRESS_UNKNOWN: UNEXPECTED("Texture address mode is not specified" ); return D3D_TEXTURE_ADDRESS_CLAMP; - case TEXTURE_ADDRESS_WRAP: return D3D_TEXTURE_ADDRESS_WRAP; - case TEXTURE_ADDRESS_MIRROR: return D3D_TEXTURE_ADDRESS_MIRROR; - case TEXTURE_ADDRESS_CLAMP: return D3D_TEXTURE_ADDRESS_CLAMP; - case TEXTURE_ADDRESS_BORDER: return D3D_TEXTURE_ADDRESS_BORDER; - case TEXTURE_ADDRESS_MIRROR_ONCE: return D3D_TEXTURE_ADDRESS_MIRROR_ONCE; - default: UNEXPECTED("Unknown texture address mode" ); return D3D_TEXTURE_ADDRESS_CLAMP; - // clang-format on - } -} - -template -D3D_PRIM_TOPOLOGY TopologyToD3DTopology(PRIMITIVE_TOPOLOGY Topology) -{ - static bool bIsInit = false; - static std::array d3dPrimTopology = {}; - if (!bIsInit) - { - // clang-format off - d3dPrimTopology[PRIMITIVE_TOPOLOGY_UNDEFINED] = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_POINT_LIST] = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_LINE_LIST] = D3D_PRIMITIVE_TOPOLOGY_LINELIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST; - d3dPrimTopology[PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST; - // clang-format on - bIsInit = true; - } - - VERIFY_EXPR(Topology >= PRIMITIVE_TOPOLOGY_UNDEFINED && Topology < PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES); - return d3dPrimTopology[Topology]; -} - - -// ================= Rasterizer state attributes conversion functions ================= - -template -D3D_FILL_MODE FillModeToD3DFillMode(FILL_MODE FillMode) -{ - // D3D12_FILL_MODE is identical tp D3D11_FILL_MODE - static bool bIsInit = false; - static std::array d3dFillModes = {}; - if (!bIsInit) - { - d3dFillModes[FILL_MODE_WIREFRAME] = D3D_FILL_MODE_WIREFRAME; - d3dFillModes[FILL_MODE_SOLID] = D3D_FILL_MODE_SOLID; - - bIsInit = true; - } - if (FILL_MODE_UNDEFINED < FillMode && FillMode < FILL_MODE_NUM_MODES) - { - auto d3dFillMode = d3dFillModes[FillMode]; - VERIFY(d3dFillMode != 0, "Incorrect fill mode"); - return d3dFillMode; - } - else - { - UNEXPECTED("Incorrect fill mode (", FillMode, ")"); - return static_cast(0); - } -} - -template -D3D_CULL_MODE CullModeToD3DCullMode(CULL_MODE CullMode) -{ - // D3D_CULL_MODE is identical to D3D11_CULL_MODE - static bool bIsInit = false; - static std::array d3dCullModes = {}; - if (!bIsInit) - { - d3dCullModes[CULL_MODE_NONE] = D3D_CULL_MODE_NONE; - d3dCullModes[CULL_MODE_FRONT] = D3D_CULL_MODE_FRONT; - d3dCullModes[CULL_MODE_BACK] = D3D_CULL_MODE_BACK; - - bIsInit = true; - } - - if (CULL_MODE_UNDEFINED < CullMode && CullMode < CULL_MODE_NUM_MODES) - { - auto d3dCullMode = d3dCullModes[CullMode]; - VERIFY(d3dCullMode != 0, "Incorrect cull mode"); - return d3dCullMode; - } - else - { - UNEXPECTED("Incorrect cull mode (", CullMode, ")"); - return static_cast(0); - } -} - -template -void RasterizerStateDesc_To_D3D_RASTERIZER_DESC(const RasterizerStateDesc& RasterizerDesc, D3D_RASTERIZER_DESC& d3dRSDesc) -{ - d3dRSDesc.FillMode = FillModeToD3DFillMode(RasterizerDesc.FillMode); - d3dRSDesc.CullMode = CullModeToD3DCullMode(RasterizerDesc.CullMode); - d3dRSDesc.FrontCounterClockwise = RasterizerDesc.FrontCounterClockwise ? TRUE : FALSE; - d3dRSDesc.DepthBias = RasterizerDesc.DepthBias; - d3dRSDesc.DepthBiasClamp = RasterizerDesc.DepthBiasClamp; - d3dRSDesc.SlopeScaledDepthBias = RasterizerDesc.SlopeScaledDepthBias; - d3dRSDesc.DepthClipEnable = RasterizerDesc.DepthClipEnable ? TRUE : FALSE; - - //d3d12RSDesc.ScissorEnable = RSDesc.ScissorEnable ? TRUE : FALSE; - - d3dRSDesc.AntialiasedLineEnable = RasterizerDesc.AntialiasedLineEnable ? TRUE : FALSE; - d3dRSDesc.MultisampleEnable = d3dRSDesc.AntialiasedLineEnable; -} - - - -// ================= Blend state attributes conversion functions ================= - -template -D3D_BLEND BlendFactorToD3DBlend(BLEND_FACTOR bf) -{ - // D3D11_BLEND and D3D12_BLEND are identical - - // Note that this code is safe for multithreaded environments since - // bIsInit is set to true only AFTER the entire map is initialized. - static bool bIsInit = false; - static std::array D3DBlend = {}; - if (!bIsInit) - { - // In a multithreaded environment, several threads can potentially enter - // this block. This is not a problem since they will just initialize the - // memory with the same values more than once - - // clang-format off - D3DBlend[BLEND_FACTOR_ZERO ] = D3D_BLEND_ZERO; - D3DBlend[BLEND_FACTOR_ONE ] = D3D_BLEND_ONE; - D3DBlend[BLEND_FACTOR_SRC_COLOR ] = D3D_BLEND_SRC_COLOR; - D3DBlend[BLEND_FACTOR_INV_SRC_COLOR ] = D3D_BLEND_INV_SRC_COLOR; - D3DBlend[BLEND_FACTOR_SRC_ALPHA ] = D3D_BLEND_SRC_ALPHA; - D3DBlend[BLEND_FACTOR_INV_SRC_ALPHA ] = D3D_BLEND_INV_SRC_ALPHA; - D3DBlend[BLEND_FACTOR_DEST_ALPHA ] = D3D_BLEND_DEST_ALPHA; - D3DBlend[BLEND_FACTOR_INV_DEST_ALPHA ] = D3D_BLEND_INV_DEST_ALPHA; - D3DBlend[BLEND_FACTOR_DEST_COLOR ] = D3D_BLEND_DEST_COLOR; - D3DBlend[BLEND_FACTOR_INV_DEST_COLOR ] = D3D_BLEND_INV_DEST_COLOR; - D3DBlend[BLEND_FACTOR_SRC_ALPHA_SAT ] = D3D_BLEND_SRC_ALPHA_SAT; - D3DBlend[BLEND_FACTOR_BLEND_FACTOR ] = D3D_BLEND_BLEND_FACTOR; - D3DBlend[BLEND_FACTOR_INV_BLEND_FACTOR] = D3D_BLEND_INV_BLEND_FACTOR; - D3DBlend[BLEND_FACTOR_SRC1_COLOR ] = D3D_BLEND_SRC1_COLOR; - D3DBlend[BLEND_FACTOR_INV_SRC1_COLOR ] = D3D_BLEND_INV_SRC1_COLOR; - D3DBlend[BLEND_FACTOR_SRC1_ALPHA ] = D3D_BLEND_SRC1_ALPHA; - D3DBlend[BLEND_FACTOR_INV_SRC1_ALPHA ] = D3D_BLEND_INV_SRC1_ALPHA; - // clang-format on - - bIsInit = true; - } - if (bf > BLEND_FACTOR_UNDEFINED && bf < BLEND_FACTOR_NUM_FACTORS) - { - auto d3dbf = D3DBlend[bf]; - VERIFY(d3dbf != 0, "Incorrect blend factor"); - return d3dbf; - } - else - { - UNEXPECTED("Incorrect blend factor (", bf, ")"); - return static_cast(0); - } -} - -template -D3D_BLEND_OP BlendOperationToD3DBlendOp(BLEND_OPERATION BlendOp) -{ - // D3D12_BLEND_OP and D3D11_BLEND_OP are identical - - static bool bIsInit = false; - static std::array D3DBlendOp = {}; - if (!bIsInit) - { - // clang-format off - D3DBlendOp[BLEND_OPERATION_ADD ] = D3D_BLEND_OP_ADD; - D3DBlendOp[BLEND_OPERATION_SUBTRACT ] = D3D_BLEND_OP_SUBTRACT; - D3DBlendOp[BLEND_OPERATION_REV_SUBTRACT] = D3D_BLEND_OP_REV_SUBTRACT; - D3DBlendOp[BLEND_OPERATION_MIN ] = D3D_BLEND_OP_MIN; - D3DBlendOp[BLEND_OPERATION_MAX ] = D3D_BLEND_OP_MAX; - // clang-format on - - bIsInit = true; - } - - if (BlendOp > BLEND_OPERATION_UNDEFINED && BlendOp < BLEND_OPERATION_NUM_OPERATIONS) - { - auto d3dbop = D3DBlendOp[BlendOp]; - VERIFY(d3dbop != 0, "Incorrect blend operation"); - return d3dbop; - } - else - { - UNEXPECTED("Incorrect blend operation (", BlendOp, ")"); - return static_cast(0); - } -} - -template -void BlendStateDescToD3DBlendDesc(const BlendStateDesc& BSDesc, D3D_BLEND_DESC& d3d12BlendDesc) -{ - // D3D_BLEND_DESC and D3D11_BLEND_DESC structures are identical - d3d12BlendDesc.AlphaToCoverageEnable = BSDesc.AlphaToCoverageEnable ? TRUE : FALSE; - d3d12BlendDesc.IndependentBlendEnable = BSDesc.IndependentBlendEnable ? TRUE : FALSE; - VERIFY(MAX_RENDER_TARGETS >= 8, "Number of render targets is expected to be at least 8"); - for (int i = 0; i < 8; ++i) - { - const auto& SrcRTDesc = BSDesc.RenderTargets[i]; - auto& DstRTDesc = d3d12BlendDesc.RenderTarget[i]; - DstRTDesc.BlendEnable = SrcRTDesc.BlendEnable ? TRUE : FALSE; - - DstRTDesc.SrcBlend = BlendFactorToD3DBlend(SrcRTDesc.SrcBlend); - DstRTDesc.DestBlend = BlendFactorToD3DBlend(SrcRTDesc.DestBlend); - DstRTDesc.BlendOp = BlendOperationToD3DBlendOp(SrcRTDesc.BlendOp); - - DstRTDesc.SrcBlendAlpha = BlendFactorToD3DBlend(SrcRTDesc.SrcBlendAlpha); - DstRTDesc.DestBlendAlpha = BlendFactorToD3DBlend(SrcRTDesc.DestBlendAlpha); - DstRTDesc.BlendOpAlpha = BlendOperationToD3DBlendOp(SrcRTDesc.BlendOpAlpha); - - DstRTDesc.RenderTargetWriteMask = - ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_RED) ? D3D_COLOR_WRITE_ENABLE_RED : 0) | - ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_GREEN) ? D3D_COLOR_WRITE_ENABLE_GREEN : 0) | - ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_BLUE) ? D3D_COLOR_WRITE_ENABLE_BLUE : 0) | - ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_ALPHA) ? D3D_COLOR_WRITE_ENABLE_ALPHA : 0); - } -} - - - -// ====================== Depth-stencil state attributes conversion functions ====================== - -template -D3D_STENCIL_OP StencilOpToD3DStencilOp(STENCIL_OP StencilOp) -{ - static bool bIsInit = false; - static std::array StOpToD3DStOpMap = {}; - if (!bIsInit) - { - // clang-format off - StOpToD3DStOpMap[STENCIL_OP_KEEP ] = D3D_STENCIL_OP_KEEP; - StOpToD3DStOpMap[STENCIL_OP_ZERO ] = D3D_STENCIL_OP_ZERO; - StOpToD3DStOpMap[STENCIL_OP_REPLACE ] = D3D_STENCIL_OP_REPLACE; - StOpToD3DStOpMap[STENCIL_OP_INCR_SAT ] = D3D_STENCIL_OP_INCR_SAT; - StOpToD3DStOpMap[STENCIL_OP_DECR_SAT ] = D3D_STENCIL_OP_DECR_SAT; - StOpToD3DStOpMap[STENCIL_OP_INVERT ] = D3D_STENCIL_OP_INVERT; - StOpToD3DStOpMap[STENCIL_OP_INCR_WRAP] = D3D_STENCIL_OP_INCR; - StOpToD3DStOpMap[STENCIL_OP_DECR_WRAP] = D3D_STENCIL_OP_DECR; - // clang-format on - - bIsInit = true; - } - - if (StencilOp > STENCIL_OP_UNDEFINED && StencilOp < STENCIL_OP_NUM_OPS) - { - auto d3dStencilOp = StOpToD3DStOpMap[StencilOp]; - VERIFY(d3dStencilOp != 0, "Unexpected stencil op"); - return d3dStencilOp; - } - else - { - UNEXPECTED("Stencil operation (", StencilOp, ") is out of allowed range [1, ", STENCIL_OP_NUM_OPS - 1, "]"); - return static_cast(0); - } -} - -template -D3D_DEPTH_STENCILOP_DESC StencilOpDescToD3DStencilOpDesc(const StencilOpDesc& StOpDesc) -{ - // D3D12_DEPTH_STENCILOP_DESC is identical to D3D11_DEPTH_STENCILOP_DESC - D3D_DEPTH_STENCILOP_DESC D3DStOpDesc; - D3DStOpDesc.StencilFailOp = StencilOpToD3DStencilOp(StOpDesc.StencilFailOp); - D3DStOpDesc.StencilDepthFailOp = StencilOpToD3DStencilOp(StOpDesc.StencilDepthFailOp); - D3DStOpDesc.StencilPassOp = StencilOpToD3DStencilOp(StOpDesc.StencilPassOp); - D3DStOpDesc.StencilFunc = ComparisonFuncToD3DComparisonFunc(StOpDesc.StencilFunc); - return D3DStOpDesc; -} - -template -void DepthStencilStateDesc_To_D3D_DEPTH_STENCIL_DESC(const DepthStencilStateDesc& DepthStencilDesc, D3D_DEPTH_STENCIL_DESC& d3dDSSDesc) -{ - // D3D_DEPTH_STENCIL_DESC is identical to D3D11_DEPTH_STENCIL_DESC - d3dDSSDesc.DepthEnable = DepthStencilDesc.DepthEnable ? TRUE : FALSE; - d3dDSSDesc.DepthWriteMask = DepthStencilDesc.DepthWriteEnable ? D3D_DEPTH_WRITE_MASK_ALL : D3D_DEPTH_WRITE_MASK_ZERO; - d3dDSSDesc.DepthFunc = ComparisonFuncToD3DComparisonFunc(DepthStencilDesc.DepthFunc); - d3dDSSDesc.StencilEnable = DepthStencilDesc.StencilEnable ? TRUE : FALSE; - d3dDSSDesc.StencilReadMask = DepthStencilDesc.StencilReadMask; - d3dDSSDesc.StencilWriteMask = DepthStencilDesc.StencilWriteMask; - d3dDSSDesc.FrontFace = StencilOpDescToD3DStencilOpDesc(DepthStencilDesc.FrontFace); - d3dDSSDesc.BackFace = StencilOpDescToD3DStencilOpDesc(DepthStencilDesc.BackFace); -} - - - -template -void LayoutElements_To_D3D_INPUT_ELEMENT_DESCs(const InputLayoutDesc& InputLayout, - std::vector>& D3DInputElements) -{ - // D3D12_INPUT_ELEMENT_DESC and D3D11_INPUT_ELEMENT_DESC are identical - D3DInputElements.resize(InputLayout.NumElements); - for (Uint32 iElem = 0; iElem < InputLayout.NumElements; ++iElem) - { - const auto& CurrElem = InputLayout.LayoutElements[iElem]; - auto& D3DElem = D3DInputElements[iElem]; - D3DElem.SemanticName = CurrElem.HLSLSemantic; - D3DElem.SemanticIndex = CurrElem.InputIndex; - D3DElem.AlignedByteOffset = CurrElem.RelativeOffset; - D3DElem.InputSlot = CurrElem.BufferSlot; - D3DElem.Format = TypeToDXGI_Format(CurrElem.ValueType, CurrElem.NumComponents, CurrElem.IsNormalized); - D3DElem.InputSlotClass = (CurrElem.Frequency == INPUT_ELEMENT_FREQUENCY_PER_VERTEX) ? D3D_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; - D3DElem.InstanceDataStepRate = (CurrElem.Frequency == INPUT_ELEMENT_FREQUENCY_PER_VERTEX) ? 0 : CurrElem.InstanceDataStepRate; - } -} - - -template -D3D_FILTER FilterTypeToD3DFilter(FILTER_TYPE MinFilter, FILTER_TYPE MagFilter, FILTER_TYPE MipFilter) -{ - switch (MinFilter) - { - // Regular filters - case FILTER_TYPE_POINT: - if (MagFilter == FILTER_TYPE_POINT) - { - if (MipFilter == FILTER_TYPE_POINT) - return D3D_FILTER_MIN_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_LINEAR) - return D3D_FILTER_MIN_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_LINEAR) - { - if (MipFilter == FILTER_TYPE_POINT) - return D3D_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_LINEAR) - return D3D_FILTER_MIN_POINT_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_LINEAR: - if (MagFilter == FILTER_TYPE_POINT) - { - if (MipFilter == FILTER_TYPE_POINT) - return D3D_FILTER_MIN_LINEAR_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_LINEAR) - return D3D_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_LINEAR) - { - if (MipFilter == FILTER_TYPE_POINT) - return D3D_FILTER_MIN_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_LINEAR) - return D3D_FILTER_MIN_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_ANISOTROPIC: - VERIFY(MagFilter == FILTER_TYPE_ANISOTROPIC && MipFilter == FILTER_TYPE_ANISOTROPIC, - "For anistropic filtering, all filters must be anisotropic"); - return D3D_FILTER_ANISOTROPIC; - break; - - - - // Comparison filters - case FILTER_TYPE_COMPARISON_POINT: - if (MagFilter == FILTER_TYPE_COMPARISON_POINT) - { - if (MipFilter == FILTER_TYPE_COMPARISON_POINT) - return D3D_FILTER_COMPARISON_MIN_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) - return D3D_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_COMPARISON_LINEAR) - { - if (MipFilter == FILTER_TYPE_COMPARISON_POINT) - return D3D_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) - return D3D_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_COMPARISON_LINEAR: - if (MagFilter == FILTER_TYPE_COMPARISON_POINT) - { - if (MipFilter == FILTER_TYPE_COMPARISON_POINT) - return D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) - return D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_COMPARISON_LINEAR) - { - if (MipFilter == FILTER_TYPE_COMPARISON_POINT) - return D3D_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) - return D3D_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_COMPARISON_ANISOTROPIC: - VERIFY(MagFilter == FILTER_TYPE_COMPARISON_ANISOTROPIC && MipFilter == FILTER_TYPE_COMPARISON_ANISOTROPIC, - "For comparison anistropic filtering, all filters must be anisotropic"); - return D3D_FILTER_COMPARISON_ANISOTROPIC; - break; - - - - // Minimum filters - case FILTER_TYPE_MINIMUM_POINT: - if (MagFilter == FILTER_TYPE_MINIMUM_POINT) - { - if (MipFilter == FILTER_TYPE_MINIMUM_POINT) - return D3D_FILTER_MINIMUM_MIN_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) - return D3D_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_MINIMUM_LINEAR) - { - if (MipFilter == FILTER_TYPE_MINIMUM_POINT) - return D3D_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) - return D3D_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_MINIMUM_LINEAR: - if (MagFilter == FILTER_TYPE_MINIMUM_POINT) - { - if (MipFilter == FILTER_TYPE_MINIMUM_POINT) - return D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) - return D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_MINIMUM_LINEAR) - { - if (MipFilter == FILTER_TYPE_MINIMUM_POINT) - return D3D_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) - return D3D_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_MINIMUM_ANISOTROPIC: - VERIFY(MagFilter == FILTER_TYPE_MINIMUM_ANISOTROPIC && MipFilter == FILTER_TYPE_MINIMUM_ANISOTROPIC, - "For minimum anistropic filtering, all filters must be anisotropic"); - return D3D_FILTER_MINIMUM_ANISOTROPIC; - break; - - - - // Maximum filters - case FILTER_TYPE_MAXIMUM_POINT: - if (MagFilter == FILTER_TYPE_MAXIMUM_POINT) - { - if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) - return D3D_FILTER_MAXIMUM_MIN_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) - return D3D_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_MAXIMUM_LINEAR) - { - if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) - return D3D_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) - return D3D_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_MAXIMUM_LINEAR: - if (MagFilter == FILTER_TYPE_MAXIMUM_POINT) - { - if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) - return D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) - return D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - } - else if (MagFilter == FILTER_TYPE_MAXIMUM_LINEAR) - { - if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) - return D3D_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT; - else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) - return D3D_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR; - } - break; - - case FILTER_TYPE_MAXIMUM_ANISOTROPIC: - VERIFY(MagFilter == FILTER_TYPE_MAXIMUM_ANISOTROPIC && MipFilter == FILTER_TYPE_MAXIMUM_ANISOTROPIC, - "For maximum anistropic filtering, all filters must be anisotropic"); - return D3D_FILTER_MAXIMUM_ANISOTROPIC; - break; - } - - UNEXPECTED("Unsupported filter combination"); - return D3D_FILTER_MIN_MAG_MIP_POINT; -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.hpp new file mode 100644 index 00000000..0e2c684d --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/D3DTypeConversionImpl.hpp @@ -0,0 +1,589 @@ +/* + * Copyright 2019-2020 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 + +#include + +/// \file +/// Implementation of D3D type conversions + +/// This file must be included after D3D11TypeDefinitions.h or D3D12TypeDefinitions.h + +namespace Diligent +{ + +template +inline D3D_COMPARISON_FUNC ComparisonFuncToD3DComparisonFunc(COMPARISON_FUNCTION Func) +{ + // D3D12_COMPARISON_FUNC is equal to D3D11_COMPARISON_FUNC + switch (Func) + { + // clang-format off + case COMPARISON_FUNC_UNKNOWN: UNEXPECTED("Comparison function is not specified" ); return D3D_COMPARISON_FUNC_ALWAYS; + case COMPARISON_FUNC_NEVER: return D3D_COMPARISON_FUNC_NEVER; + case COMPARISON_FUNC_LESS: return D3D_COMPARISON_FUNC_LESS; + case COMPARISON_FUNC_EQUAL: return D3D_COMPARISON_FUNC_EQUAL; + case COMPARISON_FUNC_LESS_EQUAL: return D3D_COMPARISON_FUNC_LESS_EQUAL; + case COMPARISON_FUNC_GREATER: return D3D_COMPARISON_FUNC_GREATER; + case COMPARISON_FUNC_NOT_EQUAL: return D3D_COMPARISON_FUNC_NOT_EQUAL; + case COMPARISON_FUNC_GREATER_EQUAL: return D3D_COMPARISON_FUNC_GREATER_EQUAL; + case COMPARISON_FUNC_ALWAYS: return D3D_COMPARISON_FUNC_ALWAYS; + default: UNEXPECTED("Unknown comparison function" ); return D3D_COMPARISON_FUNC_ALWAYS; + // clang-format on + } +} + + +template +D3D_TEXTURE_ADDRESS_MODE TexAddressModeToD3DAddressMode(TEXTURE_ADDRESS_MODE Mode) +{ + switch (Mode) + { + // clang-format off + case TEXTURE_ADDRESS_UNKNOWN: UNEXPECTED("Texture address mode is not specified" ); return D3D_TEXTURE_ADDRESS_CLAMP; + case TEXTURE_ADDRESS_WRAP: return D3D_TEXTURE_ADDRESS_WRAP; + case TEXTURE_ADDRESS_MIRROR: return D3D_TEXTURE_ADDRESS_MIRROR; + case TEXTURE_ADDRESS_CLAMP: return D3D_TEXTURE_ADDRESS_CLAMP; + case TEXTURE_ADDRESS_BORDER: return D3D_TEXTURE_ADDRESS_BORDER; + case TEXTURE_ADDRESS_MIRROR_ONCE: return D3D_TEXTURE_ADDRESS_MIRROR_ONCE; + default: UNEXPECTED("Unknown texture address mode" ); return D3D_TEXTURE_ADDRESS_CLAMP; + // clang-format on + } +} + +template +D3D_PRIM_TOPOLOGY TopologyToD3DTopology(PRIMITIVE_TOPOLOGY Topology) +{ + static bool bIsInit = false; + static std::array d3dPrimTopology = {}; + if (!bIsInit) + { + // clang-format off + d3dPrimTopology[PRIMITIVE_TOPOLOGY_UNDEFINED] = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_POINT_LIST] = D3D_PRIMITIVE_TOPOLOGY_POINTLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_LINE_LIST] = D3D_PRIMITIVE_TOPOLOGY_LINELIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST; + d3dPrimTopology[PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST] = D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST; + // clang-format on + bIsInit = true; + } + + VERIFY_EXPR(Topology >= PRIMITIVE_TOPOLOGY_UNDEFINED && Topology < PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES); + return d3dPrimTopology[Topology]; +} + + +// ================= Rasterizer state attributes conversion functions ================= + +template +D3D_FILL_MODE FillModeToD3DFillMode(FILL_MODE FillMode) +{ + // D3D12_FILL_MODE is identical tp D3D11_FILL_MODE + static bool bIsInit = false; + static std::array d3dFillModes = {}; + if (!bIsInit) + { + d3dFillModes[FILL_MODE_WIREFRAME] = D3D_FILL_MODE_WIREFRAME; + d3dFillModes[FILL_MODE_SOLID] = D3D_FILL_MODE_SOLID; + + bIsInit = true; + } + if (FILL_MODE_UNDEFINED < FillMode && FillMode < FILL_MODE_NUM_MODES) + { + auto d3dFillMode = d3dFillModes[FillMode]; + VERIFY(d3dFillMode != 0, "Incorrect fill mode"); + return d3dFillMode; + } + else + { + UNEXPECTED("Incorrect fill mode (", FillMode, ")"); + return static_cast(0); + } +} + +template +D3D_CULL_MODE CullModeToD3DCullMode(CULL_MODE CullMode) +{ + // D3D_CULL_MODE is identical to D3D11_CULL_MODE + static bool bIsInit = false; + static std::array d3dCullModes = {}; + if (!bIsInit) + { + d3dCullModes[CULL_MODE_NONE] = D3D_CULL_MODE_NONE; + d3dCullModes[CULL_MODE_FRONT] = D3D_CULL_MODE_FRONT; + d3dCullModes[CULL_MODE_BACK] = D3D_CULL_MODE_BACK; + + bIsInit = true; + } + + if (CULL_MODE_UNDEFINED < CullMode && CullMode < CULL_MODE_NUM_MODES) + { + auto d3dCullMode = d3dCullModes[CullMode]; + VERIFY(d3dCullMode != 0, "Incorrect cull mode"); + return d3dCullMode; + } + else + { + UNEXPECTED("Incorrect cull mode (", CullMode, ")"); + return static_cast(0); + } +} + +template +void RasterizerStateDesc_To_D3D_RASTERIZER_DESC(const RasterizerStateDesc& RasterizerDesc, D3D_RASTERIZER_DESC& d3dRSDesc) +{ + d3dRSDesc.FillMode = FillModeToD3DFillMode(RasterizerDesc.FillMode); + d3dRSDesc.CullMode = CullModeToD3DCullMode(RasterizerDesc.CullMode); + d3dRSDesc.FrontCounterClockwise = RasterizerDesc.FrontCounterClockwise ? TRUE : FALSE; + d3dRSDesc.DepthBias = RasterizerDesc.DepthBias; + d3dRSDesc.DepthBiasClamp = RasterizerDesc.DepthBiasClamp; + d3dRSDesc.SlopeScaledDepthBias = RasterizerDesc.SlopeScaledDepthBias; + d3dRSDesc.DepthClipEnable = RasterizerDesc.DepthClipEnable ? TRUE : FALSE; + + //d3d12RSDesc.ScissorEnable = RSDesc.ScissorEnable ? TRUE : FALSE; + + d3dRSDesc.AntialiasedLineEnable = RasterizerDesc.AntialiasedLineEnable ? TRUE : FALSE; + d3dRSDesc.MultisampleEnable = d3dRSDesc.AntialiasedLineEnable; +} + + + +// ================= Blend state attributes conversion functions ================= + +template +D3D_BLEND BlendFactorToD3DBlend(BLEND_FACTOR bf) +{ + // D3D11_BLEND and D3D12_BLEND are identical + + // Note that this code is safe for multithreaded environments since + // bIsInit is set to true only AFTER the entire map is initialized. + static bool bIsInit = false; + static std::array D3DBlend = {}; + if (!bIsInit) + { + // In a multithreaded environment, several threads can potentially enter + // this block. This is not a problem since they will just initialize the + // memory with the same values more than once + + // clang-format off + D3DBlend[BLEND_FACTOR_ZERO ] = D3D_BLEND_ZERO; + D3DBlend[BLEND_FACTOR_ONE ] = D3D_BLEND_ONE; + D3DBlend[BLEND_FACTOR_SRC_COLOR ] = D3D_BLEND_SRC_COLOR; + D3DBlend[BLEND_FACTOR_INV_SRC_COLOR ] = D3D_BLEND_INV_SRC_COLOR; + D3DBlend[BLEND_FACTOR_SRC_ALPHA ] = D3D_BLEND_SRC_ALPHA; + D3DBlend[BLEND_FACTOR_INV_SRC_ALPHA ] = D3D_BLEND_INV_SRC_ALPHA; + D3DBlend[BLEND_FACTOR_DEST_ALPHA ] = D3D_BLEND_DEST_ALPHA; + D3DBlend[BLEND_FACTOR_INV_DEST_ALPHA ] = D3D_BLEND_INV_DEST_ALPHA; + D3DBlend[BLEND_FACTOR_DEST_COLOR ] = D3D_BLEND_DEST_COLOR; + D3DBlend[BLEND_FACTOR_INV_DEST_COLOR ] = D3D_BLEND_INV_DEST_COLOR; + D3DBlend[BLEND_FACTOR_SRC_ALPHA_SAT ] = D3D_BLEND_SRC_ALPHA_SAT; + D3DBlend[BLEND_FACTOR_BLEND_FACTOR ] = D3D_BLEND_BLEND_FACTOR; + D3DBlend[BLEND_FACTOR_INV_BLEND_FACTOR] = D3D_BLEND_INV_BLEND_FACTOR; + D3DBlend[BLEND_FACTOR_SRC1_COLOR ] = D3D_BLEND_SRC1_COLOR; + D3DBlend[BLEND_FACTOR_INV_SRC1_COLOR ] = D3D_BLEND_INV_SRC1_COLOR; + D3DBlend[BLEND_FACTOR_SRC1_ALPHA ] = D3D_BLEND_SRC1_ALPHA; + D3DBlend[BLEND_FACTOR_INV_SRC1_ALPHA ] = D3D_BLEND_INV_SRC1_ALPHA; + // clang-format on + + bIsInit = true; + } + if (bf > BLEND_FACTOR_UNDEFINED && bf < BLEND_FACTOR_NUM_FACTORS) + { + auto d3dbf = D3DBlend[bf]; + VERIFY(d3dbf != 0, "Incorrect blend factor"); + return d3dbf; + } + else + { + UNEXPECTED("Incorrect blend factor (", bf, ")"); + return static_cast(0); + } +} + +template +D3D_BLEND_OP BlendOperationToD3DBlendOp(BLEND_OPERATION BlendOp) +{ + // D3D12_BLEND_OP and D3D11_BLEND_OP are identical + + static bool bIsInit = false; + static std::array D3DBlendOp = {}; + if (!bIsInit) + { + // clang-format off + D3DBlendOp[BLEND_OPERATION_ADD ] = D3D_BLEND_OP_ADD; + D3DBlendOp[BLEND_OPERATION_SUBTRACT ] = D3D_BLEND_OP_SUBTRACT; + D3DBlendOp[BLEND_OPERATION_REV_SUBTRACT] = D3D_BLEND_OP_REV_SUBTRACT; + D3DBlendOp[BLEND_OPERATION_MIN ] = D3D_BLEND_OP_MIN; + D3DBlendOp[BLEND_OPERATION_MAX ] = D3D_BLEND_OP_MAX; + // clang-format on + + bIsInit = true; + } + + if (BlendOp > BLEND_OPERATION_UNDEFINED && BlendOp < BLEND_OPERATION_NUM_OPERATIONS) + { + auto d3dbop = D3DBlendOp[BlendOp]; + VERIFY(d3dbop != 0, "Incorrect blend operation"); + return d3dbop; + } + else + { + UNEXPECTED("Incorrect blend operation (", BlendOp, ")"); + return static_cast(0); + } +} + +template +void BlendStateDescToD3DBlendDesc(const BlendStateDesc& BSDesc, D3D_BLEND_DESC& d3d12BlendDesc) +{ + // D3D_BLEND_DESC and D3D11_BLEND_DESC structures are identical + d3d12BlendDesc.AlphaToCoverageEnable = BSDesc.AlphaToCoverageEnable ? TRUE : FALSE; + d3d12BlendDesc.IndependentBlendEnable = BSDesc.IndependentBlendEnable ? TRUE : FALSE; + VERIFY(MAX_RENDER_TARGETS >= 8, "Number of render targets is expected to be at least 8"); + for (int i = 0; i < 8; ++i) + { + const auto& SrcRTDesc = BSDesc.RenderTargets[i]; + auto& DstRTDesc = d3d12BlendDesc.RenderTarget[i]; + DstRTDesc.BlendEnable = SrcRTDesc.BlendEnable ? TRUE : FALSE; + + DstRTDesc.SrcBlend = BlendFactorToD3DBlend(SrcRTDesc.SrcBlend); + DstRTDesc.DestBlend = BlendFactorToD3DBlend(SrcRTDesc.DestBlend); + DstRTDesc.BlendOp = BlendOperationToD3DBlendOp(SrcRTDesc.BlendOp); + + DstRTDesc.SrcBlendAlpha = BlendFactorToD3DBlend(SrcRTDesc.SrcBlendAlpha); + DstRTDesc.DestBlendAlpha = BlendFactorToD3DBlend(SrcRTDesc.DestBlendAlpha); + DstRTDesc.BlendOpAlpha = BlendOperationToD3DBlendOp(SrcRTDesc.BlendOpAlpha); + + DstRTDesc.RenderTargetWriteMask = + ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_RED) ? D3D_COLOR_WRITE_ENABLE_RED : 0) | + ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_GREEN) ? D3D_COLOR_WRITE_ENABLE_GREEN : 0) | + ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_BLUE) ? D3D_COLOR_WRITE_ENABLE_BLUE : 0) | + ((SrcRTDesc.RenderTargetWriteMask & COLOR_MASK_ALPHA) ? D3D_COLOR_WRITE_ENABLE_ALPHA : 0); + } +} + + + +// ====================== Depth-stencil state attributes conversion functions ====================== + +template +D3D_STENCIL_OP StencilOpToD3DStencilOp(STENCIL_OP StencilOp) +{ + static bool bIsInit = false; + static std::array StOpToD3DStOpMap = {}; + if (!bIsInit) + { + // clang-format off + StOpToD3DStOpMap[STENCIL_OP_KEEP ] = D3D_STENCIL_OP_KEEP; + StOpToD3DStOpMap[STENCIL_OP_ZERO ] = D3D_STENCIL_OP_ZERO; + StOpToD3DStOpMap[STENCIL_OP_REPLACE ] = D3D_STENCIL_OP_REPLACE; + StOpToD3DStOpMap[STENCIL_OP_INCR_SAT ] = D3D_STENCIL_OP_INCR_SAT; + StOpToD3DStOpMap[STENCIL_OP_DECR_SAT ] = D3D_STENCIL_OP_DECR_SAT; + StOpToD3DStOpMap[STENCIL_OP_INVERT ] = D3D_STENCIL_OP_INVERT; + StOpToD3DStOpMap[STENCIL_OP_INCR_WRAP] = D3D_STENCIL_OP_INCR; + StOpToD3DStOpMap[STENCIL_OP_DECR_WRAP] = D3D_STENCIL_OP_DECR; + // clang-format on + + bIsInit = true; + } + + if (StencilOp > STENCIL_OP_UNDEFINED && StencilOp < STENCIL_OP_NUM_OPS) + { + auto d3dStencilOp = StOpToD3DStOpMap[StencilOp]; + VERIFY(d3dStencilOp != 0, "Unexpected stencil op"); + return d3dStencilOp; + } + else + { + UNEXPECTED("Stencil operation (", StencilOp, ") is out of allowed range [1, ", STENCIL_OP_NUM_OPS - 1, "]"); + return static_cast(0); + } +} + +template +D3D_DEPTH_STENCILOP_DESC StencilOpDescToD3DStencilOpDesc(const StencilOpDesc& StOpDesc) +{ + // D3D12_DEPTH_STENCILOP_DESC is identical to D3D11_DEPTH_STENCILOP_DESC + D3D_DEPTH_STENCILOP_DESC D3DStOpDesc; + D3DStOpDesc.StencilFailOp = StencilOpToD3DStencilOp(StOpDesc.StencilFailOp); + D3DStOpDesc.StencilDepthFailOp = StencilOpToD3DStencilOp(StOpDesc.StencilDepthFailOp); + D3DStOpDesc.StencilPassOp = StencilOpToD3DStencilOp(StOpDesc.StencilPassOp); + D3DStOpDesc.StencilFunc = ComparisonFuncToD3DComparisonFunc(StOpDesc.StencilFunc); + return D3DStOpDesc; +} + +template +void DepthStencilStateDesc_To_D3D_DEPTH_STENCIL_DESC(const DepthStencilStateDesc& DepthStencilDesc, D3D_DEPTH_STENCIL_DESC& d3dDSSDesc) +{ + // D3D_DEPTH_STENCIL_DESC is identical to D3D11_DEPTH_STENCIL_DESC + d3dDSSDesc.DepthEnable = DepthStencilDesc.DepthEnable ? TRUE : FALSE; + d3dDSSDesc.DepthWriteMask = DepthStencilDesc.DepthWriteEnable ? D3D_DEPTH_WRITE_MASK_ALL : D3D_DEPTH_WRITE_MASK_ZERO; + d3dDSSDesc.DepthFunc = ComparisonFuncToD3DComparisonFunc(DepthStencilDesc.DepthFunc); + d3dDSSDesc.StencilEnable = DepthStencilDesc.StencilEnable ? TRUE : FALSE; + d3dDSSDesc.StencilReadMask = DepthStencilDesc.StencilReadMask; + d3dDSSDesc.StencilWriteMask = DepthStencilDesc.StencilWriteMask; + d3dDSSDesc.FrontFace = StencilOpDescToD3DStencilOpDesc(DepthStencilDesc.FrontFace); + d3dDSSDesc.BackFace = StencilOpDescToD3DStencilOpDesc(DepthStencilDesc.BackFace); +} + + + +template +void LayoutElements_To_D3D_INPUT_ELEMENT_DESCs(const InputLayoutDesc& InputLayout, + std::vector>& D3DInputElements) +{ + // D3D12_INPUT_ELEMENT_DESC and D3D11_INPUT_ELEMENT_DESC are identical + D3DInputElements.resize(InputLayout.NumElements); + for (Uint32 iElem = 0; iElem < InputLayout.NumElements; ++iElem) + { + const auto& CurrElem = InputLayout.LayoutElements[iElem]; + auto& D3DElem = D3DInputElements[iElem]; + D3DElem.SemanticName = CurrElem.HLSLSemantic; + D3DElem.SemanticIndex = CurrElem.InputIndex; + D3DElem.AlignedByteOffset = CurrElem.RelativeOffset; + D3DElem.InputSlot = CurrElem.BufferSlot; + D3DElem.Format = TypeToDXGI_Format(CurrElem.ValueType, CurrElem.NumComponents, CurrElem.IsNormalized); + D3DElem.InputSlotClass = (CurrElem.Frequency == INPUT_ELEMENT_FREQUENCY_PER_VERTEX) ? D3D_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; + D3DElem.InstanceDataStepRate = (CurrElem.Frequency == INPUT_ELEMENT_FREQUENCY_PER_VERTEX) ? 0 : CurrElem.InstanceDataStepRate; + } +} + + +template +D3D_FILTER FilterTypeToD3DFilter(FILTER_TYPE MinFilter, FILTER_TYPE MagFilter, FILTER_TYPE MipFilter) +{ + switch (MinFilter) + { + // Regular filters + case FILTER_TYPE_POINT: + if (MagFilter == FILTER_TYPE_POINT) + { + if (MipFilter == FILTER_TYPE_POINT) + return D3D_FILTER_MIN_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_LINEAR) + return D3D_FILTER_MIN_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_LINEAR) + { + if (MipFilter == FILTER_TYPE_POINT) + return D3D_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_LINEAR) + return D3D_FILTER_MIN_POINT_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_LINEAR: + if (MagFilter == FILTER_TYPE_POINT) + { + if (MipFilter == FILTER_TYPE_POINT) + return D3D_FILTER_MIN_LINEAR_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_LINEAR) + return D3D_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_LINEAR) + { + if (MipFilter == FILTER_TYPE_POINT) + return D3D_FILTER_MIN_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_LINEAR) + return D3D_FILTER_MIN_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_ANISOTROPIC: + VERIFY(MagFilter == FILTER_TYPE_ANISOTROPIC && MipFilter == FILTER_TYPE_ANISOTROPIC, + "For anistropic filtering, all filters must be anisotropic"); + return D3D_FILTER_ANISOTROPIC; + break; + + + + // Comparison filters + case FILTER_TYPE_COMPARISON_POINT: + if (MagFilter == FILTER_TYPE_COMPARISON_POINT) + { + if (MipFilter == FILTER_TYPE_COMPARISON_POINT) + return D3D_FILTER_COMPARISON_MIN_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) + return D3D_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_COMPARISON_LINEAR) + { + if (MipFilter == FILTER_TYPE_COMPARISON_POINT) + return D3D_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) + return D3D_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_COMPARISON_LINEAR: + if (MagFilter == FILTER_TYPE_COMPARISON_POINT) + { + if (MipFilter == FILTER_TYPE_COMPARISON_POINT) + return D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) + return D3D_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_COMPARISON_LINEAR) + { + if (MipFilter == FILTER_TYPE_COMPARISON_POINT) + return D3D_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_COMPARISON_LINEAR) + return D3D_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_COMPARISON_ANISOTROPIC: + VERIFY(MagFilter == FILTER_TYPE_COMPARISON_ANISOTROPIC && MipFilter == FILTER_TYPE_COMPARISON_ANISOTROPIC, + "For comparison anistropic filtering, all filters must be anisotropic"); + return D3D_FILTER_COMPARISON_ANISOTROPIC; + break; + + + + // Minimum filters + case FILTER_TYPE_MINIMUM_POINT: + if (MagFilter == FILTER_TYPE_MINIMUM_POINT) + { + if (MipFilter == FILTER_TYPE_MINIMUM_POINT) + return D3D_FILTER_MINIMUM_MIN_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) + return D3D_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_MINIMUM_LINEAR) + { + if (MipFilter == FILTER_TYPE_MINIMUM_POINT) + return D3D_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) + return D3D_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_MINIMUM_LINEAR: + if (MagFilter == FILTER_TYPE_MINIMUM_POINT) + { + if (MipFilter == FILTER_TYPE_MINIMUM_POINT) + return D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) + return D3D_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_MINIMUM_LINEAR) + { + if (MipFilter == FILTER_TYPE_MINIMUM_POINT) + return D3D_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MINIMUM_LINEAR) + return D3D_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_MINIMUM_ANISOTROPIC: + VERIFY(MagFilter == FILTER_TYPE_MINIMUM_ANISOTROPIC && MipFilter == FILTER_TYPE_MINIMUM_ANISOTROPIC, + "For minimum anistropic filtering, all filters must be anisotropic"); + return D3D_FILTER_MINIMUM_ANISOTROPIC; + break; + + + + // Maximum filters + case FILTER_TYPE_MAXIMUM_POINT: + if (MagFilter == FILTER_TYPE_MAXIMUM_POINT) + { + if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) + return D3D_FILTER_MAXIMUM_MIN_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) + return D3D_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_MAXIMUM_LINEAR) + { + if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) + return D3D_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) + return D3D_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_MAXIMUM_LINEAR: + if (MagFilter == FILTER_TYPE_MAXIMUM_POINT) + { + if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) + return D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) + return D3D_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } + else if (MagFilter == FILTER_TYPE_MAXIMUM_LINEAR) + { + if (MipFilter == FILTER_TYPE_MAXIMUM_POINT) + return D3D_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT; + else if (MipFilter == FILTER_TYPE_MAXIMUM_LINEAR) + return D3D_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR; + } + break; + + case FILTER_TYPE_MAXIMUM_ANISOTROPIC: + VERIFY(MagFilter == FILTER_TYPE_MAXIMUM_ANISOTROPIC && MipFilter == FILTER_TYPE_MAXIMUM_ANISOTROPIC, + "For maximum anistropic filtering, all filters must be anisotropic"); + return D3D_FILTER_MAXIMUM_ANISOTROPIC; + break; + } + + UNEXPECTED("Unsupported filter combination"); + return D3D_FILTER_MIN_MAG_MIP_POINT; +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.h b/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.h deleted file mode 100644 index 5f6939a8..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright 2019-2020 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 D3D type conversions - -/// This file must be included after D3D11TypeDefinitions.h or D3D12TypeDefinitions.h - -#include "DXGITypeConversions.h" - -namespace Diligent -{ - -template -void TextureViewDesc_to_D3D_SRV_DESC(const TextureViewDesc& SRVDesc, D3D_SHADER_RESOURCE_VIEW_DESC& d3dSRVDesc, Uint32 SampleCount) -{ - memset(&d3dSRVDesc, 0, sizeof(d3dSRVDesc)); - d3dSRVDesc.Format = TexFormatToDXGI_Format(SRVDesc.Format, BIND_SHADER_RESOURCE); - - switch (SRVDesc.TextureDim) - { - case RESOURCE_DIM_TEX_1D: - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D; - d3dSRVDesc.Texture1D.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.Texture1D.MostDetailedMip = SRVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY; - d3dSRVDesc.Texture1DArray.ArraySize = SRVDesc.NumArraySlices; - d3dSRVDesc.Texture1DArray.FirstArraySlice = SRVDesc.FirstArraySlice; - d3dSRVDesc.Texture1DArray.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.Texture1DArray.MostDetailedMip = SRVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_2D: - if (SampleCount > 1) - { - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; - d3dSRVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; - } - else - { - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; - d3dSRVDesc.Texture2D.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.Texture2D.MostDetailedMip = SRVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (SampleCount > 1) - { - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DMSARRAY; - d3dSRVDesc.Texture2DMSArray.ArraySize = SRVDesc.NumArraySlices; - d3dSRVDesc.Texture2DMSArray.FirstArraySlice = SRVDesc.FirstArraySlice; - } - else - { - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; - d3dSRVDesc.Texture2DArray.ArraySize = SRVDesc.NumArraySlices; - d3dSRVDesc.Texture2DArray.FirstArraySlice = SRVDesc.FirstArraySlice; - d3dSRVDesc.Texture2DArray.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.Texture2DArray.MostDetailedMip = SRVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_3D: - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D; - d3dSRVDesc.Texture3D.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.Texture3D.MostDetailedMip = SRVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_CUBE: - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE; - d3dSRVDesc.TextureCube.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.TextureCube.MostDetailedMip = SRVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_CUBE_ARRAY: - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY; - d3dSRVDesc.TextureCubeArray.MipLevels = SRVDesc.NumMipLevels; - d3dSRVDesc.TextureCubeArray.MostDetailedMip = SRVDesc.MostDetailedMip; - d3dSRVDesc.TextureCubeArray.First2DArrayFace = SRVDesc.FirstArraySlice; - d3dSRVDesc.TextureCubeArray.NumCubes = SRVDesc.NumArraySlices / 6; - break; - - default: - UNEXPECTED("Unexpected view type"); - } -} - -template -void TextureViewDesc_to_D3D_RTV_DESC(const TextureViewDesc& RTVDesc, D3D_RENDER_TARGET_VIEW_DESC& d3dRTVDesc, Uint32 SampleCount) -{ - memset(&d3dRTVDesc, 0, sizeof(d3dRTVDesc)); - d3dRTVDesc.Format = TexFormatToDXGI_Format(RTVDesc.Format, BIND_RENDER_TARGET); - - switch (RTVDesc.TextureDim) - { - case RESOURCE_DIM_TEX_1D: - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE1D; - d3dRTVDesc.Texture1D.MipSlice = RTVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE1DARRAY; - d3dRTVDesc.Texture1DArray.ArraySize = RTVDesc.NumArraySlices; - d3dRTVDesc.Texture1DArray.FirstArraySlice = RTVDesc.FirstArraySlice; - d3dRTVDesc.Texture1DArray.MipSlice = RTVDesc.MostDetailedMip; - break; - - - case RESOURCE_DIM_TEX_2D: - if (SampleCount > 1) - { - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DMS; - d3dRTVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; - } - else - { - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2D; - d3dRTVDesc.Texture2D.MipSlice = RTVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (SampleCount > 1) - { - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DMSARRAY; - d3dRTVDesc.Texture2DMSArray.ArraySize = RTVDesc.NumArraySlices; - d3dRTVDesc.Texture2DMSArray.FirstArraySlice = RTVDesc.FirstArraySlice; - } - else - { - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DARRAY; - d3dRTVDesc.Texture2DArray.ArraySize = RTVDesc.NumArraySlices; - d3dRTVDesc.Texture2DArray.FirstArraySlice = RTVDesc.FirstArraySlice; - d3dRTVDesc.Texture2DArray.MipSlice = RTVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_3D: - d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE3D; - d3dRTVDesc.Texture3D.FirstWSlice = RTVDesc.FirstDepthSlice; - d3dRTVDesc.Texture3D.WSize = RTVDesc.NumDepthSlices; - d3dRTVDesc.Texture3D.MipSlice = RTVDesc.MostDetailedMip; - break; - - default: - UNEXPECTED("Unexpected view type"); - } -} - -template -void TextureViewDesc_to_D3D_DSV_DESC(const TextureViewDesc& DSVDesc, D3D_DEPTH_STENCIL_VIEW_DESC& d3dDSVDesc, Uint32 SampleCount) -{ - memset(&d3dDSVDesc, 0, sizeof(d3dDSVDesc)); - d3dDSVDesc.Format = TexFormatToDXGI_Format(DSVDesc.Format, BIND_DEPTH_STENCIL); - - switch (DSVDesc.TextureDim) - { - case RESOURCE_DIM_TEX_1D: - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE1D; - d3dDSVDesc.Texture1D.MipSlice = DSVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE1DARRAY; - d3dDSVDesc.Texture1DArray.ArraySize = DSVDesc.NumArraySlices; - d3dDSVDesc.Texture1DArray.FirstArraySlice = DSVDesc.FirstArraySlice; - d3dDSVDesc.Texture1DArray.MipSlice = DSVDesc.MostDetailedMip; - break; - - - case RESOURCE_DIM_TEX_2D: - if (SampleCount > 1) - { - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DMS; - d3dDSVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; - } - else - { - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2D; - d3dDSVDesc.Texture2D.MipSlice = DSVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (SampleCount > 1) - { - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DMSARRAY; - d3dDSVDesc.Texture2DMSArray.ArraySize = DSVDesc.NumArraySlices; - d3dDSVDesc.Texture2DMSArray.FirstArraySlice = DSVDesc.FirstArraySlice; - } - else - { - d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DARRAY; - d3dDSVDesc.Texture2DArray.ArraySize = DSVDesc.NumArraySlices; - d3dDSVDesc.Texture2DArray.FirstArraySlice = DSVDesc.FirstArraySlice; - d3dDSVDesc.Texture2DArray.MipSlice = DSVDesc.MostDetailedMip; - } - break; - - case RESOURCE_DIM_TEX_3D: - LOG_ERROR_AND_THROW("Depth stencil views are not supported for 3D textures"); - break; - - default: - UNEXPECTED("Unexpected view type"); - } -} - -template -void TextureViewDesc_to_D3D_UAV_DESC(const TextureViewDesc& UAVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dUAVDesc) -{ - memset(&d3dUAVDesc, 0, sizeof(d3dUAVDesc)); - d3dUAVDesc.Format = TexFormatToDXGI_Format(UAVDesc.Format, BIND_UNORDERED_ACCESS); - - switch (UAVDesc.TextureDim) - { - case RESOURCE_DIM_TEX_1D: - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE1D; - d3dUAVDesc.Texture1D.MipSlice = UAVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE1DARRAY; - d3dUAVDesc.Texture1DArray.ArraySize = UAVDesc.NumArraySlices; - d3dUAVDesc.Texture1DArray.FirstArraySlice = UAVDesc.FirstArraySlice; - d3dUAVDesc.Texture1DArray.MipSlice = UAVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_2D: - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE2D; - d3dUAVDesc.Texture2D.MipSlice = UAVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE2DARRAY; - d3dUAVDesc.Texture2DArray.ArraySize = UAVDesc.NumArraySlices; - d3dUAVDesc.Texture2DArray.FirstArraySlice = UAVDesc.FirstArraySlice; - d3dUAVDesc.Texture2DArray.MipSlice = UAVDesc.MostDetailedMip; - break; - - case RESOURCE_DIM_TEX_3D: - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE3D; - d3dUAVDesc.Texture3D.FirstWSlice = UAVDesc.FirstDepthSlice; - d3dUAVDesc.Texture3D.WSize = UAVDesc.NumDepthSlices; - d3dUAVDesc.Texture3D.MipSlice = UAVDesc.MostDetailedMip; - break; - - default: - UNEXPECTED("Unexpected view type"); - } -} - -template -void BufferViewDesc_to_D3D_SRV_DESC(const BufferDesc& BuffDesc, const BufferViewDesc& SRVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dSRVDesc) -{ - VERIFY(SRVDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Incorrect view type: shader resource is expected"); - - memset(&d3dSRVDesc, 0, sizeof(d3dSRVDesc)); - const auto& BuffFmt = SRVDesc.Format; - if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) - d3dSRVDesc.Format = TypeToDXGI_Format(BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized); - - Uint32 ElementByteStride = 0; - if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) - ElementByteStride = BuffDesc.ElementByteStride; - else if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType == VT_UNDEFINED) - ElementByteStride = 4; - - if (ElementByteStride != 0) - { - DEV_CHECK_ERR((SRVDesc.ByteOffset % ElementByteStride) == 0, "Byte offest (", SRVDesc.ByteOffset, ") is not multiple of element byte stride (", ElementByteStride, ")"); - DEV_CHECK_ERR((SRVDesc.ByteWidth % ElementByteStride) == 0, "Byte width (", SRVDesc.ByteWidth, ")is not multiple of element byte stride (", ElementByteStride, ")"); - d3dSRVDesc.Buffer.FirstElement = SRVDesc.ByteOffset / ElementByteStride; - d3dSRVDesc.Buffer.NumElements = SRVDesc.ByteWidth / ElementByteStride; - } - d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_BUFFER; -} - -template -void BufferViewDesc_to_D3D_UAV_DESC(const BufferDesc& BuffDesc, const BufferViewDesc& UAVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dUAVDesc) -{ - VERIFY(UAVDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Incorrect view type: unordered access is expected"); - - memset(&d3dUAVDesc, 0, sizeof(d3dUAVDesc)); - const auto& BuffFmt = UAVDesc.Format; - if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) - d3dUAVDesc.Format = TypeToDXGI_Format(BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized); - - Uint32 ElementByteStride = 0; - if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) - ElementByteStride = BuffDesc.ElementByteStride; - else if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType == VT_UNDEFINED) - ElementByteStride = 4; - - if (ElementByteStride != 0) - { - DEV_CHECK_ERR((UAVDesc.ByteOffset % ElementByteStride) == 0, "Byte offest (", UAVDesc.ByteOffset, ") is not multiple of element byte stride (", ElementByteStride, ")"); - DEV_CHECK_ERR((UAVDesc.ByteWidth % ElementByteStride) == 0, "Byte width (", UAVDesc.ByteWidth, ")is not multiple of element byte stride (", ElementByteStride, ")"); - d3dUAVDesc.Buffer.FirstElement = UAVDesc.ByteOffset / ElementByteStride; - d3dUAVDesc.Buffer.NumElements = UAVDesc.ByteWidth / ElementByteStride; - } - - if (BuffDesc.Mode == BUFFER_MODE_RAW && UAVDesc.Format.ValueType == VT_UNDEFINED) - { - d3dUAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; - d3dUAVDesc.Buffer.Flags = D3D_BUFFER_UAV_FLAG_RAW; - } - else - d3dUAVDesc.Buffer.Flags = D3D_BUFFER_UAV_FLAG_NONE; - - d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_BUFFER; -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.hpp new file mode 100644 index 00000000..5f6939a8 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/D3DViewDescConversionImpl.hpp @@ -0,0 +1,344 @@ +/* + * Copyright 2019-2020 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 D3D type conversions + +/// This file must be included after D3D11TypeDefinitions.h or D3D12TypeDefinitions.h + +#include "DXGITypeConversions.h" + +namespace Diligent +{ + +template +void TextureViewDesc_to_D3D_SRV_DESC(const TextureViewDesc& SRVDesc, D3D_SHADER_RESOURCE_VIEW_DESC& d3dSRVDesc, Uint32 SampleCount) +{ + memset(&d3dSRVDesc, 0, sizeof(d3dSRVDesc)); + d3dSRVDesc.Format = TexFormatToDXGI_Format(SRVDesc.Format, BIND_SHADER_RESOURCE); + + switch (SRVDesc.TextureDim) + { + case RESOURCE_DIM_TEX_1D: + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D; + d3dSRVDesc.Texture1D.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.Texture1D.MostDetailedMip = SRVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY; + d3dSRVDesc.Texture1DArray.ArraySize = SRVDesc.NumArraySlices; + d3dSRVDesc.Texture1DArray.FirstArraySlice = SRVDesc.FirstArraySlice; + d3dSRVDesc.Texture1DArray.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.Texture1DArray.MostDetailedMip = SRVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_2D: + if (SampleCount > 1) + { + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DMS; + d3dSRVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; + } + else + { + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + d3dSRVDesc.Texture2D.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.Texture2D.MostDetailedMip = SRVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (SampleCount > 1) + { + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DMSARRAY; + d3dSRVDesc.Texture2DMSArray.ArraySize = SRVDesc.NumArraySlices; + d3dSRVDesc.Texture2DMSArray.FirstArraySlice = SRVDesc.FirstArraySlice; + } + else + { + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + d3dSRVDesc.Texture2DArray.ArraySize = SRVDesc.NumArraySlices; + d3dSRVDesc.Texture2DArray.FirstArraySlice = SRVDesc.FirstArraySlice; + d3dSRVDesc.Texture2DArray.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.Texture2DArray.MostDetailedMip = SRVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_3D: + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D; + d3dSRVDesc.Texture3D.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.Texture3D.MostDetailedMip = SRVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_CUBE: + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE; + d3dSRVDesc.TextureCube.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.TextureCube.MostDetailedMip = SRVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_CUBE_ARRAY: + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY; + d3dSRVDesc.TextureCubeArray.MipLevels = SRVDesc.NumMipLevels; + d3dSRVDesc.TextureCubeArray.MostDetailedMip = SRVDesc.MostDetailedMip; + d3dSRVDesc.TextureCubeArray.First2DArrayFace = SRVDesc.FirstArraySlice; + d3dSRVDesc.TextureCubeArray.NumCubes = SRVDesc.NumArraySlices / 6; + break; + + default: + UNEXPECTED("Unexpected view type"); + } +} + +template +void TextureViewDesc_to_D3D_RTV_DESC(const TextureViewDesc& RTVDesc, D3D_RENDER_TARGET_VIEW_DESC& d3dRTVDesc, Uint32 SampleCount) +{ + memset(&d3dRTVDesc, 0, sizeof(d3dRTVDesc)); + d3dRTVDesc.Format = TexFormatToDXGI_Format(RTVDesc.Format, BIND_RENDER_TARGET); + + switch (RTVDesc.TextureDim) + { + case RESOURCE_DIM_TEX_1D: + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE1D; + d3dRTVDesc.Texture1D.MipSlice = RTVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE1DARRAY; + d3dRTVDesc.Texture1DArray.ArraySize = RTVDesc.NumArraySlices; + d3dRTVDesc.Texture1DArray.FirstArraySlice = RTVDesc.FirstArraySlice; + d3dRTVDesc.Texture1DArray.MipSlice = RTVDesc.MostDetailedMip; + break; + + + case RESOURCE_DIM_TEX_2D: + if (SampleCount > 1) + { + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DMS; + d3dRTVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; + } + else + { + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2D; + d3dRTVDesc.Texture2D.MipSlice = RTVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (SampleCount > 1) + { + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DMSARRAY; + d3dRTVDesc.Texture2DMSArray.ArraySize = RTVDesc.NumArraySlices; + d3dRTVDesc.Texture2DMSArray.FirstArraySlice = RTVDesc.FirstArraySlice; + } + else + { + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE2DARRAY; + d3dRTVDesc.Texture2DArray.ArraySize = RTVDesc.NumArraySlices; + d3dRTVDesc.Texture2DArray.FirstArraySlice = RTVDesc.FirstArraySlice; + d3dRTVDesc.Texture2DArray.MipSlice = RTVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_3D: + d3dRTVDesc.ViewDimension = D3D_RTV_DIMENSION_TEXTURE3D; + d3dRTVDesc.Texture3D.FirstWSlice = RTVDesc.FirstDepthSlice; + d3dRTVDesc.Texture3D.WSize = RTVDesc.NumDepthSlices; + d3dRTVDesc.Texture3D.MipSlice = RTVDesc.MostDetailedMip; + break; + + default: + UNEXPECTED("Unexpected view type"); + } +} + +template +void TextureViewDesc_to_D3D_DSV_DESC(const TextureViewDesc& DSVDesc, D3D_DEPTH_STENCIL_VIEW_DESC& d3dDSVDesc, Uint32 SampleCount) +{ + memset(&d3dDSVDesc, 0, sizeof(d3dDSVDesc)); + d3dDSVDesc.Format = TexFormatToDXGI_Format(DSVDesc.Format, BIND_DEPTH_STENCIL); + + switch (DSVDesc.TextureDim) + { + case RESOURCE_DIM_TEX_1D: + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE1D; + d3dDSVDesc.Texture1D.MipSlice = DSVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE1DARRAY; + d3dDSVDesc.Texture1DArray.ArraySize = DSVDesc.NumArraySlices; + d3dDSVDesc.Texture1DArray.FirstArraySlice = DSVDesc.FirstArraySlice; + d3dDSVDesc.Texture1DArray.MipSlice = DSVDesc.MostDetailedMip; + break; + + + case RESOURCE_DIM_TEX_2D: + if (SampleCount > 1) + { + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DMS; + d3dDSVDesc.Texture2DMS.UnusedField_NothingToDefine = 0; + } + else + { + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2D; + d3dDSVDesc.Texture2D.MipSlice = DSVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (SampleCount > 1) + { + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DMSARRAY; + d3dDSVDesc.Texture2DMSArray.ArraySize = DSVDesc.NumArraySlices; + d3dDSVDesc.Texture2DMSArray.FirstArraySlice = DSVDesc.FirstArraySlice; + } + else + { + d3dDSVDesc.ViewDimension = D3D_DSV_DIMENSION_TEXTURE2DARRAY; + d3dDSVDesc.Texture2DArray.ArraySize = DSVDesc.NumArraySlices; + d3dDSVDesc.Texture2DArray.FirstArraySlice = DSVDesc.FirstArraySlice; + d3dDSVDesc.Texture2DArray.MipSlice = DSVDesc.MostDetailedMip; + } + break; + + case RESOURCE_DIM_TEX_3D: + LOG_ERROR_AND_THROW("Depth stencil views are not supported for 3D textures"); + break; + + default: + UNEXPECTED("Unexpected view type"); + } +} + +template +void TextureViewDesc_to_D3D_UAV_DESC(const TextureViewDesc& UAVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dUAVDesc) +{ + memset(&d3dUAVDesc, 0, sizeof(d3dUAVDesc)); + d3dUAVDesc.Format = TexFormatToDXGI_Format(UAVDesc.Format, BIND_UNORDERED_ACCESS); + + switch (UAVDesc.TextureDim) + { + case RESOURCE_DIM_TEX_1D: + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE1D; + d3dUAVDesc.Texture1D.MipSlice = UAVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE1DARRAY; + d3dUAVDesc.Texture1DArray.ArraySize = UAVDesc.NumArraySlices; + d3dUAVDesc.Texture1DArray.FirstArraySlice = UAVDesc.FirstArraySlice; + d3dUAVDesc.Texture1DArray.MipSlice = UAVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_2D: + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE2D; + d3dUAVDesc.Texture2D.MipSlice = UAVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE2DARRAY; + d3dUAVDesc.Texture2DArray.ArraySize = UAVDesc.NumArraySlices; + d3dUAVDesc.Texture2DArray.FirstArraySlice = UAVDesc.FirstArraySlice; + d3dUAVDesc.Texture2DArray.MipSlice = UAVDesc.MostDetailedMip; + break; + + case RESOURCE_DIM_TEX_3D: + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_TEXTURE3D; + d3dUAVDesc.Texture3D.FirstWSlice = UAVDesc.FirstDepthSlice; + d3dUAVDesc.Texture3D.WSize = UAVDesc.NumDepthSlices; + d3dUAVDesc.Texture3D.MipSlice = UAVDesc.MostDetailedMip; + break; + + default: + UNEXPECTED("Unexpected view type"); + } +} + +template +void BufferViewDesc_to_D3D_SRV_DESC(const BufferDesc& BuffDesc, const BufferViewDesc& SRVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dSRVDesc) +{ + VERIFY(SRVDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Incorrect view type: shader resource is expected"); + + memset(&d3dSRVDesc, 0, sizeof(d3dSRVDesc)); + const auto& BuffFmt = SRVDesc.Format; + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) + d3dSRVDesc.Format = TypeToDXGI_Format(BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized); + + Uint32 ElementByteStride = 0; + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) + ElementByteStride = BuffDesc.ElementByteStride; + else if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType == VT_UNDEFINED) + ElementByteStride = 4; + + if (ElementByteStride != 0) + { + DEV_CHECK_ERR((SRVDesc.ByteOffset % ElementByteStride) == 0, "Byte offest (", SRVDesc.ByteOffset, ") is not multiple of element byte stride (", ElementByteStride, ")"); + DEV_CHECK_ERR((SRVDesc.ByteWidth % ElementByteStride) == 0, "Byte width (", SRVDesc.ByteWidth, ")is not multiple of element byte stride (", ElementByteStride, ")"); + d3dSRVDesc.Buffer.FirstElement = SRVDesc.ByteOffset / ElementByteStride; + d3dSRVDesc.Buffer.NumElements = SRVDesc.ByteWidth / ElementByteStride; + } + d3dSRVDesc.ViewDimension = D3D_SRV_DIMENSION_BUFFER; +} + +template +void BufferViewDesc_to_D3D_UAV_DESC(const BufferDesc& BuffDesc, const BufferViewDesc& UAVDesc, D3D_UNORDERED_ACCESS_VIEW_DESC& d3dUAVDesc) +{ + VERIFY(UAVDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Incorrect view type: unordered access is expected"); + + memset(&d3dUAVDesc, 0, sizeof(d3dUAVDesc)); + const auto& BuffFmt = UAVDesc.Format; + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) + d3dUAVDesc.Format = TypeToDXGI_Format(BuffFmt.ValueType, BuffFmt.NumComponents, BuffFmt.IsNormalized); + + Uint32 ElementByteStride = 0; + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType != VT_UNDEFINED) + ElementByteStride = BuffDesc.ElementByteStride; + else if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffFmt.ValueType == VT_UNDEFINED) + ElementByteStride = 4; + + if (ElementByteStride != 0) + { + DEV_CHECK_ERR((UAVDesc.ByteOffset % ElementByteStride) == 0, "Byte offest (", UAVDesc.ByteOffset, ") is not multiple of element byte stride (", ElementByteStride, ")"); + DEV_CHECK_ERR((UAVDesc.ByteWidth % ElementByteStride) == 0, "Byte width (", UAVDesc.ByteWidth, ")is not multiple of element byte stride (", ElementByteStride, ")"); + d3dUAVDesc.Buffer.FirstElement = UAVDesc.ByteOffset / ElementByteStride; + d3dUAVDesc.Buffer.NumElements = UAVDesc.ByteWidth / ElementByteStride; + } + + if (BuffDesc.Mode == BUFFER_MODE_RAW && UAVDesc.Format.ValueType == VT_UNDEFINED) + { + d3dUAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; + d3dUAVDesc.Buffer.Flags = D3D_BUFFER_UAV_FLAG_RAW; + } + else + d3dUAVDesc.Buffer.Flags = D3D_BUFFER_UAV_FLAG_NONE; + + d3dUAVDesc.ViewDimension = D3D_UAV_DIMENSION_BUFFER; +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h deleted file mode 100644 index e2f04091..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include "DXGITypeConversions.h" -#include "EngineFactoryBase.h" - -/// \file -/// Implementation of the Diligent::EngineFactoryD3DBase template class - -namespace Diligent -{ - -template -class EngineFactoryD3DBase : public EngineFactoryBase -{ -public: - using TEngineFactoryBase = EngineFactoryBase; - - EngineFactoryD3DBase(const INTERFACE_ID& FactoryIID) : - TEngineFactoryBase{FactoryIID} - {} - - - virtual void EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, - Uint32& NumAdapters, - AdapterAttribs* Adapters) override - { - auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel); - - if (Adapters == nullptr) - NumAdapters = static_cast(DXGIAdapters.size()); - else - { - NumAdapters = std::min(NumAdapters, static_cast(DXGIAdapters.size())); - for (Uint32 adapter = 0; adapter < NumAdapters; ++adapter) - { - IDXGIAdapter1* pDXIAdapter = DXGIAdapters[adapter]; - DXGI_ADAPTER_DESC1 AdapterDesc; - pDXIAdapter->GetDesc1(&AdapterDesc); - - auto& Attribs = Adapters[adapter]; - - Attribs.AdapterType = (AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? ADAPTER_TYPE_SOFTWARE : ADAPTER_TYPE_HARDWARE; - WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, Attribs.Description, _countof(Attribs.Description), NULL, FALSE); - Attribs.DedicatedVideoMemory = AdapterDesc.DedicatedVideoMemory; - Attribs.DedicatedSystemMemory = AdapterDesc.DedicatedSystemMemory; - Attribs.SharedSystemMemory = AdapterDesc.SharedSystemMemory; - Attribs.VendorId = AdapterDesc.VendorId; - Attribs.DeviceId = AdapterDesc.DeviceId; - - Attribs.NumOutputs = 0; - CComPtr pOutput; - while (pDXIAdapter->EnumOutputs(Attribs.NumOutputs, &pOutput) != DXGI_ERROR_NOT_FOUND) - { - ++Attribs.NumOutputs; - pOutput.Release(); - }; - } - } - } - - - virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, - Uint32 AdapterId, - Uint32 OutputId, - TEXTURE_FORMAT Format, - Uint32& NumDisplayModes, - DisplayModeAttribs* DisplayModes) override - { - auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel); - if (AdapterId >= DXGIAdapters.size()) - { - LOG_ERROR("Incorrect adapter id ", AdapterId); - return; - } - - IDXGIAdapter1* pDXIAdapter = DXGIAdapters[AdapterId]; - - DXGI_FORMAT DXIGFormat = TexFormatToDXGI_Format(Format); - CComPtr pOutput; - if (pDXIAdapter->EnumOutputs(OutputId, &pOutput) == DXGI_ERROR_NOT_FOUND) - { - DXGI_ADAPTER_DESC1 AdapterDesc; - pDXIAdapter->GetDesc1(&AdapterDesc); - char DescriptionMB[_countof(AdapterDesc.Description)]; - WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, DescriptionMB, _countof(DescriptionMB), NULL, FALSE); - LOG_ERROR_MESSAGE("Failed to enumerate output ", OutputId, " of adapter ", AdapterId, " (", DescriptionMB, ')'); - return; - } - - UINT numModes = 0; - // Get the number of elements - auto hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, NULL); - if (DisplayModes != nullptr) - { - // Get the list - std::vector DXIDisplayModes(numModes); - hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, DXIDisplayModes.data()); - for (Uint32 m = 0; m < std::min(NumDisplayModes, numModes); ++m) - { - const auto& SrcMode = DXIDisplayModes[m]; - auto& DstMode = DisplayModes[m]; - DstMode.Width = SrcMode.Width; - DstMode.Height = SrcMode.Height; - DstMode.Format = DXGI_FormatToTexFormat(SrcMode.Format); - DstMode.RefreshRateNumerator = SrcMode.RefreshRate.Numerator; - DstMode.RefreshRateDenominator = SrcMode.RefreshRate.Denominator; - DstMode.Scaling = static_cast(SrcMode.Scaling); - DstMode.ScanlineOrder = static_cast(SrcMode.ScanlineOrdering); - } - NumDisplayModes = std::min(NumDisplayModes, numModes); - } - else - { - NumDisplayModes = numModes; - } - } - - - std::vector> FindCompatibleAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel) - { - std::vector> DXGIAdapters; - - CComPtr pFactory; - if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&pFactory))) - { - LOG_ERROR_MESSAGE("Failed to create DXGI Factory"); - return std::move(DXGIAdapters); - } - - CComPtr pDXIAdapter; - - auto d3dFeatureLevel = GetD3DFeatureLevel(MinFeatureLevel); - UINT adapter = 0; - for (; pFactory->EnumAdapters1(adapter, &pDXIAdapter) != DXGI_ERROR_NOT_FOUND; ++adapter, pDXIAdapter.Release()) - { - DXGI_ADAPTER_DESC1 AdapterDesc; - pDXIAdapter->GetDesc1(&AdapterDesc); - bool IsCompatibleAdapter = CheckAdapterCompatibility(pDXIAdapter, d3dFeatureLevel); - if (IsCompatibleAdapter) - { - DXGIAdapters.emplace_back(std::move(pDXIAdapter)); - } - } - - return std::move(DXGIAdapters); - } - - -protected: - static D3D_FEATURE_LEVEL GetD3DFeatureLevel(DIRECT3D_FEATURE_LEVEL FeatureLevel) - { - switch (FeatureLevel) - { - case DIRECT3D_FEATURE_LEVEL_10_0: return D3D_FEATURE_LEVEL_10_0; - case DIRECT3D_FEATURE_LEVEL_10_1: return D3D_FEATURE_LEVEL_10_1; - case DIRECT3D_FEATURE_LEVEL_11_0: return D3D_FEATURE_LEVEL_11_0; - case DIRECT3D_FEATURE_LEVEL_11_1: return D3D_FEATURE_LEVEL_11_1; -#if defined(_WIN32_WINNT_WIN10) && (_WIN32_WINNT >= _WIN32_WINNT_WIN10) - case DIRECT3D_FEATURE_LEVEL_12_0: return D3D_FEATURE_LEVEL_12_0; - case DIRECT3D_FEATURE_LEVEL_12_1: return D3D_FEATURE_LEVEL_12_1; -#endif - - default: - UNEXPECTED("Unknown DIRECT3D_FEATURE_LEVEL ", static_cast(FeatureLevel)); - return D3D_FEATURE_LEVEL_11_0; - } - } - -private: - template - bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, - D3D_FEATURE_LEVEL FeatureLevels); - - template <> - bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, - D3D_FEATURE_LEVEL FeatureLevel) - { - auto hr = D3D11CreateDevice( - nullptr, - D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. - 0, - 0, // Flags. - &FeatureLevel, // Feature levels. - 1, // Number of feature levels - D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. - nullptr, // No need to keep the D3D device reference. - nullptr, // Feature level of the created adapter. - nullptr // No need to keep the D3D device context reference. - ); - return SUCCEEDED(hr); - } - - template <> - bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, - D3D_FEATURE_LEVEL FeatureLevel) - { - auto hr = D3D12CreateDevice(pDXGIAdapter, FeatureLevel, _uuidof(ID3D12Device), nullptr); - return SUCCEEDED(hr); - } -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.hpp new file mode 100644 index 00000000..1e610f62 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.hpp @@ -0,0 +1,229 @@ +/* + * Copyright 2019-2020 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 + +#include "DXGITypeConversions.h" +#include "EngineFactoryBase.hpp" + +/// \file +/// Implementation of the Diligent::EngineFactoryD3DBase template class + +namespace Diligent +{ + +template +class EngineFactoryD3DBase : public EngineFactoryBase +{ +public: + using TEngineFactoryBase = EngineFactoryBase; + + EngineFactoryD3DBase(const INTERFACE_ID& FactoryIID) : + TEngineFactoryBase{FactoryIID} + {} + + + virtual void EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, + Uint32& NumAdapters, + AdapterAttribs* Adapters) override + { + auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel); + + if (Adapters == nullptr) + NumAdapters = static_cast(DXGIAdapters.size()); + else + { + NumAdapters = std::min(NumAdapters, static_cast(DXGIAdapters.size())); + for (Uint32 adapter = 0; adapter < NumAdapters; ++adapter) + { + IDXGIAdapter1* pDXIAdapter = DXGIAdapters[adapter]; + DXGI_ADAPTER_DESC1 AdapterDesc; + pDXIAdapter->GetDesc1(&AdapterDesc); + + auto& Attribs = Adapters[adapter]; + + Attribs.AdapterType = (AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? ADAPTER_TYPE_SOFTWARE : ADAPTER_TYPE_HARDWARE; + WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, Attribs.Description, _countof(Attribs.Description), NULL, FALSE); + Attribs.DedicatedVideoMemory = AdapterDesc.DedicatedVideoMemory; + Attribs.DedicatedSystemMemory = AdapterDesc.DedicatedSystemMemory; + Attribs.SharedSystemMemory = AdapterDesc.SharedSystemMemory; + Attribs.VendorId = AdapterDesc.VendorId; + Attribs.DeviceId = AdapterDesc.DeviceId; + + Attribs.NumOutputs = 0; + CComPtr pOutput; + while (pDXIAdapter->EnumOutputs(Attribs.NumOutputs, &pOutput) != DXGI_ERROR_NOT_FOUND) + { + ++Attribs.NumOutputs; + pOutput.Release(); + }; + } + } + } + + + virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, + Uint32 AdapterId, + Uint32 OutputId, + TEXTURE_FORMAT Format, + Uint32& NumDisplayModes, + DisplayModeAttribs* DisplayModes) override + { + auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel); + if (AdapterId >= DXGIAdapters.size()) + { + LOG_ERROR("Incorrect adapter id ", AdapterId); + return; + } + + IDXGIAdapter1* pDXIAdapter = DXGIAdapters[AdapterId]; + + DXGI_FORMAT DXIGFormat = TexFormatToDXGI_Format(Format); + CComPtr pOutput; + if (pDXIAdapter->EnumOutputs(OutputId, &pOutput) == DXGI_ERROR_NOT_FOUND) + { + DXGI_ADAPTER_DESC1 AdapterDesc; + pDXIAdapter->GetDesc1(&AdapterDesc); + char DescriptionMB[_countof(AdapterDesc.Description)]; + WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, DescriptionMB, _countof(DescriptionMB), NULL, FALSE); + LOG_ERROR_MESSAGE("Failed to enumerate output ", OutputId, " of adapter ", AdapterId, " (", DescriptionMB, ')'); + return; + } + + UINT numModes = 0; + // Get the number of elements + auto hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, NULL); + if (DisplayModes != nullptr) + { + // Get the list + std::vector DXIDisplayModes(numModes); + hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, DXIDisplayModes.data()); + for (Uint32 m = 0; m < std::min(NumDisplayModes, numModes); ++m) + { + const auto& SrcMode = DXIDisplayModes[m]; + auto& DstMode = DisplayModes[m]; + DstMode.Width = SrcMode.Width; + DstMode.Height = SrcMode.Height; + DstMode.Format = DXGI_FormatToTexFormat(SrcMode.Format); + DstMode.RefreshRateNumerator = SrcMode.RefreshRate.Numerator; + DstMode.RefreshRateDenominator = SrcMode.RefreshRate.Denominator; + DstMode.Scaling = static_cast(SrcMode.Scaling); + DstMode.ScanlineOrder = static_cast(SrcMode.ScanlineOrdering); + } + NumDisplayModes = std::min(NumDisplayModes, numModes); + } + else + { + NumDisplayModes = numModes; + } + } + + + std::vector> FindCompatibleAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel) + { + std::vector> DXGIAdapters; + + CComPtr pFactory; + if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&pFactory))) + { + LOG_ERROR_MESSAGE("Failed to create DXGI Factory"); + return std::move(DXGIAdapters); + } + + CComPtr pDXIAdapter; + + auto d3dFeatureLevel = GetD3DFeatureLevel(MinFeatureLevel); + UINT adapter = 0; + for (; pFactory->EnumAdapters1(adapter, &pDXIAdapter) != DXGI_ERROR_NOT_FOUND; ++adapter, pDXIAdapter.Release()) + { + DXGI_ADAPTER_DESC1 AdapterDesc; + pDXIAdapter->GetDesc1(&AdapterDesc); + bool IsCompatibleAdapter = CheckAdapterCompatibility(pDXIAdapter, d3dFeatureLevel); + if (IsCompatibleAdapter) + { + DXGIAdapters.emplace_back(std::move(pDXIAdapter)); + } + } + + return std::move(DXGIAdapters); + } + + +protected: + static D3D_FEATURE_LEVEL GetD3DFeatureLevel(DIRECT3D_FEATURE_LEVEL FeatureLevel) + { + switch (FeatureLevel) + { + case DIRECT3D_FEATURE_LEVEL_10_0: return D3D_FEATURE_LEVEL_10_0; + case DIRECT3D_FEATURE_LEVEL_10_1: return D3D_FEATURE_LEVEL_10_1; + case DIRECT3D_FEATURE_LEVEL_11_0: return D3D_FEATURE_LEVEL_11_0; + case DIRECT3D_FEATURE_LEVEL_11_1: return D3D_FEATURE_LEVEL_11_1; +#if defined(_WIN32_WINNT_WIN10) && (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + case DIRECT3D_FEATURE_LEVEL_12_0: return D3D_FEATURE_LEVEL_12_0; + case DIRECT3D_FEATURE_LEVEL_12_1: return D3D_FEATURE_LEVEL_12_1; +#endif + + default: + UNEXPECTED("Unknown DIRECT3D_FEATURE_LEVEL ", static_cast(FeatureLevel)); + return D3D_FEATURE_LEVEL_11_0; + } + } + +private: + template + bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, + D3D_FEATURE_LEVEL FeatureLevels); + + template <> + bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, + D3D_FEATURE_LEVEL FeatureLevel) + { + auto hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + 0, // Flags. + &FeatureLevel, // Feature levels. + 1, // Number of feature levels + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // Feature level of the created adapter. + nullptr // No need to keep the D3D device context reference. + ); + return SUCCEEDED(hr); + } + + template <> + bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter, + D3D_FEATURE_LEVEL FeatureLevel) + { + auto hr = D3D12CreateDevice(pDXGIAdapter, FeatureLevel, _uuidof(ID3D12Device), nullptr); + return SUCCEEDED(hr); + } +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.h deleted file mode 100644 index a1f0f601..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2019-2020 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 "RenderDeviceBase.h" - -namespace Diligent -{ - -/// Base implementation of a D3D render device - -template -class RenderDeviceD3DBase : public RenderDeviceBase -{ -public: - RenderDeviceD3DBase(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - IEngineFactory* pEngineFactory, - Uint32 NumDeferredContexts, - const DeviceObjectSizes& ObjectSizes) : - RenderDeviceBase{pRefCounters, RawMemAllocator, pEngineFactory, NumDeferredContexts, ObjectSizes} - { - // Flag texture formats always supported in D3D11 and D3D12 - - // clang-format off -#define FLAG_FORMAT(Fmt, IsSupported) m_TextureFormatsInfo[Fmt].Supported=IsSupported - - FLAG_FORMAT(TEX_FORMAT_RGBA32_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RGBA32_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA32_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA32_SINT, true); - FLAG_FORMAT(TEX_FORMAT_RGB32_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RGB32_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RGB32_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RGB32_SINT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGBA16_SINT, true); - FLAG_FORMAT(TEX_FORMAT_RG32_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RG32_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RG32_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RG32_SINT, true); - FLAG_FORMAT(TEX_FORMAT_R32G8X24_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_D32_FLOAT_S8X24_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_X32_TYPELESS_G8X24_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RGB10A2_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RGB10A2_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGB10A2_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R11G11B10_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGBA8_SINT, true); - FLAG_FORMAT(TEX_FORMAT_RG16_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RG16_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_RG16_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RG16_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RG16_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_RG16_SINT, true); - FLAG_FORMAT(TEX_FORMAT_R32_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_D32_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_R32_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_R32_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R32_SINT, true); - FLAG_FORMAT(TEX_FORMAT_R24G8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_D24_UNORM_S8_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R24_UNORM_X8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_X24_TYPELESS_G8_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RG8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_RG8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RG8_UINT, true); - FLAG_FORMAT(TEX_FORMAT_RG8_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_RG8_SINT, true); - FLAG_FORMAT(TEX_FORMAT_R16_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_R16_FLOAT, true); - FLAG_FORMAT(TEX_FORMAT_D16_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_R16_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_R16_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R16_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_R16_SINT, true); - FLAG_FORMAT(TEX_FORMAT_R8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_R8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_R8_UINT, true); - FLAG_FORMAT(TEX_FORMAT_R8_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_R8_SINT, true); - FLAG_FORMAT(TEX_FORMAT_A8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_R1_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_RGB9E5_SHAREDEXP, true); - FLAG_FORMAT(TEX_FORMAT_RG8_B8G8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_G8R8_G8B8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC1_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC1_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC1_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_BC2_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC2_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC2_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_BC3_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC3_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC3_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_BC4_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC4_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC4_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC5_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC5_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC5_SNORM, true); - FLAG_FORMAT(TEX_FORMAT_B5G6R5_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_B5G5R5A1_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BGRA8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_BGRX8_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM_SRGB, true); - FLAG_FORMAT(TEX_FORMAT_BC6H_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC6H_UF16, true); - FLAG_FORMAT(TEX_FORMAT_BC6H_SF16, true); - FLAG_FORMAT(TEX_FORMAT_BC7_TYPELESS, true); - FLAG_FORMAT(TEX_FORMAT_BC7_UNORM, true); - FLAG_FORMAT(TEX_FORMAT_BC7_UNORM_SRGB, true); -#undef FLAG_FORMAT - // clang-format on - - auto& Features = this->m_DeviceCaps.Features; - - Features.SeparablePrograms = True; - Features.IndirectRendering = True; - Features.WireframeFill = True; - Features.MultithreadedResourceCreation = True; - Features.ComputeShaders = True; - Features.GeometryShaders = True; - Features.Tessellation = True; - Features.OcclusionQueries = True; - Features.BinaryOcclusionQueries = True; - Features.TimestampQueries = True; - Features.PipelineStatisticsQueries = True; - Features.DepthBiasClamp = True; - Features.DepthClamp = True; - Features.IndependentBlend = True; - Features.DualSourceBlend = True; - Features.MultiViewport = True; - Features.TextureCompressionBC = True; - Features.PixelUAVWritesAndAtomics = True; - Features.TextureUAVExtendedFormats = True; - } -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp new file mode 100644 index 00000000..5b11dabc --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp @@ -0,0 +1,182 @@ +/* + * Copyright 2019-2020 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 "RenderDeviceBase.hpp" + +namespace Diligent +{ + +/// Base implementation of a D3D render device + +template +class RenderDeviceD3DBase : public RenderDeviceBase +{ +public: + RenderDeviceD3DBase(IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + IEngineFactory* pEngineFactory, + Uint32 NumDeferredContexts, + const DeviceObjectSizes& ObjectSizes) : + RenderDeviceBase{pRefCounters, RawMemAllocator, pEngineFactory, NumDeferredContexts, ObjectSizes} + { + // Flag texture formats always supported in D3D11 and D3D12 + + // clang-format off +#define FLAG_FORMAT(Fmt, IsSupported) m_TextureFormatsInfo[Fmt].Supported=IsSupported + + FLAG_FORMAT(TEX_FORMAT_RGBA32_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RGBA32_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA32_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA32_SINT, true); + FLAG_FORMAT(TEX_FORMAT_RGB32_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RGB32_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RGB32_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RGB32_SINT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGBA16_SINT, true); + FLAG_FORMAT(TEX_FORMAT_RG32_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RG32_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RG32_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RG32_SINT, true); + FLAG_FORMAT(TEX_FORMAT_R32G8X24_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_D32_FLOAT_S8X24_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R32_FLOAT_X8X24_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_X32_TYPELESS_G8X24_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RGB10A2_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RGB10A2_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGB10A2_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R11G11B10_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGBA8_SINT, true); + FLAG_FORMAT(TEX_FORMAT_RG16_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RG16_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_RG16_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RG16_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RG16_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_RG16_SINT, true); + FLAG_FORMAT(TEX_FORMAT_R32_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_D32_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_R32_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_R32_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R32_SINT, true); + FLAG_FORMAT(TEX_FORMAT_R24G8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_D24_UNORM_S8_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R24_UNORM_X8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_X24_TYPELESS_G8_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RG8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_RG8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RG8_UINT, true); + FLAG_FORMAT(TEX_FORMAT_RG8_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_RG8_SINT, true); + FLAG_FORMAT(TEX_FORMAT_R16_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_R16_FLOAT, true); + FLAG_FORMAT(TEX_FORMAT_D16_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_R16_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_R16_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R16_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_R16_SINT, true); + FLAG_FORMAT(TEX_FORMAT_R8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_R8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_R8_UINT, true); + FLAG_FORMAT(TEX_FORMAT_R8_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_R8_SINT, true); + FLAG_FORMAT(TEX_FORMAT_A8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_R1_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_RGB9E5_SHAREDEXP, true); + FLAG_FORMAT(TEX_FORMAT_RG8_B8G8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_G8R8_G8B8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC1_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC1_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC1_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_BC2_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC2_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC2_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_BC3_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC3_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC3_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_BC4_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC4_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC4_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC5_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC5_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC5_SNORM, true); + FLAG_FORMAT(TEX_FORMAT_B5G6R5_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_B5G5R5A1_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BGRA8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BGRA8_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_BGRX8_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BGRX8_UNORM_SRGB, true); + FLAG_FORMAT(TEX_FORMAT_BC6H_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC6H_UF16, true); + FLAG_FORMAT(TEX_FORMAT_BC6H_SF16, true); + FLAG_FORMAT(TEX_FORMAT_BC7_TYPELESS, true); + FLAG_FORMAT(TEX_FORMAT_BC7_UNORM, true); + FLAG_FORMAT(TEX_FORMAT_BC7_UNORM_SRGB, true); +#undef FLAG_FORMAT + // clang-format on + + auto& Features = this->m_DeviceCaps.Features; + + Features.SeparablePrograms = True; + Features.IndirectRendering = True; + Features.WireframeFill = True; + Features.MultithreadedResourceCreation = True; + Features.ComputeShaders = True; + Features.GeometryShaders = True; + Features.Tessellation = True; + Features.OcclusionQueries = True; + Features.BinaryOcclusionQueries = True; + Features.TimestampQueries = True; + Features.PipelineStatisticsQueries = True; + Features.DepthBiasClamp = True; + Features.DepthClamp = True; + Features.IndependentBlend = True; + Features.DualSourceBlend = True; + Features.MultiViewport = True; + Features.TextureCompressionBC = True; + Features.PixelUAVWritesAndAtomics = True; + Features.TextureUAVExtendedFormats = True; + } +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.h deleted file mode 100644 index e7b61f59..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include - -#include "Shader.h" - -/// \file -/// Base implementation of a D3D shader - -namespace Diligent -{ - -/// Base implementation of a D3D shader -class ShaderD3DBase -{ -public: - ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* ShaderModel); - -protected: - CComPtr m_pShaderByteCode; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp new file mode 100644 index 00000000..e7b61f59 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp @@ -0,0 +1,50 @@ +/* + * Copyright 2019-2020 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 + +#include + +#include "Shader.h" + +/// \file +/// Base implementation of a D3D shader + +namespace Diligent +{ + +/// Base implementation of a D3D shader +class ShaderD3DBase +{ +public: + ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* ShaderModel); + +protected: + CComPtr m_pShaderByteCode; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h deleted file mode 100644 index 343c4177..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright 2019-2020 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 -/// Declaration of Diligent::ShaderResources class -/// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resources/ - -// ShaderResources class uses continuous chunk of memory to store all resources, as follows: -// -// -// m_MemoryBuffer m_TexSRVOffset m_TexUAVOffset m_BufSRVOffset m_BufUAVOffset m_SamplersOffset m_MemorySize -// | | | | | | | | -// | CB[0] ... CB[Ncb-1] | TexSRV[0] ... TexSRV[Ntsrv-1] | TexUAV[0] ... TexUAV[Ntuav-1] | BufSRV[0] ... BufSRV[Nbsrv-1] | BufUAV[0] ... BufUAV[Nbuav-1] | Sam[0] ... Sam[Nsam-1] | Resource Names | -// -// Ncb - number of constant buffers -// Ntsrv - number of texture SRVs -// Ntuav - number of texture UAVs -// Nbsrv - number of buffer SRVs -// Nbuav - number of buffer UAVs -// Nsam - number of samplers -// -// -// If texture SRV is assigned a sampler, it is cross-referenced through SamplerOrTexSRVId: -// -// _____________________SamplerOrTexSRVId___________________ -// | | -// | V -// | CBs | ... TexSRV[n] ... | TexUAVs | BufSRVs | BufUAVs | Sam[0] ... Sam[SamplerId] ... | -// A | -// '---------------------SamplerOrTexSRVId-------------------' -// - -#include - -#define NOMINMAX -#include - -#include "ShaderD3D.h" -#include "STDAllocator.h" -#include "HashUtils.h" -#include "StringPool.h" -#include "D3DShaderResourceLoader.h" -#include "PipelineState.h" - -namespace Diligent -{ - -// sizeof(D3DShaderResourceAttribs) == 16 (x64) -struct D3DShaderResourceAttribs -{ - // clang-format off - -/* 0 */ const char* const Name; - -/* 8 */ const Uint16 BindPoint; -/*10 */ const Uint16 BindCount; - -private: - // 4 4 24 - // bit | 0 1 2 3 | 4 5 6 7 | 8 9 10 ... 31 | - // | | | | - // | InputType | SRV Dim | SamplerOrTexSRVIdBits | - static constexpr const Uint32 ShaderInputTypeBits = 4; - static constexpr const Uint32 SRVDimBits = 4; - static constexpr const Uint32 SamplerOrTexSRVIdBits = 24; - static_assert(ShaderInputTypeBits + SRVDimBits + SamplerOrTexSRVIdBits == 32, "Attributes are better be packed into 32 bits"); - - static_assert(D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER < (1 << ShaderInputTypeBits), "Not enough bits to represent D3D_SHADER_INPUT_TYPE"); - static_assert(D3D_SRV_DIMENSION_BUFFEREX < (1 << SRVDimBits), "Not enough bits to represent D3D_SRV_DIMENSION"); - - // We need to use Uint32 instead of the actual type for reliability and correctness. - // There originally was a problem when the type of InputType was D3D_SHADER_INPUT_TYPE: - // the value of D3D_SIT_UAV_RWBYTEADDRESS (8) was interpreted as -8 (as the underlying enum type - // is signed) causing errors -/*12.0*/ const Uint32 InputType : ShaderInputTypeBits; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER == 11 -/*12.4*/ const Uint32 SRVDimension : SRVDimBits; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11 -/*13.0*/ Uint32 SamplerOrTexSRVId : SamplerOrTexSRVIdBits; // Max value: 2^24-1 -/*16 */ // End of structure - - // clang-format on - -public: - static constexpr const Uint32 InvalidSamplerId = (1 << SamplerOrTexSRVIdBits) - 1; - static constexpr const Uint32 InvalidTexSRVId = (1 << SamplerOrTexSRVIdBits) - 1; - static constexpr const Uint16 InvalidBindPoint = std::numeric_limits::max(); - static constexpr const Uint16 MaxBindPoint = InvalidBindPoint - 1; - static constexpr const Uint16 MaxBindCount = std::numeric_limits::max(); - - - D3DShaderResourceAttribs(const char* _Name, - UINT _BindPoint, - UINT _BindCount, - D3D_SHADER_INPUT_TYPE _InputType, - D3D_SRV_DIMENSION _SRVDimension, - Uint32 _SamplerId) noexcept : - // clang-format off - Name {_Name}, - BindPoint {static_cast (_BindPoint) }, - BindCount {static_cast (_BindCount) }, - InputType {static_cast (_InputType) }, - SRVDimension {static_cast(_SRVDimension)}, - SamplerOrTexSRVId {_SamplerId} - // clang-format on - { -#ifdef _DEBUG - // clang-format off - VERIFY(_BindPoint <= MaxBindPoint || _BindPoint == InvalidBindPoint, "Bind Point is out of allowed range"); - VERIFY(_BindCount <= MaxBindCount, "Bind Count is out of allowed range"); - VERIFY(_InputType < (1 << ShaderInputTypeBits), "Shader input type is out of expected range"); - VERIFY(_SRVDimension < (1 << SRVDimBits), "SRV dimensions is out of expected range"); - VERIFY(_SamplerId < (1 << SamplerOrTexSRVIdBits), "SamplerOrTexSRVId is out of representable range"); - // clang-format on - - if (_InputType == D3D_SIT_TEXTURE && _SRVDimension != D3D_SRV_DIMENSION_BUFFER) - VERIFY_EXPR(GetCombinedSamplerId() == _SamplerId); - else - VERIFY(_SamplerId == InvalidSamplerId, "Only texture SRV can be assigned a valid texture sampler"); -#endif - } - - D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs, Uint32 SamplerId) noexcept : - // clang-format off - D3DShaderResourceAttribs - { - NamesPool.CopyString(rhs.Name), - rhs.BindPoint, - rhs.BindCount, - rhs.GetInputType(), - rhs.GetSRVDimension(), - SamplerId - } - // clang-format on - { - VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Only texture SRV can be assigned a texture sampler"); - } - - D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs) noexcept : - // clang-format off - D3DShaderResourceAttribs - { - NamesPool.CopyString(rhs.Name), - rhs.BindPoint, - rhs.BindCount, - rhs.GetInputType(), - rhs.GetSRVDimension(), - rhs.SamplerOrTexSRVId - } - // clang-format on - { - } - - // clang-format off - D3DShaderResourceAttribs (const D3DShaderResourceAttribs& rhs) = delete; - D3DShaderResourceAttribs ( D3DShaderResourceAttribs&& rhs) = default; // Required for vector - D3DShaderResourceAttribs& operator = (const D3DShaderResourceAttribs& rhs) = delete; - D3DShaderResourceAttribs& operator = ( D3DShaderResourceAttribs&& rhs) = delete; - // clang-format on - - D3D_SHADER_INPUT_TYPE GetInputType() const - { - return static_cast(InputType); - } - - D3D_SRV_DIMENSION GetSRVDimension() const - { - return static_cast(SRVDimension); - } - - bool IsCombinedWithSampler() const - { - return GetCombinedSamplerId() != InvalidSamplerId; - } - - bool IsCombinedWithTexSRV() const - { - return GetCombinedTexSRVId() != InvalidTexSRVId; - } - - bool IsValidBindPoint() const - { - return BindPoint != InvalidBindPoint; - } - - String GetPrintName(Uint32 ArrayInd) const - { - VERIFY_EXPR(ArrayInd < BindCount); - if (BindCount > 1) - return String(Name) + '[' + std::to_string(ArrayInd) + ']'; - else - return Name; - } - - bool IsCompatibleWith(const D3DShaderResourceAttribs& Attribs) const - { - return BindPoint == Attribs.BindPoint && - BindCount == Attribs.BindCount && - InputType == Attribs.InputType && - SRVDimension == Attribs.SRVDimension && - SamplerOrTexSRVId == Attribs.SamplerOrTexSRVId; - } - - size_t GetHash() const - { - return ComputeHash(BindPoint, BindCount, InputType, SRVDimension, SamplerOrTexSRVId); - } - - HLSLShaderResourceDesc GetHLSLResourceDesc() const; - -private: - friend class ShaderResources; - - Uint32 GetCombinedSamplerId() const - { - VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Invalid input type: D3D_SIT_TEXTURE is expected"); - return SamplerOrTexSRVId; - } - - void SetTexSRVId(Uint32 TexSRVId) - { - VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected"); - VERIFY(TexSRVId < (1 << SamplerOrTexSRVIdBits), "TexSRVId (", TexSRVId, ") is out of representable range"); - SamplerOrTexSRVId = TexSRVId; - } - - Uint32 GetCombinedTexSRVId() const - { - VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected"); - return SamplerOrTexSRVId; - } -}; -static_assert(sizeof(D3DShaderResourceAttribs) == sizeof(void*) + sizeof(Uint32) * 2, "Unexpected sizeof(D3DShaderResourceAttribs)"); - - -/// Diligent::ShaderResources class -class ShaderResources -{ -public: - ShaderResources(SHADER_TYPE ShaderType) noexcept : - m_ShaderType{ShaderType} - { - } - - // clang-format off - ShaderResources (const ShaderResources&) = delete; - ShaderResources ( ShaderResources&&) = delete; - ShaderResources& operator = (const ShaderResources&) = delete; - ShaderResources& operator = ( ShaderResources&&) = delete; - // clang-format on - - ~ShaderResources(); - - // clang-format off - Uint32 GetNumCBs() const noexcept { return (m_TexSRVOffset - 0); } - Uint32 GetNumTexSRV() const noexcept { return (m_TexUAVOffset - m_TexSRVOffset); } - Uint32 GetNumTexUAV() const noexcept { return (m_BufSRVOffset - m_TexUAVOffset); } - Uint32 GetNumBufSRV() const noexcept { return (m_BufUAVOffset - m_BufSRVOffset); } - Uint32 GetNumBufUAV() const noexcept { return (m_SamplersOffset - m_BufUAVOffset); } - Uint32 GetNumSamplers() const noexcept { return (m_TotalResources - m_SamplersOffset); } - Uint32 GetTotalResources()const noexcept { return m_TotalResources; } - - const D3DShaderResourceAttribs& GetCB (Uint32 n)const noexcept { return GetResAttribs(n, GetNumCBs(), 0); } - const D3DShaderResourceAttribs& GetTexSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } - const D3DShaderResourceAttribs& GetTexUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } - const D3DShaderResourceAttribs& GetBufSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } - const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } - const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } - // clang-format on - - const D3DShaderResourceAttribs& GetCombinedSampler(const D3DShaderResourceAttribs& TexSRV) const noexcept - { - VERIFY(TexSRV.IsCombinedWithSampler(), "This texture SRV is not combined with any sampler"); - return GetSampler(TexSRV.GetCombinedSamplerId()); - } - - const D3DShaderResourceAttribs& GetCombinedTextureSRV(const D3DShaderResourceAttribs& Sampler) const noexcept - { - VERIFY(Sampler.IsCombinedWithTexSRV(), "This sampler is not combined with any texture SRV"); - return GetTexSRV(Sampler.GetCombinedTexSRVId()); - } - - SHADER_TYPE GetShaderType() const noexcept { return m_ShaderType; } - - HLSLShaderResourceDesc GetHLSLShaderResourceDesc(Uint32 Index) const; - - template - void ProcessResources(THandleCB HandleCB, - THandleSampler HandleSampler, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV) const - { - for (Uint32 n = 0; n < GetNumCBs(); ++n) - { - const auto& CB = GetCB(n); - HandleCB(CB, n); - } - - for (Uint32 n = 0; n < GetNumSamplers(); ++n) - { - const auto& Sampler = GetSampler(n); - HandleSampler(Sampler, n); - } - - for (Uint32 n = 0; n < GetNumTexSRV(); ++n) - { - const auto& TexSRV = GetTexSRV(n); - HandleTexSRV(TexSRV, n); - } - - for (Uint32 n = 0; n < GetNumTexUAV(); ++n) - { - const auto& TexUAV = GetTexUAV(n); - HandleTexUAV(TexUAV, n); - } - - for (Uint32 n = 0; n < GetNumBufSRV(); ++n) - { - const auto& BufSRV = GetBufSRV(n); - HandleBufSRV(BufSRV, n); - } - - for (Uint32 n = 0; n < GetNumBufUAV(); ++n) - { - const auto& BufUAV = GetBufUAV(n); - HandleBufUAV(BufUAV, n); - } - } - - bool IsCompatibleWith(const ShaderResources& Resources) const; - bool IsUsingCombinedTextureSamplers() const { return m_SamplerSuffix != nullptr; } - const char* GetCombinedSamplerSuffix() const { return m_SamplerSuffix; } - const Char* GetShaderName() const { return m_ShaderName; } - - size_t GetHash() const; - - SHADER_RESOURCE_VARIABLE_TYPE FindVariableType(const D3DShaderResourceAttribs& ResourceAttribs, - const PipelineResourceLayoutDesc& ResourceLayout) const; - - Int32 FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - bool LogStaticSamplerArrayError) const; - - D3DShaderResourceCounters CountResources(const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool CountStaticSamplers) const noexcept; -#ifdef DEVELOPMENT - static void DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& ResourceLayout, - const ShaderResources* const pShaderResources[], - Uint32 NumShaders); -#endif - - void GetShaderModel(Uint32& Major, Uint32& Minor) const - { - Major = (m_ShaderVersion & 0x000000F0) >> 4; - Minor = (m_ShaderVersion & 0x0000000F); - } - -protected: - template - void Initialize(ID3DBlob* pShaderByteCode, - TNewResourceHandler NewResHandler, - const Char* ShaderName, - const Char* SamplerSuffix); - - - __forceinline D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset) noexcept - { - VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Resource array size: ", NumResources); - VERIFY_EXPR(Offset + n < m_TotalResources); - return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; - } - - __forceinline const D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset) const noexcept - { - VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Resource array size: ", NumResources); - VERIFY_EXPR(Offset + n < m_TotalResources); - return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; - } - - // clang-format off - D3DShaderResourceAttribs& GetCB(Uint32 n) noexcept { return GetResAttribs(n, GetNumCBs(), 0); } - D3DShaderResourceAttribs& GetTexSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } - D3DShaderResourceAttribs& GetTexUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } - D3DShaderResourceAttribs& GetBufSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } - D3DShaderResourceAttribs& GetBufUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } - D3DShaderResourceAttribs& GetSampler(Uint32 n) noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } - // clang-format on - -private: - void AllocateMemory(IMemoryAllocator& Allocator, - const D3DShaderResourceCounters& ResCounters, - size_t ResourceNamesPoolSize); - - Uint32 FindAssignedSamplerId(const D3DShaderResourceAttribs& TexSRV, const char* SamplerSuffix) const; - - // Memory buffer that holds all resources as continuous chunk of memory: - // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | Resource Names | - // - - std::unique_ptr> m_MemoryBuffer; - - StringPool m_ResourceNames; - const char* m_SamplerSuffix = nullptr; // The suffix and the shader name - const char* m_ShaderName = nullptr; // are put into the m_ResourceNames - - // Offsets in elements of D3DShaderResourceAttribs - typedef Uint16 OffsetType; - OffsetType m_TexSRVOffset = 0; - OffsetType m_TexUAVOffset = 0; - OffsetType m_BufSRVOffset = 0; - OffsetType m_BufUAVOffset = 0; - OffsetType m_SamplersOffset = 0; - OffsetType m_TotalResources = 0; - - const SHADER_TYPE m_ShaderType; - - Uint32 m_ShaderVersion = 0; -}; - - -template -void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, - TNewResourceHandler NewResHandler, - const Char* ShaderName, - const Char* CombinedSamplerSuffix) -{ - Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; - LoadD3DShaderResources( - pShaderByteCode, - - [&](const D3D_SHADER_DESC& d3dShaderDesc) // - { - m_ShaderVersion = d3dShaderDesc.Version; - }, - - [&](const D3DShaderResourceCounters& ResCounters, size_t ResourceNamesPoolSize) // - { - VERIFY_EXPR(ShaderName != nullptr); - ResourceNamesPoolSize += strlen(ShaderName) + 1; - - if (CombinedSamplerSuffix != nullptr) - ResourceNamesPoolSize += strlen(CombinedSamplerSuffix) + 1; - - AllocateMemory(GetRawAllocator(), ResCounters, ResourceNamesPoolSize); - }, - - [&](const D3DShaderResourceAttribs& CBAttribs) // - { - VERIFY_EXPR(CBAttribs.GetInputType() == D3D_SIT_CBUFFER); - auto* pNewCB = new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(m_ResourceNames, CBAttribs); - NewResHandler.OnNewCB(*pNewCB); - }, - - [&](const D3DShaderResourceAttribs& TexUAV) // - { - VERIFY_EXPR(TexUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && TexUAV.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); - auto* pNewTexUAV = new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs(m_ResourceNames, TexUAV); - NewResHandler.OnNewTexUAV(*pNewTexUAV); - }, - - [&](const D3DShaderResourceAttribs& BuffUAV) // - { - VERIFY_EXPR(BuffUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && BuffUAV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffUAV.GetInputType() == D3D_SIT_UAV_RWSTRUCTURED || BuffUAV.GetInputType() == D3D_SIT_UAV_RWBYTEADDRESS); - auto* pNewBufUAV = new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffUAV); - NewResHandler.OnNewBuffUAV(*pNewBufUAV); - }, - - [&](const D3DShaderResourceAttribs& BuffSRV) // - { - VERIFY_EXPR(BuffSRV.GetInputType() == D3D_SIT_TEXTURE && BuffSRV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffSRV.GetInputType() == D3D_SIT_STRUCTURED || BuffSRV.GetInputType() == D3D_SIT_BYTEADDRESS); - auto* pNewBuffSRV = new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffSRV); - NewResHandler.OnNewBuffSRV(*pNewBuffSRV); - }, - - [&](const D3DShaderResourceAttribs& SamplerAttribs) // - { - VERIFY_EXPR(SamplerAttribs.GetInputType() == D3D_SIT_SAMPLER); - auto* pNewSampler = new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs(m_ResourceNames, SamplerAttribs); - NewResHandler.OnNewSampler(*pNewSampler); - }, - - [&](const D3DShaderResourceAttribs& TexAttribs) // - { - VERIFY_EXPR(TexAttribs.GetInputType() == D3D_SIT_TEXTURE && TexAttribs.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); - VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs"); - - auto SamplerId = CombinedSamplerSuffix != nullptr ? FindAssignedSamplerId(TexAttribs, CombinedSamplerSuffix) : D3DShaderResourceAttribs::InvalidSamplerId; - auto* pNewTexSRV = new (&GetTexSRV(CurrTexSRV)) D3DShaderResourceAttribs(m_ResourceNames, TexAttribs, SamplerId); - if (SamplerId != D3DShaderResourceAttribs::InvalidSamplerId) - { - GetSampler(SamplerId).SetTexSRVId(CurrTexSRV); - } - ++CurrTexSRV; - NewResHandler.OnNewTexSRV(*pNewTexSRV); - } // - ); - - m_ShaderName = m_ResourceNames.CopyString(ShaderName); - - if (CombinedSamplerSuffix != nullptr) - { - m_SamplerSuffix = m_ResourceNames.CopyString(CombinedSamplerSuffix); - -#ifdef DEVELOPMENT - for (Uint32 n = 0; n < GetNumSamplers(); ++n) - { - const auto& Sampler = GetSampler(n); - if (!Sampler.IsCombinedWithTexSRV()) - LOG_ERROR_MESSAGE("Shader '", ShaderName, "' uses combined texture samplers, but sampler '", Sampler.Name, "' is not assigned to any texture"); - } -#endif - } - - VERIFY_EXPR(m_ResourceNames.GetRemainingSize() == 0); - // clang-format off - VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); - VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - // clang-format on -} - -} // namespace Diligent - -namespace std -{ - -template <> -struct hash -{ - size_t operator()(const Diligent::D3DShaderResourceAttribs& Attribs) const - { - return Attribs.GetHash(); - } -}; - -template <> -struct hash -{ - size_t operator()(const Diligent::ShaderResources& Res) const - { - return Res.GetHash(); - } -}; - -} // namespace std diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp new file mode 100644 index 00000000..a2ed64dd --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -0,0 +1,587 @@ +/* + * Copyright 2019-2020 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 +/// Declaration of Diligent::ShaderResources class +/// See http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resources/ + +// ShaderResources class uses continuous chunk of memory to store all resources, as follows: +// +// +// m_MemoryBuffer m_TexSRVOffset m_TexUAVOffset m_BufSRVOffset m_BufUAVOffset m_SamplersOffset m_MemorySize +// | | | | | | | | +// | CB[0] ... CB[Ncb-1] | TexSRV[0] ... TexSRV[Ntsrv-1] | TexUAV[0] ... TexUAV[Ntuav-1] | BufSRV[0] ... BufSRV[Nbsrv-1] | BufUAV[0] ... BufUAV[Nbuav-1] | Sam[0] ... Sam[Nsam-1] | Resource Names | +// +// Ncb - number of constant buffers +// Ntsrv - number of texture SRVs +// Ntuav - number of texture UAVs +// Nbsrv - number of buffer SRVs +// Nbuav - number of buffer UAVs +// Nsam - number of samplers +// +// +// If texture SRV is assigned a sampler, it is cross-referenced through SamplerOrTexSRVId: +// +// _____________________SamplerOrTexSRVId___________________ +// | | +// | V +// | CBs | ... TexSRV[n] ... | TexUAVs | BufSRVs | BufUAVs | Sam[0] ... Sam[SamplerId] ... | +// A | +// '---------------------SamplerOrTexSRVId-------------------' +// + +#include + +#define NOMINMAX +#include + +#include "ShaderD3D.h" +#include "STDAllocator.h" +#include "HashUtils.h" +#include "StringPool.h" +#include "D3DShaderResourceLoader.hpp" +#include "PipelineState.h" + +namespace Diligent +{ + +// sizeof(D3DShaderResourceAttribs) == 16 (x64) +struct D3DShaderResourceAttribs +{ + // clang-format off + +/* 0 */ const char* const Name; + +/* 8 */ const Uint16 BindPoint; +/*10 */ const Uint16 BindCount; + +private: + // 4 4 24 + // bit | 0 1 2 3 | 4 5 6 7 | 8 9 10 ... 31 | + // | | | | + // | InputType | SRV Dim | SamplerOrTexSRVIdBits | + static constexpr const Uint32 ShaderInputTypeBits = 4; + static constexpr const Uint32 SRVDimBits = 4; + static constexpr const Uint32 SamplerOrTexSRVIdBits = 24; + static_assert(ShaderInputTypeBits + SRVDimBits + SamplerOrTexSRVIdBits == 32, "Attributes are better be packed into 32 bits"); + + static_assert(D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER < (1 << ShaderInputTypeBits), "Not enough bits to represent D3D_SHADER_INPUT_TYPE"); + static_assert(D3D_SRV_DIMENSION_BUFFEREX < (1 << SRVDimBits), "Not enough bits to represent D3D_SRV_DIMENSION"); + + // We need to use Uint32 instead of the actual type for reliability and correctness. + // There originally was a problem when the type of InputType was D3D_SHADER_INPUT_TYPE: + // the value of D3D_SIT_UAV_RWBYTEADDRESS (8) was interpreted as -8 (as the underlying enum type + // is signed) causing errors +/*12.0*/ const Uint32 InputType : ShaderInputTypeBits; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER == 11 +/*12.4*/ const Uint32 SRVDimension : SRVDimBits; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11 +/*13.0*/ Uint32 SamplerOrTexSRVId : SamplerOrTexSRVIdBits; // Max value: 2^24-1 +/*16 */ // End of structure + + // clang-format on + +public: + static constexpr const Uint32 InvalidSamplerId = (1 << SamplerOrTexSRVIdBits) - 1; + static constexpr const Uint32 InvalidTexSRVId = (1 << SamplerOrTexSRVIdBits) - 1; + static constexpr const Uint16 InvalidBindPoint = std::numeric_limits::max(); + static constexpr const Uint16 MaxBindPoint = InvalidBindPoint - 1; + static constexpr const Uint16 MaxBindCount = std::numeric_limits::max(); + + + D3DShaderResourceAttribs(const char* _Name, + UINT _BindPoint, + UINT _BindCount, + D3D_SHADER_INPUT_TYPE _InputType, + D3D_SRV_DIMENSION _SRVDimension, + Uint32 _SamplerId) noexcept : + // clang-format off + Name {_Name}, + BindPoint {static_cast (_BindPoint) }, + BindCount {static_cast (_BindCount) }, + InputType {static_cast (_InputType) }, + SRVDimension {static_cast(_SRVDimension)}, + SamplerOrTexSRVId {_SamplerId} + // clang-format on + { +#ifdef _DEBUG + // clang-format off + VERIFY(_BindPoint <= MaxBindPoint || _BindPoint == InvalidBindPoint, "Bind Point is out of allowed range"); + VERIFY(_BindCount <= MaxBindCount, "Bind Count is out of allowed range"); + VERIFY(_InputType < (1 << ShaderInputTypeBits), "Shader input type is out of expected range"); + VERIFY(_SRVDimension < (1 << SRVDimBits), "SRV dimensions is out of expected range"); + VERIFY(_SamplerId < (1 << SamplerOrTexSRVIdBits), "SamplerOrTexSRVId is out of representable range"); + // clang-format on + + if (_InputType == D3D_SIT_TEXTURE && _SRVDimension != D3D_SRV_DIMENSION_BUFFER) + VERIFY_EXPR(GetCombinedSamplerId() == _SamplerId); + else + VERIFY(_SamplerId == InvalidSamplerId, "Only texture SRV can be assigned a valid texture sampler"); +#endif + } + + D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs, Uint32 SamplerId) noexcept : + // clang-format off + D3DShaderResourceAttribs + { + NamesPool.CopyString(rhs.Name), + rhs.BindPoint, + rhs.BindCount, + rhs.GetInputType(), + rhs.GetSRVDimension(), + SamplerId + } + // clang-format on + { + VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Only texture SRV can be assigned a texture sampler"); + } + + D3DShaderResourceAttribs(StringPool& NamesPool, const D3DShaderResourceAttribs& rhs) noexcept : + // clang-format off + D3DShaderResourceAttribs + { + NamesPool.CopyString(rhs.Name), + rhs.BindPoint, + rhs.BindCount, + rhs.GetInputType(), + rhs.GetSRVDimension(), + rhs.SamplerOrTexSRVId + } + // clang-format on + { + } + + // clang-format off + D3DShaderResourceAttribs (const D3DShaderResourceAttribs& rhs) = delete; + D3DShaderResourceAttribs ( D3DShaderResourceAttribs&& rhs) = default; // Required for vector + D3DShaderResourceAttribs& operator = (const D3DShaderResourceAttribs& rhs) = delete; + D3DShaderResourceAttribs& operator = ( D3DShaderResourceAttribs&& rhs) = delete; + // clang-format on + + D3D_SHADER_INPUT_TYPE GetInputType() const + { + return static_cast(InputType); + } + + D3D_SRV_DIMENSION GetSRVDimension() const + { + return static_cast(SRVDimension); + } + + bool IsCombinedWithSampler() const + { + return GetCombinedSamplerId() != InvalidSamplerId; + } + + bool IsCombinedWithTexSRV() const + { + return GetCombinedTexSRVId() != InvalidTexSRVId; + } + + bool IsValidBindPoint() const + { + return BindPoint != InvalidBindPoint; + } + + String GetPrintName(Uint32 ArrayInd) const + { + VERIFY_EXPR(ArrayInd < BindCount); + if (BindCount > 1) + return String(Name) + '[' + std::to_string(ArrayInd) + ']'; + else + return Name; + } + + bool IsCompatibleWith(const D3DShaderResourceAttribs& Attribs) const + { + return BindPoint == Attribs.BindPoint && + BindCount == Attribs.BindCount && + InputType == Attribs.InputType && + SRVDimension == Attribs.SRVDimension && + SamplerOrTexSRVId == Attribs.SamplerOrTexSRVId; + } + + size_t GetHash() const + { + return ComputeHash(BindPoint, BindCount, InputType, SRVDimension, SamplerOrTexSRVId); + } + + HLSLShaderResourceDesc GetHLSLResourceDesc() const; + +private: + friend class ShaderResources; + + Uint32 GetCombinedSamplerId() const + { + VERIFY(GetInputType() == D3D_SIT_TEXTURE && GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER, "Invalid input type: D3D_SIT_TEXTURE is expected"); + return SamplerOrTexSRVId; + } + + void SetTexSRVId(Uint32 TexSRVId) + { + VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected"); + VERIFY(TexSRVId < (1 << SamplerOrTexSRVIdBits), "TexSRVId (", TexSRVId, ") is out of representable range"); + SamplerOrTexSRVId = TexSRVId; + } + + Uint32 GetCombinedTexSRVId() const + { + VERIFY(GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected"); + return SamplerOrTexSRVId; + } +}; +static_assert(sizeof(D3DShaderResourceAttribs) == sizeof(void*) + sizeof(Uint32) * 2, "Unexpected sizeof(D3DShaderResourceAttribs)"); + + +/// Diligent::ShaderResources class +class ShaderResources +{ +public: + ShaderResources(SHADER_TYPE ShaderType) noexcept : + m_ShaderType{ShaderType} + { + } + + // clang-format off + ShaderResources (const ShaderResources&) = delete; + ShaderResources ( ShaderResources&&) = delete; + ShaderResources& operator = (const ShaderResources&) = delete; + ShaderResources& operator = ( ShaderResources&&) = delete; + // clang-format on + + ~ShaderResources(); + + // clang-format off + Uint32 GetNumCBs() const noexcept { return (m_TexSRVOffset - 0); } + Uint32 GetNumTexSRV() const noexcept { return (m_TexUAVOffset - m_TexSRVOffset); } + Uint32 GetNumTexUAV() const noexcept { return (m_BufSRVOffset - m_TexUAVOffset); } + Uint32 GetNumBufSRV() const noexcept { return (m_BufUAVOffset - m_BufSRVOffset); } + Uint32 GetNumBufUAV() const noexcept { return (m_SamplersOffset - m_BufUAVOffset); } + Uint32 GetNumSamplers() const noexcept { return (m_TotalResources - m_SamplersOffset); } + Uint32 GetTotalResources()const noexcept { return m_TotalResources; } + + const D3DShaderResourceAttribs& GetCB (Uint32 n)const noexcept { return GetResAttribs(n, GetNumCBs(), 0); } + const D3DShaderResourceAttribs& GetTexSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } + const D3DShaderResourceAttribs& GetTexUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } + const D3DShaderResourceAttribs& GetBufSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } + const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } + const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + // clang-format on + + const D3DShaderResourceAttribs& GetCombinedSampler(const D3DShaderResourceAttribs& TexSRV) const noexcept + { + VERIFY(TexSRV.IsCombinedWithSampler(), "This texture SRV is not combined with any sampler"); + return GetSampler(TexSRV.GetCombinedSamplerId()); + } + + const D3DShaderResourceAttribs& GetCombinedTextureSRV(const D3DShaderResourceAttribs& Sampler) const noexcept + { + VERIFY(Sampler.IsCombinedWithTexSRV(), "This sampler is not combined with any texture SRV"); + return GetTexSRV(Sampler.GetCombinedTexSRVId()); + } + + SHADER_TYPE GetShaderType() const noexcept { return m_ShaderType; } + + HLSLShaderResourceDesc GetHLSLShaderResourceDesc(Uint32 Index) const; + + template + void ProcessResources(THandleCB HandleCB, + THandleSampler HandleSampler, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV) const + { + for (Uint32 n = 0; n < GetNumCBs(); ++n) + { + const auto& CB = GetCB(n); + HandleCB(CB, n); + } + + for (Uint32 n = 0; n < GetNumSamplers(); ++n) + { + const auto& Sampler = GetSampler(n); + HandleSampler(Sampler, n); + } + + for (Uint32 n = 0; n < GetNumTexSRV(); ++n) + { + const auto& TexSRV = GetTexSRV(n); + HandleTexSRV(TexSRV, n); + } + + for (Uint32 n = 0; n < GetNumTexUAV(); ++n) + { + const auto& TexUAV = GetTexUAV(n); + HandleTexUAV(TexUAV, n); + } + + for (Uint32 n = 0; n < GetNumBufSRV(); ++n) + { + const auto& BufSRV = GetBufSRV(n); + HandleBufSRV(BufSRV, n); + } + + for (Uint32 n = 0; n < GetNumBufUAV(); ++n) + { + const auto& BufUAV = GetBufUAV(n); + HandleBufUAV(BufUAV, n); + } + } + + bool IsCompatibleWith(const ShaderResources& Resources) const; + bool IsUsingCombinedTextureSamplers() const { return m_SamplerSuffix != nullptr; } + const char* GetCombinedSamplerSuffix() const { return m_SamplerSuffix; } + const Char* GetShaderName() const { return m_ShaderName; } + + size_t GetHash() const; + + SHADER_RESOURCE_VARIABLE_TYPE FindVariableType(const D3DShaderResourceAttribs& ResourceAttribs, + const PipelineResourceLayoutDesc& ResourceLayout) const; + + Int32 FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + bool LogStaticSamplerArrayError) const; + + D3DShaderResourceCounters CountResources(const PipelineResourceLayoutDesc& ResourceLayout, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + bool CountStaticSamplers) const noexcept; +#ifdef DEVELOPMENT + static void DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& ResourceLayout, + const ShaderResources* const pShaderResources[], + Uint32 NumShaders); +#endif + + void GetShaderModel(Uint32& Major, Uint32& Minor) const + { + Major = (m_ShaderVersion & 0x000000F0) >> 4; + Minor = (m_ShaderVersion & 0x0000000F); + } + +protected: + template + void Initialize(ID3DBlob* pShaderByteCode, + TNewResourceHandler NewResHandler, + const Char* ShaderName, + const Char* SamplerSuffix); + + + __forceinline D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset) noexcept + { + VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Resource array size: ", NumResources); + VERIFY_EXPR(Offset + n < m_TotalResources); + return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; + } + + __forceinline const D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset) const noexcept + { + VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Resource array size: ", NumResources); + VERIFY_EXPR(Offset + n < m_TotalResources); + return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; + } + + // clang-format off + D3DShaderResourceAttribs& GetCB(Uint32 n) noexcept { return GetResAttribs(n, GetNumCBs(), 0); } + D3DShaderResourceAttribs& GetTexSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } + D3DShaderResourceAttribs& GetTexUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } + D3DShaderResourceAttribs& GetBufSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } + D3DShaderResourceAttribs& GetBufUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } + D3DShaderResourceAttribs& GetSampler(Uint32 n) noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + // clang-format on + +private: + void AllocateMemory(IMemoryAllocator& Allocator, + const D3DShaderResourceCounters& ResCounters, + size_t ResourceNamesPoolSize); + + Uint32 FindAssignedSamplerId(const D3DShaderResourceAttribs& TexSRV, const char* SamplerSuffix) const; + + // Memory buffer that holds all resources as continuous chunk of memory: + // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | Resource Names | + // + + std::unique_ptr> m_MemoryBuffer; + + StringPool m_ResourceNames; + const char* m_SamplerSuffix = nullptr; // The suffix and the shader name + const char* m_ShaderName = nullptr; // are put into the m_ResourceNames + + // Offsets in elements of D3DShaderResourceAttribs + typedef Uint16 OffsetType; + OffsetType m_TexSRVOffset = 0; + OffsetType m_TexUAVOffset = 0; + OffsetType m_BufSRVOffset = 0; + OffsetType m_BufUAVOffset = 0; + OffsetType m_SamplersOffset = 0; + OffsetType m_TotalResources = 0; + + const SHADER_TYPE m_ShaderType; + + Uint32 m_ShaderVersion = 0; +}; + + +template +void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, + TNewResourceHandler NewResHandler, + const Char* ShaderName, + const Char* CombinedSamplerSuffix) +{ + Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; + LoadD3DShaderResources( + pShaderByteCode, + + [&](const D3D_SHADER_DESC& d3dShaderDesc) // + { + m_ShaderVersion = d3dShaderDesc.Version; + }, + + [&](const D3DShaderResourceCounters& ResCounters, size_t ResourceNamesPoolSize) // + { + VERIFY_EXPR(ShaderName != nullptr); + ResourceNamesPoolSize += strlen(ShaderName) + 1; + + if (CombinedSamplerSuffix != nullptr) + ResourceNamesPoolSize += strlen(CombinedSamplerSuffix) + 1; + + AllocateMemory(GetRawAllocator(), ResCounters, ResourceNamesPoolSize); + }, + + [&](const D3DShaderResourceAttribs& CBAttribs) // + { + VERIFY_EXPR(CBAttribs.GetInputType() == D3D_SIT_CBUFFER); + auto* pNewCB = new (&GetCB(CurrCB++)) D3DShaderResourceAttribs(m_ResourceNames, CBAttribs); + NewResHandler.OnNewCB(*pNewCB); + }, + + [&](const D3DShaderResourceAttribs& TexUAV) // + { + VERIFY_EXPR(TexUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && TexUAV.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); + auto* pNewTexUAV = new (&GetTexUAV(CurrTexUAV++)) D3DShaderResourceAttribs(m_ResourceNames, TexUAV); + NewResHandler.OnNewTexUAV(*pNewTexUAV); + }, + + [&](const D3DShaderResourceAttribs& BuffUAV) // + { + VERIFY_EXPR(BuffUAV.GetInputType() == D3D_SIT_UAV_RWTYPED && BuffUAV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffUAV.GetInputType() == D3D_SIT_UAV_RWSTRUCTURED || BuffUAV.GetInputType() == D3D_SIT_UAV_RWBYTEADDRESS); + auto* pNewBufUAV = new (&GetBufUAV(CurrBufUAV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffUAV); + NewResHandler.OnNewBuffUAV(*pNewBufUAV); + }, + + [&](const D3DShaderResourceAttribs& BuffSRV) // + { + VERIFY_EXPR(BuffSRV.GetInputType() == D3D_SIT_TEXTURE && BuffSRV.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER || BuffSRV.GetInputType() == D3D_SIT_STRUCTURED || BuffSRV.GetInputType() == D3D_SIT_BYTEADDRESS); + auto* pNewBuffSRV = new (&GetBufSRV(CurrBufSRV++)) D3DShaderResourceAttribs(m_ResourceNames, BuffSRV); + NewResHandler.OnNewBuffSRV(*pNewBuffSRV); + }, + + [&](const D3DShaderResourceAttribs& SamplerAttribs) // + { + VERIFY_EXPR(SamplerAttribs.GetInputType() == D3D_SIT_SAMPLER); + auto* pNewSampler = new (&GetSampler(CurrSampler++)) D3DShaderResourceAttribs(m_ResourceNames, SamplerAttribs); + NewResHandler.OnNewSampler(*pNewSampler); + }, + + [&](const D3DShaderResourceAttribs& TexAttribs) // + { + VERIFY_EXPR(TexAttribs.GetInputType() == D3D_SIT_TEXTURE && TexAttribs.GetSRVDimension() != D3D_SRV_DIMENSION_BUFFER); + VERIFY(CurrSampler == GetNumSamplers(), "All samplers must be initialized before texture SRVs"); + + auto SamplerId = CombinedSamplerSuffix != nullptr ? FindAssignedSamplerId(TexAttribs, CombinedSamplerSuffix) : D3DShaderResourceAttribs::InvalidSamplerId; + auto* pNewTexSRV = new (&GetTexSRV(CurrTexSRV)) D3DShaderResourceAttribs(m_ResourceNames, TexAttribs, SamplerId); + if (SamplerId != D3DShaderResourceAttribs::InvalidSamplerId) + { + GetSampler(SamplerId).SetTexSRVId(CurrTexSRV); + } + ++CurrTexSRV; + NewResHandler.OnNewTexSRV(*pNewTexSRV); + } // + ); + + m_ShaderName = m_ResourceNames.CopyString(ShaderName); + + if (CombinedSamplerSuffix != nullptr) + { + m_SamplerSuffix = m_ResourceNames.CopyString(CombinedSamplerSuffix); + +#ifdef DEVELOPMENT + for (Uint32 n = 0; n < GetNumSamplers(); ++n) + { + const auto& Sampler = GetSampler(n); + if (!Sampler.IsCombinedWithTexSRV()) + LOG_ERROR_MESSAGE("Shader '", ShaderName, "' uses combined texture samplers, but sampler '", Sampler.Name, "' is not assigned to any texture"); + } +#endif + } + + VERIFY_EXPR(m_ResourceNames.GetRemainingSize() == 0); + // clang-format off + VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); + VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + // clang-format on +} + +} // namespace Diligent + +namespace std +{ + +template <> +struct hash +{ + size_t operator()(const Diligent::D3DShaderResourceAttribs& Attribs) const + { + return Attribs.GetHash(); + } +}; + +template <> +struct hash +{ + size_t operator()(const Diligent::ShaderResources& Res) const + { + return Res.GetHash(); + } +}; + +} // namespace std diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.h deleted file mode 100644 index 3c566b20..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include "ShaderResourceVariableBase.h" -#include "ShaderResourceVariableD3D.h" - -/// \file -/// Declaration of Diligent::ShaderVariableD3DBase class - -namespace Diligent -{ - -struct D3DVariableIDComparator -{ - bool operator()(const INTERFACE_ID& IID) const - { - return IID == IID_ShaderResourceVariableD3D || IID == IID_ShaderResourceVariable || IID == IID_Unknown; - } -}; - -template -struct ShaderVariableD3DBase : public ShaderVariableBase -{ - using TBase = ShaderVariableBase; - - ShaderVariableD3DBase(TShaderResourceLayout& ParentResLayout, - const D3DShaderResourceAttribs& Attribs, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - // clang-format off - TBase {ParentResLayout}, - m_Attribs {Attribs }, - m_VariableType {VariableType } - // clang-format on - { - } - - virtual SHADER_RESOURCE_VARIABLE_TYPE GetType() const override final - { - return m_VariableType; - } - - virtual void GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final - { - ResourceDesc = GetHLSLResourceDesc(); - } - - virtual HLSLShaderResourceDesc GetHLSLResourceDesc() const override final - { - return m_Attribs.GetHLSLResourceDesc(); - } - - virtual Uint32 GetIndex() const override final - { - return m_ParentResLayout.GetVariableIndex(*this); - } - - const D3DShaderResourceAttribs& m_Attribs; - -protected: - const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp new file mode 100644 index 00000000..c89610f9 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp @@ -0,0 +1,89 @@ +/* + * Copyright 2019-2020 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 + +#include "ShaderResourceVariableBase.hpp" +#include "ShaderResourceVariableD3D.h" + +/// \file +/// Declaration of Diligent::ShaderVariableD3DBase class + +namespace Diligent +{ + +struct D3DVariableIDComparator +{ + bool operator()(const INTERFACE_ID& IID) const + { + return IID == IID_ShaderResourceVariableD3D || IID == IID_ShaderResourceVariable || IID == IID_Unknown; + } +}; + +template +struct ShaderVariableD3DBase : public ShaderVariableBase +{ + using TBase = ShaderVariableBase; + + ShaderVariableD3DBase(TShaderResourceLayout& ParentResLayout, + const D3DShaderResourceAttribs& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VariableType) : + // clang-format off + TBase {ParentResLayout}, + m_Attribs {Attribs }, + m_VariableType {VariableType } + // clang-format on + { + } + + virtual SHADER_RESOURCE_VARIABLE_TYPE GetType() const override final + { + return m_VariableType; + } + + virtual void GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final + { + ResourceDesc = GetHLSLResourceDesc(); + } + + virtual HLSLShaderResourceDesc GetHLSLResourceDesc() const override final + { + return m_Attribs.GetHLSLResourceDesc(); + } + + virtual Uint32 GetIndex() const override final + { + return m_ParentResLayout.GetVariableIndex(*this); + } + + const D3DShaderResourceAttribs& m_Attribs; + +protected: + const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.h deleted file mode 100644 index a3b091d2..00000000 --- a/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright 2019-2020 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 - -#include -#include "SwapChainBase.h" - -/// \file -/// Base implementation of a D3D swap chain - -namespace Diligent -{ - -/// Base implementation of a D3D swap chain -template -class SwapChainD3DBase : public SwapChainBase -{ -public: - using TBase = SwapChainBase; - SwapChainD3DBase(IReferenceCounters* pRefCounters, - IRenderDevice* pDevice, - IDeviceContext* pDeviceContext, - const SwapChainDesc& SCDesc, - const FullScreenModeDesc& FSDesc, - void* pNativeWndHandle) : - // clang-format off - TBase{pRefCounters, pDevice, pDeviceContext, SCDesc}, - m_FSDesc {FSDesc}, - m_pNativeWndHandle {pNativeWndHandle} - // clang-format on - {} - - ~SwapChainD3DBase() - { - if (m_pSwapChain) - { - // Swap chain must be in windowed mode when it is destroyed - // https://msdn.microsoft.com/en-us/library/windows/desktop/bb205075(v=vs.85).aspx#Destroying - BOOL IsFullScreen = FALSE; - m_pSwapChain->GetFullscreenState(&IsFullScreen, nullptr); - if (IsFullScreen) - m_pSwapChain->SetFullscreenState(FALSE, nullptr); - } - } - -protected: - virtual void UpdateSwapChain(bool CreateNew) = 0; - - void CreateDXGISwapChain(IUnknown* pD3D11DeviceOrD3D12CmdQueue) - { -#if PLATFORM_WIN32 - auto hWnd = reinterpret_cast(m_pNativeWndHandle); - if (m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0) - { - RECT rc; - if (m_FSDesc.Fullscreen) - { - const HWND hDesktop = GetDesktopWindow(); - GetWindowRect(hDesktop, &rc); - } - else - { - GetClientRect(hWnd, &rc); - } - m_SwapChainDesc.Width = rc.right - rc.left; - m_SwapChainDesc.Height = rc.bottom - rc.top; - } -#endif - - auto DXGIColorBuffFmt = TexFormatToDXGI_Format(m_SwapChainDesc.ColorBufferFormat); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; - - swapChainDesc.Width = m_SwapChainDesc.Width; - swapChainDesc.Height = m_SwapChainDesc.Height; - // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats: - // - DXGI_FORMAT_R16G16B16A16_FLOAT - // - DXGI_FORMAT_B8G8R8A8_UNORM - // - DXGI_FORMAT_R8G8B8A8_UNORM - // - DXGI_FORMAT_R10G10B10A2_UNORM - // If RGBA8_UNORM_SRGB swap chain is required, we will create RGBA8_UNORM swap chain, but - // create RGBA8_UNORM_SRGB render target view - switch (DXGIColorBuffFmt) - { - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - break; - - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - break; - - default: - swapChainDesc.Format = DXGIColorBuffFmt; - } - - swapChainDesc.Stereo = FALSE; - - // Multi-sampled swap chains are not supported anymore. CreateSwapChainForHwnd() fails when sample count is not 1 - // for any swap effect. - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - - DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined"); - swapChainDesc.BufferUsage = 0; - if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_RENDER_TARGET) - swapChainDesc.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; - if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_SHADER_INPUT) - swapChainDesc.BufferUsage |= DXGI_USAGE_SHADER_INPUT; - //if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_COPY_SOURCE) - // ; - - swapChainDesc.BufferCount = m_SwapChainDesc.BufferCount; - swapChainDesc.Scaling = DXGI_SCALING_NONE; - -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - // DXGI_SCALING_NONE is supported starting with Windows 8 - if (!IsWindows8OrGreater()) - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; -#endif - - // DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL is the flip presentation model, where the contents of the back - // buffer is preserved after the call to Present. This flag cannot be used with multisampling. - // The only swap effect that supports multisampling is DXGI_SWAP_EFFECT_DISCARD. - // Windows Store apps must use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL or DXGI_SWAP_EFFECT_FLIP_DISCARD. - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Transparency behavior is not specified - - // DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH enables an application to switch modes by calling - // IDXGISwapChain::ResizeTarget(). When switching from windowed to fullscreen mode, the display - // mode (or monitor resolution) will be changed to match the dimensions of the application window. - swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - - CComPtr pSwapChain1; - CComPtr factory; - HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory))); - CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory"); - -#if PLATFORM_WIN32 - - DXGI_SWAP_CHAIN_FULLSCREEN_DESC FullScreenDesc = {}; - - FullScreenDesc.Windowed = m_FSDesc.Fullscreen ? FALSE : TRUE; - FullScreenDesc.RefreshRate.Numerator = m_FSDesc.RefreshRateNumerator; - FullScreenDesc.RefreshRate.Denominator = m_FSDesc.RefreshRateDenominator; - FullScreenDesc.Scaling = static_cast(m_FSDesc.Scaling); - FullScreenDesc.ScanlineOrdering = static_cast(m_FSDesc.ScanlineOrder); - - hr = factory->CreateSwapChainForHwnd(pD3D11DeviceOrD3D12CmdQueue, hWnd, &swapChainDesc, &FullScreenDesc, nullptr, &pSwapChain1); - CHECK_D3D_RESULT_THROW(hr, "Failed to create Swap Chain"); - - { - // This is silly, but IDXGIFactory used for MakeWindowAssociation must be retrieved via - // calling IDXGISwapchain::GetParent first, otherwise it won't work - // https://www.gamedev.net/forums/topic/634235-dxgidisabling-altenter/?do=findComment&comment=4999990 - CComPtr pFactoryFromSC; - if (SUCCEEDED(pSwapChain1->GetParent(__uuidof(pFactoryFromSC), (void**)&pFactoryFromSC))) - { - // Do not allow the swap chain to handle Alt+Enter - pFactoryFromSC->MakeWindowAssociation(hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER); - } - } - -#elif PLATFORM_UNIVERSAL_WINDOWS - - if (m_FSDesc.Fullscreen) - LOG_WARNING_MESSAGE("UWP applications do not support fullscreen mode"); - - hr = factory->CreateSwapChainForCoreWindow( - pD3D11DeviceOrD3D12CmdQueue, - reinterpret_cast(m_pNativeWndHandle), - &swapChainDesc, - nullptr, - &pSwapChain1); - CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI swap chain"); - - // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and - // ensures that the application will only render after each VSync, minimizing power consumption. - //pDXGIDevice->SetMaximumFrameLatency( 1 ); - -#endif - - pSwapChain1->QueryInterface(__uuidof(m_pSwapChain), reinterpret_cast(static_cast(&m_pSwapChain))); - } - - virtual void SetFullscreenMode(const DisplayModeAttribs& DisplayMode) override final - { - if (m_pSwapChain) - { - // If we are already in fullscreen mode, we need to switch to windowed mode first, - // because a swap chain must be in windowed mode when it is released. - // https://msdn.microsoft.com/en-us/library/windows/desktop/bb205075(v=vs.85).aspx#Destroying - if (m_FSDesc.Fullscreen) - m_pSwapChain->SetFullscreenState(FALSE, nullptr); - m_FSDesc.Fullscreen = True; - m_FSDesc.RefreshRateNumerator = DisplayMode.RefreshRateNumerator; - m_FSDesc.RefreshRateDenominator = DisplayMode.RefreshRateDenominator; - m_FSDesc.Scaling = DisplayMode.Scaling; - m_FSDesc.ScanlineOrder = DisplayMode.ScanlineOrder; - m_SwapChainDesc.Width = DisplayMode.Width; - m_SwapChainDesc.Height = DisplayMode.Height; - if (DisplayMode.Format != TEX_FORMAT_UNKNOWN) - m_SwapChainDesc.ColorBufferFormat = DisplayMode.Format; - UpdateSwapChain(true); - } - } - - virtual void SetWindowedMode() override final - { - if (m_FSDesc.Fullscreen) - { - m_FSDesc.Fullscreen = False; - m_pSwapChain->SetFullscreenState(FALSE, nullptr); - } - } - - FullScreenModeDesc m_FSDesc; - CComPtr m_pSwapChain; - void* m_pNativeWndHandle; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp new file mode 100644 index 00000000..70856a63 --- /dev/null +++ b/Graphics/GraphicsEngineD3DBase/include/SwapChainD3DBase.hpp @@ -0,0 +1,248 @@ +/* + * Copyright 2019-2020 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 + +#include +#include "SwapChainBase.hpp" + +/// \file +/// Base implementation of a D3D swap chain + +namespace Diligent +{ + +/// Base implementation of a D3D swap chain +template +class SwapChainD3DBase : public SwapChainBase +{ +public: + using TBase = SwapChainBase; + SwapChainD3DBase(IReferenceCounters* pRefCounters, + IRenderDevice* pDevice, + IDeviceContext* pDeviceContext, + const SwapChainDesc& SCDesc, + const FullScreenModeDesc& FSDesc, + void* pNativeWndHandle) : + // clang-format off + TBase{pRefCounters, pDevice, pDeviceContext, SCDesc}, + m_FSDesc {FSDesc}, + m_pNativeWndHandle {pNativeWndHandle} + // clang-format on + {} + + ~SwapChainD3DBase() + { + if (m_pSwapChain) + { + // Swap chain must be in windowed mode when it is destroyed + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb205075(v=vs.85).aspx#Destroying + BOOL IsFullScreen = FALSE; + m_pSwapChain->GetFullscreenState(&IsFullScreen, nullptr); + if (IsFullScreen) + m_pSwapChain->SetFullscreenState(FALSE, nullptr); + } + } + +protected: + virtual void UpdateSwapChain(bool CreateNew) = 0; + + void CreateDXGISwapChain(IUnknown* pD3D11DeviceOrD3D12CmdQueue) + { +#if PLATFORM_WIN32 + auto hWnd = reinterpret_cast(m_pNativeWndHandle); + if (m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0) + { + RECT rc; + if (m_FSDesc.Fullscreen) + { + const HWND hDesktop = GetDesktopWindow(); + GetWindowRect(hDesktop, &rc); + } + else + { + GetClientRect(hWnd, &rc); + } + m_SwapChainDesc.Width = rc.right - rc.left; + m_SwapChainDesc.Height = rc.bottom - rc.top; + } +#endif + + auto DXGIColorBuffFmt = TexFormatToDXGI_Format(m_SwapChainDesc.ColorBufferFormat); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + + swapChainDesc.Width = m_SwapChainDesc.Width; + swapChainDesc.Height = m_SwapChainDesc.Height; + // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats: + // - DXGI_FORMAT_R16G16B16A16_FLOAT + // - DXGI_FORMAT_B8G8R8A8_UNORM + // - DXGI_FORMAT_R8G8B8A8_UNORM + // - DXGI_FORMAT_R10G10B10A2_UNORM + // If RGBA8_UNORM_SRGB swap chain is required, we will create RGBA8_UNORM swap chain, but + // create RGBA8_UNORM_SRGB render target view + switch (DXGIColorBuffFmt) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + break; + + default: + swapChainDesc.Format = DXGIColorBuffFmt; + } + + swapChainDesc.Stereo = FALSE; + + // Multi-sampled swap chains are not supported anymore. CreateSwapChainForHwnd() fails when sample count is not 1 + // for any swap effect. + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + + DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined"); + swapChainDesc.BufferUsage = 0; + if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_RENDER_TARGET) + swapChainDesc.BufferUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT; + if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_SHADER_INPUT) + swapChainDesc.BufferUsage |= DXGI_USAGE_SHADER_INPUT; + //if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_COPY_SOURCE) + // ; + + swapChainDesc.BufferCount = m_SwapChainDesc.BufferCount; + swapChainDesc.Scaling = DXGI_SCALING_NONE; + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + // DXGI_SCALING_NONE is supported starting with Windows 8 + if (!IsWindows8OrGreater()) + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; +#endif + + // DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL is the flip presentation model, where the contents of the back + // buffer is preserved after the call to Present. This flag cannot be used with multisampling. + // The only swap effect that supports multisampling is DXGI_SWAP_EFFECT_DISCARD. + // Windows Store apps must use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL or DXGI_SWAP_EFFECT_FLIP_DISCARD. + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Transparency behavior is not specified + + // DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH enables an application to switch modes by calling + // IDXGISwapChain::ResizeTarget(). When switching from windowed to fullscreen mode, the display + // mode (or monitor resolution) will be changed to match the dimensions of the application window. + swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + CComPtr pSwapChain1; + CComPtr factory; + HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory))); + CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory"); + +#if PLATFORM_WIN32 + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC FullScreenDesc = {}; + + FullScreenDesc.Windowed = m_FSDesc.Fullscreen ? FALSE : TRUE; + FullScreenDesc.RefreshRate.Numerator = m_FSDesc.RefreshRateNumerator; + FullScreenDesc.RefreshRate.Denominator = m_FSDesc.RefreshRateDenominator; + FullScreenDesc.Scaling = static_cast(m_FSDesc.Scaling); + FullScreenDesc.ScanlineOrdering = static_cast(m_FSDesc.ScanlineOrder); + + hr = factory->CreateSwapChainForHwnd(pD3D11DeviceOrD3D12CmdQueue, hWnd, &swapChainDesc, &FullScreenDesc, nullptr, &pSwapChain1); + CHECK_D3D_RESULT_THROW(hr, "Failed to create Swap Chain"); + + { + // This is silly, but IDXGIFactory used for MakeWindowAssociation must be retrieved via + // calling IDXGISwapchain::GetParent first, otherwise it won't work + // https://www.gamedev.net/forums/topic/634235-dxgidisabling-altenter/?do=findComment&comment=4999990 + CComPtr pFactoryFromSC; + if (SUCCEEDED(pSwapChain1->GetParent(__uuidof(pFactoryFromSC), (void**)&pFactoryFromSC))) + { + // Do not allow the swap chain to handle Alt+Enter + pFactoryFromSC->MakeWindowAssociation(hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER); + } + } + +#elif PLATFORM_UNIVERSAL_WINDOWS + + if (m_FSDesc.Fullscreen) + LOG_WARNING_MESSAGE("UWP applications do not support fullscreen mode"); + + hr = factory->CreateSwapChainForCoreWindow( + pD3D11DeviceOrD3D12CmdQueue, + reinterpret_cast(m_pNativeWndHandle), + &swapChainDesc, + nullptr, + &pSwapChain1); + CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI swap chain"); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + //pDXGIDevice->SetMaximumFrameLatency( 1 ); + +#endif + + pSwapChain1->QueryInterface(__uuidof(m_pSwapChain), reinterpret_cast(static_cast(&m_pSwapChain))); + } + + virtual void SetFullscreenMode(const DisplayModeAttribs& DisplayMode) override final + { + if (m_pSwapChain) + { + // If we are already in fullscreen mode, we need to switch to windowed mode first, + // because a swap chain must be in windowed mode when it is released. + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb205075(v=vs.85).aspx#Destroying + if (m_FSDesc.Fullscreen) + m_pSwapChain->SetFullscreenState(FALSE, nullptr); + m_FSDesc.Fullscreen = True; + m_FSDesc.RefreshRateNumerator = DisplayMode.RefreshRateNumerator; + m_FSDesc.RefreshRateDenominator = DisplayMode.RefreshRateDenominator; + m_FSDesc.Scaling = DisplayMode.Scaling; + m_FSDesc.ScanlineOrder = DisplayMode.ScanlineOrder; + m_SwapChainDesc.Width = DisplayMode.Width; + m_SwapChainDesc.Height = DisplayMode.Height; + if (DisplayMode.Format != TEX_FORMAT_UNKNOWN) + m_SwapChainDesc.ColorBufferFormat = DisplayMode.Format; + UpdateSwapChain(true); + } + } + + virtual void SetWindowedMode() override final + { + if (m_FSDesc.Fullscreen) + { + m_FSDesc.Fullscreen = False; + m_pSwapChain->SetFullscreenState(FALSE, nullptr); + } + } + + FullScreenModeDesc m_FSDesc; + CComPtr m_pSwapChain; + void* m_pNativeWndHandle; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp index 07cd4536..20fe247e 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp @@ -28,11 +28,11 @@ #include #include -#include "D3DErrors.h" +#include "D3DErrors.hpp" #include "DataBlobImpl.h" #include "RefCntAutoPtr.h" #include -#include "ShaderD3DBase.h" +#include "ShaderD3DBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 34742425..b56fa540 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -28,9 +28,9 @@ #include "pch.h" #include "EngineMemory.h" #include "StringTools.h" -#include "ShaderResources.h" +#include "ShaderResources.hpp" #include "HashUtils.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" #include "Align.h" namespace Diligent diff --git a/Graphics/GraphicsEngineNextGenBase/include/DeviceContextNextGenBase.h b/Graphics/GraphicsEngineNextGenBase/include/DeviceContextNextGenBase.h index f5b04389..8954e3d4 100644 --- a/Graphics/GraphicsEngineNextGenBase/include/DeviceContextNextGenBase.h +++ b/Graphics/GraphicsEngineNextGenBase/include/DeviceContextNextGenBase.h @@ -31,7 +31,7 @@ #include "BasicTypes.h" #include "ReferenceCounters.h" #include "RefCntAutoPtr.h" -#include "DeviceContextBase.h" +#include "DeviceContextBase.hpp" #include "RefCntAutoPtr.h" namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h index 591a619a..d20387a0 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/BufferGLImpl.h @@ -28,7 +28,7 @@ #pragma once #include "BufferGL.h" -#include "BufferBase.h" +#include "BufferBase.hpp" #include "GLObjectWrapper.h" #include "AsyncWritableResource.h" #include "BaseInterfacesGL.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h index 5cfabefd..af999d75 100644 --- a/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/BufferViewGLImpl.h @@ -29,7 +29,7 @@ #include "BufferViewGL.h" #include "BaseInterfacesGL.h" -#include "BufferViewBase.h" +#include "BufferViewBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h index b18fd7c1..1c314e48 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h @@ -28,7 +28,7 @@ #pragma once #include "DeviceContextGL.h" -#include "DeviceContextBase.h" +#include "DeviceContextBase.hpp" #include "BaseInterfacesGL.h" #include "GLContextState.h" #include "GLObjectWrapper.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h index 88669737..f7fc4338 100644 --- a/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/FenceGLImpl.h @@ -33,7 +33,7 @@ #include #include "FenceGL.h" #include "RenderDeviceGL.h" -#include "FenceBase.h" +#include "FenceBase.hpp" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.h b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.h index 7b95aadc..967f9411 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.h @@ -70,7 +70,7 @@ #include #include "Object.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" #include "GLProgramResources.h" #include "GLProgramResourceCache.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.h b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.h index 8aa14a79..40c64c8e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.h +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.h @@ -44,7 +44,7 @@ #include "Object.h" #include "StringPool.h" #include "HashUtils.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h index 28070e6b..1893f2c7 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.h @@ -29,7 +29,7 @@ #include #include "PipelineStateGL.h" -#include "PipelineStateBase.h" +#include "PipelineStateBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "GLContext.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/QueryGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/QueryGLImpl.h index f10c7bf2..4725db86 100644 --- a/Graphics/GraphicsEngineOpenGL/include/QueryGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/QueryGLImpl.h @@ -32,7 +32,7 @@ #include "QueryGL.h" #include "RenderDeviceGL.h" -#include "QueryBase.h" +#include "QueryBase.hpp" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h index a048eee2..b5dcfa80 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.h @@ -28,7 +28,7 @@ #pragma once #include -#include "RenderDeviceBase.h" +#include "RenderDeviceBase.hpp" #include "GLContext.h" #include "VAOCache.h" #include "BaseInterfacesGL.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h index 39ec621e..23c94545 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/SamplerGLImpl.h @@ -29,7 +29,7 @@ #include "BaseInterfacesGL.h" #include "SamplerGL.h" -#include "SamplerBase.h" +#include "SamplerBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h index a2528381..5a855e18 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.h @@ -29,7 +29,7 @@ #include "BaseInterfacesGL.h" #include "ShaderGL.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h index 9a845340..46b4ebd1 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceBindingGLImpl.h @@ -32,9 +32,9 @@ #include "ShaderResourceBindingGL.h" #include "RenderDeviceGL.h" -#include "ShaderResourceBindingBase.h" +#include "ShaderResourceBindingBase.hpp" #include "GLProgramResources.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "GLProgramResourceCache.h" #include "GLPipelineResourceLayout.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.h b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.h index 8ab5cd8a..19d5afb0 100644 --- a/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.h +++ b/Graphics/GraphicsEngineOpenGL/include/SwapChainGLBase.h @@ -27,7 +27,7 @@ #pragma once -#include "SwapChainBase.h" +#include "SwapChainBase.hpp" #include "TextureViewGLImpl.h" namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h index e0e29714..5865f435 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.h @@ -29,7 +29,7 @@ #include "BaseInterfacesGL.h" #include "TextureGL.h" -#include "TextureBase.h" +#include "TextureBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "TextureViewGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h index ea3a4d8f..2a3b831c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/TextureViewGLImpl.h @@ -29,7 +29,7 @@ #include "BaseInterfacesGL.h" #include "TextureViewGL.h" -#include "TextureViewBase.h" +#include "TextureViewBase.hpp" #include "RenderDevice.h" #include "GLObjectWrapper.h" #include "RenderDeviceGLImpl.h" diff --git a/Graphics/GraphicsEngineOpenGL/include/VAOCache.h b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h index b1434b1f..b7dbd93f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/VAOCache.h +++ b/Graphics/GraphicsEngineOpenGL/include/VAOCache.h @@ -33,7 +33,7 @@ #include "InputLayout.h" #include "LockHelper.h" #include "HashUtils.h" -#include "DeviceContextBase.h" +#include "DeviceContextBase.hpp" #include "BaseInterfacesGL.h" namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp b/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp index 04a19d7e..d8bb9d51 100644 --- a/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp @@ -34,7 +34,7 @@ #include "DeviceContextGLImpl.h" #include "EngineMemory.h" #include "HLSL2GLSLConverterObject.h" -#include "EngineFactoryBase.h" +#include "EngineFactoryBase.hpp" #if PLATFORM_IOS # include "SwapChainGLIOS.h" diff --git a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp index 865e8d42..fb4feea1 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp @@ -30,7 +30,7 @@ #include "GLPipelineResourceLayout.h" #include "Align.h" #include "PlatformMisc.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp index 7c1da197..0c618c2f 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResources.cpp @@ -30,8 +30,8 @@ #include "GLContextState.h" #include "GLProgramResources.h" #include "RenderDeviceGLImpl.h" -#include "ShaderResourceBindingBase.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceBindingBase.hpp" +#include "ShaderResourceVariableBase.hpp" #include "Align.h" namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h index 0ce3f911..d2dc9285 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h @@ -32,7 +32,7 @@ #include "BufferViewVk.h" #include "RenderDeviceVk.h" -#include "BufferViewBase.h" +#include "BufferViewBase.hpp" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h index 24a664f7..fade6a46 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h @@ -32,7 +32,7 @@ #include "BufferVk.h" #include "RenderDeviceVk.h" -#include "BufferBase.h" +#include "BufferBase.hpp" #include "BufferViewVkImpl.h" #include "VulkanDynamicHeap.h" #include "VulkanUtilities/VulkanObjectWrappers.h" diff --git a/Graphics/GraphicsEngineVulkan/include/CommandListVkImpl.h b/Graphics/GraphicsEngineVulkan/include/CommandListVkImpl.h index 3cf32d25..4084e51c 100644 --- a/Graphics/GraphicsEngineVulkan/include/CommandListVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/CommandListVkImpl.h @@ -31,7 +31,7 @@ /// Declaration of Diligent::CommandListVkImpl class #include "vulkan.h" -#include "CommandListBase.h" +#include "CommandListBase.hpp" #include "RenderDeviceVkImpl.h" namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h index 4743ba11..27aa8510 100644 --- a/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/FenceVkImpl.h @@ -32,7 +32,7 @@ #include #include "FenceVk.h" -#include "FenceBase.h" +#include "FenceBase.hpp" #include "VulkanUtilities/VulkanFencePool.h" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/ManagedVulkanObject.h b/Graphics/GraphicsEngineVulkan/include/ManagedVulkanObject.h index 90ef0151..d2c11471 100644 --- a/Graphics/GraphicsEngineVulkan/include/ManagedVulkanObject.h +++ b/Graphics/GraphicsEngineVulkan/include/ManagedVulkanObject.h @@ -27,7 +27,7 @@ #pragma once -#include "DeviceObjectBase.h" +#include "DeviceObjectBase.hpp" #include "RenderDeviceVkImpl.h" #include "VulkanUtilities/VulkanLogicalDevice.h" diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h index 861013d7..acd60630 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h @@ -31,7 +31,7 @@ /// Declaration of Diligent::PipelineLayout class #include -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "ShaderResourceLayoutVk.h" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "VulkanUtilities/VulkanLogicalDevice.h" diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h index 62306819..d41e7ce5 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h @@ -34,7 +34,7 @@ #include "RenderDeviceVk.h" #include "PipelineStateVk.h" -#include "PipelineStateBase.h" +#include "PipelineStateBase.hpp" #include "PipelineLayout.h" #include "ShaderResourceLayoutVk.h" #include "ShaderVariableVk.h" diff --git a/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.h b/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.h index 9782a6c8..c326ce4f 100644 --- a/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.h @@ -31,7 +31,7 @@ /// Declaration of Diligent::QueryVkImpl class #include "QueryVk.h" -#include "QueryBase.h" +#include "QueryBase.hpp" #include "RenderDeviceVkImpl.h" #include "QueryManagerVk.h" diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h index bbdab268..66683412 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h @@ -32,7 +32,7 @@ #include #include "RenderDeviceVk.h" -#include "RenderDeviceBase.h" +#include "RenderDeviceBase.hpp" #include "RenderDeviceNextGenBase.h" #include "DescriptorPoolManager.h" #include "VulkanDynamicHeap.h" diff --git a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h index 0a7b585a..ed412ed7 100644 --- a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h @@ -32,7 +32,7 @@ #include "SamplerVk.h" #include "RenderDeviceVk.h" -#include "SamplerBase.h" +#include "SamplerBase.hpp" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h index 786ed279..b79177e5 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h @@ -32,8 +32,8 @@ #include "ShaderResourceBindingVk.h" #include "RenderDeviceVk.h" -#include "ShaderResourceBindingBase.h" -#include "ShaderBase.h" +#include "ShaderResourceBindingBase.hpp" +#include "ShaderBase.hpp" #include "ShaderResourceCacheVk.h" #include "ShaderVariableVk.h" diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h index a9737056..2cd12452 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h @@ -101,7 +101,7 @@ #include #include "PipelineState.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "HashUtils.h" #include "ShaderResourceCacheVk.h" #include "SPIRVShaderResources.hpp" diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h index 43e47834..b494f4b5 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h @@ -62,7 +62,7 @@ #include #include "ShaderResourceLayoutVk.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h index b8297102..d1bee3ba 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h @@ -32,7 +32,7 @@ #include "RenderDeviceVk.h" #include "ShaderVk.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "SPIRVShaderResources.hpp" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h index b4221c5c..807d7489 100644 --- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h @@ -31,7 +31,7 @@ /// Declaration of Diligent::SwapChainVkImpl class #include "SwapChainVk.h" -#include "SwapChainBase.h" +#include "SwapChainBase.hpp" #include "VulkanUtilities/VulkanInstance.h" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "ManagedVulkanObject.h" diff --git a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h index 853ddcec..abde01ef 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h @@ -32,7 +32,7 @@ #include "TextureViewVk.h" #include "RenderDeviceVk.h" -#include "TextureViewBase.h" +#include "TextureViewBase.hpp" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h index 6404be56..2140a43d 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h @@ -32,7 +32,7 @@ #include "TextureVk.h" #include "RenderDeviceVk.h" -#include "TextureBase.h" +#include "TextureBase.hpp" #include "TextureViewVkImpl.h" #include "VulkanUtilities/VulkanMemoryManager.h" #include "RenderDeviceVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/include/pch.h b/Graphics/GraphicsEngineVulkan/include/pch.h index 5b82c7a9..2c193f3e 100644 --- a/Graphics/GraphicsEngineVulkan/include/pch.h +++ b/Graphics/GraphicsEngineVulkan/include/pch.h @@ -74,5 +74,5 @@ template <> struct hash #include "Errors.h" #include "RefCntAutoPtr.h" #include "VulkanErrors.h" -#include "RenderDeviceBase.h" +#include "RenderDeviceBase.hpp" #include "ValidatedCast.h" diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 264eb168..8614c925 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -38,7 +38,7 @@ #include "CommandQueueVkImpl.h" #include "VulkanUtilities/VulkanInstance.h" #include "VulkanUtilities/VulkanPhysicalDevice.h" -#include "EngineFactoryBase.h" +#include "EngineFactoryBase.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 325deb5b..fb383f37 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -36,7 +36,7 @@ #include "SamplerVkImpl.h" #include "ShaderVkImpl.h" #include "PipelineLayout.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" #include "StringTools.h" #include "PipelineStateVkImpl.h" diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 171e138a..8c8a4460 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -28,7 +28,7 @@ #include "pch.h" #include "ShaderVariableVk.h" -#include "ShaderResourceVariableBase.h" +#include "ShaderResourceVariableBase.hpp" namespace Diligent { diff --git a/Graphics/HLSL2GLSLConverterLib/src/HLSL2GLSLConverterImpl.cpp b/Graphics/HLSL2GLSLConverterLib/src/HLSL2GLSLConverterImpl.cpp index 9e73aafe..d142aac5 100644 --- a/Graphics/HLSL2GLSLConverterLib/src/HLSL2GLSLConverterImpl.cpp +++ b/Graphics/HLSL2GLSLConverterLib/src/HLSL2GLSLConverterImpl.cpp @@ -358,7 +358,7 @@ #include #include "HLSL2GLSLConverterImpl.h" -#include "ShaderBase.h" +#include "ShaderBase.hpp" #include "DataBlobImpl.h" #include "StringDataBlobImpl.h" #include "StringTools.h" -- cgit v1.2.3