From f551f6353eaf4efe9b7f26d48822b96ebb0706a0 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 4 Mar 2019 22:38:04 -0800 Subject: Updated D3D11, D3D12, and Vk EngineFactory headers & structures --- Graphics/GraphicsEngineVulkan/CMakeLists.txt | 4 +- .../include/DeviceContextVkImpl.h | 2 +- .../include/RenderDeviceVkImpl.h | 12 +- .../interface/EngineFactoryVk.h | 128 +++++++ .../interface/RenderDeviceFactoryVk.h | 128 ------- .../src/DeviceContextVkImpl.cpp | 20 +- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 372 +++++++++++++++++++++ .../src/RenderDeviceFactoryVk.cpp | 372 --------------------- .../src/RenderDeviceVkImpl.cpp | 52 +-- .../src/ShaderResourceLayoutVk.cpp | 2 +- .../GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp | 8 +- 11 files changed, 550 insertions(+), 550 deletions(-) create mode 100644 Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h delete mode 100644 Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h create mode 100644 Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp delete mode 100644 Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index 18887fea..be94ed10 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -51,10 +51,10 @@ set(INTERFACE interface/BufferViewVk.h interface/CommandQueueVk.h interface/DeviceContextVk.h + interface/EngineFactoryVk.h interface/FenceVk.h interface/PipelineStateVk.h interface/RenderDeviceVk.h - interface/RenderDeviceFactoryVk.h interface/SamplerVk.h interface/ShaderVk.h interface/ShaderResourceBindingVk.h @@ -71,6 +71,7 @@ set(SRC src/CommandQueueVkImpl.cpp src/DescriptorPoolManager.cpp src/DeviceContextVkImpl.cpp + src/EngineFactoryVk.cpp src/FenceVkImpl.cpp src/VulkanDynamicHeap.cpp src/FramebufferCache.cpp @@ -79,7 +80,6 @@ set(SRC src/PipelineStateVkImpl.cpp src/RenderDeviceVkImpl.cpp src/RenderPassCache.cpp - src/RenderDeviceFactoryVk.cpp src/SamplerVkImpl.cpp src/ShaderVkImpl.cpp src/ShaderResourceBindingVkImpl.cpp diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h index 84e8bfdd..09eaa1a5 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h @@ -62,7 +62,7 @@ public: DeviceContextVkImpl(IReferenceCounters* pRefCounters, class RenderDeviceVkImpl* pDevice, bool bIsDeferred, - const EngineVkAttribs& Attribs, + const EngineVkCreateInfo& EngineCI, Uint32 ContextId, Uint32 CommandQueueId, std::shared_ptr GenerateMipsHelper); diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h index c0e2847b..167949df 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h @@ -55,11 +55,11 @@ class RenderDeviceVkImpl final : public RenderDeviceNextGenBase, ICommandQueueVk>; - RenderDeviceVkImpl( IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - const EngineVkAttribs& CreationAttribs, - size_t CommandQueueCount, - ICommandQueueVk** pCmdQueues, + RenderDeviceVkImpl( IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + const EngineVkCreateInfo& EngineCI, + size_t CommandQueueCount, + ICommandQueueVk** pCmdQueues, std::shared_ptr Instance, std::unique_ptr PhysicalDevice, std::shared_ptr LogicalDevice, @@ -134,7 +134,7 @@ private: std::unique_ptr m_PhysicalDevice; std::shared_ptr m_LogicalVkDevice; - EngineVkAttribs m_EngineAttribs; + EngineVkCreateInfo m_EngineAttribs; FramebufferCache m_FramebufferCache; RenderPassCache m_RenderPassCache; diff --git a/Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h b/Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h new file mode 100644 index 00000000..861f5514 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h @@ -0,0 +1,128 @@ +/* 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 +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. +* +* 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 functions that initialize Direct3D12-based engine implementation + +#include + +#include "../../GraphicsEngine/interface/RenderDevice.h" +#include "../../GraphicsEngine/interface/DeviceContext.h" +#include "../../GraphicsEngine/interface/SwapChain.h" + +#if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS || (PLATFORM_WIN32 && !defined(_MSC_VER)) + + // https://gcc.gnu.org/wiki/Visibility +# define API_QUALIFIER __attribute__((visibility("default"))) + +#elif PLATFORM_WIN32 + +# define API_QUALIFIER + +#else +# error Unsupported platform +#endif + +namespace Diligent +{ + +class IEngineFactoryVk +{ +public: + virtual void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, + IRenderDevice **ppDevice, + IDeviceContext **ppContexts, + Uint32 NumDeferredContexts) = 0; + + //virtual void AttachToVulkanDevice(void *pVkNativeDevice, + // class ICommandQueueVk *pCommandQueue, + // const EngineVkCreateInfo& EngineCI, + // IRenderDevice **ppDevice, + // IDeviceContext **ppContexts, + // Uint32 NumDeferredContexts) = 0; + + virtual void CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain) = 0; + +}; + + +#if ENGINE_DLL && PLATFORM_WIN32 && defined(_MSC_VER) + +# define EXPLICITLY_LOAD_ENGINE_VK_DLL 1 + + typedef IEngineFactoryVk* (*GetEngineFactoryVkType)(); + + static bool LoadGraphicsEngineVk(GetEngineFactoryVkType& GetFactoryFunc) + { + GetFactoryFunc = nullptr; + std::string LibName = "GraphicsEngineVk_"; + +# if _WIN64 + LibName += "64"; +# else + LibName += "32"; +# endif + +# ifdef _DEBUG + LibName += "d"; +# else + LibName += "r"; +# endif + + LibName += ".dll"; + auto hModule = LoadLibraryA(LibName.c_str()); + if (hModule == NULL) + { + std::stringstream ss; + ss << "Failed to load " << LibName << " library.\n"; + OutputDebugStringA(ss.str().c_str()); + return false; + } + + GetFactoryFunc = reinterpret_cast(GetProcAddress(hModule, "GetEngineFactoryVk")); + if (GetFactoryFunc == NULL) + { + std::stringstream ss; + ss << "Failed to load GetEngineFactoryVk() from " << LibName << " library.\n"; + OutputDebugStringA(ss.str().c_str()); + FreeLibrary(hModule); + return false; + } + + return true; + } + +#else + + API_QUALIFIER + IEngineFactoryVk* GetEngineFactoryVk(); + +#endif + +} diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h deleted file mode 100644 index b5de2664..00000000 --- a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h +++ /dev/null @@ -1,128 +0,0 @@ -/* 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 -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. -* -* 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 functions that initialize Direct3D12-based engine implementation - -#include - -#include "../../GraphicsEngine/interface/RenderDevice.h" -#include "../../GraphicsEngine/interface/DeviceContext.h" -#include "../../GraphicsEngine/interface/SwapChain.h" - -#if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS || (PLATFORM_WIN32 && !defined(_MSC_VER)) - - // https://gcc.gnu.org/wiki/Visibility -# define API_QUALIFIER __attribute__((visibility("default"))) - -#elif PLATFORM_WIN32 - -# define API_QUALIFIER - -#else -# error Unsupported platform -#endif - -namespace Diligent -{ - -class IEngineFactoryVk -{ -public: - virtual void CreateDeviceAndContextsVk(const EngineVkAttribs& CreationAttribs, - IRenderDevice **ppDevice, - IDeviceContext **ppContexts, - Uint32 NumDeferredContexts) = 0; - - //virtual void AttachToVulkanDevice(void *pVkNativeDevice, - // class ICommandQueueVk *pCommandQueue, - // const EngineVkAttribs& EngineAttribs, - // IRenderDevice **ppDevice, - // IDeviceContext **ppContexts, - // Uint32 NumDeferredContexts) = 0; - - virtual void CreateSwapChainVk(IRenderDevice *pDevice, - IDeviceContext *pImmediateContext, - const SwapChainDesc& SwapChainDesc, - void* pNativeWndHandle, - ISwapChain **ppSwapChain) = 0; - -}; - - -#if ENGINE_DLL && PLATFORM_WIN32 && defined(_MSC_VER) - -# define EXPLICITLY_LOAD_ENGINE_VK_DLL 1 - - typedef IEngineFactoryVk* (*GetEngineFactoryVkType)(); - - static bool LoadGraphicsEngineVk(GetEngineFactoryVkType &GetFactoryFunc) - { - GetFactoryFunc = nullptr; - std::string LibName = "GraphicsEngineVk_"; - -# if _WIN64 - LibName += "64"; -# else - LibName += "32"; -# endif - -# ifdef _DEBUG - LibName += "d"; -# else - LibName += "r"; -# endif - - LibName += ".dll"; - auto hModule = LoadLibraryA(LibName.c_str()); - if (hModule == NULL) - { - std::stringstream ss; - ss << "Failed to load " << LibName << " library.\n"; - OutputDebugStringA(ss.str().c_str()); - return false; - } - - GetFactoryFunc = reinterpret_cast(GetProcAddress(hModule, "GetEngineFactoryVk")); - if (GetFactoryFunc == NULL) - { - std::stringstream ss; - ss << "Failed to load GetEngineFactoryVk() from " << LibName << " library.\n"; - OutputDebugStringA(ss.str().c_str()); - FreeLibrary(hModule); - return false; - } - - return true; - } - -#else - - API_QUALIFIER - IEngineFactoryVk* GetEngineFactoryVk(); - -#endif - -} diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 0200476d..daabca38 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -45,20 +45,20 @@ namespace Diligent return ss.str(); } - DeviceContextVkImpl::DeviceContextVkImpl( IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDeviceVkImpl, - bool bIsDeferred, - const EngineVkAttribs& Attribs, - Uint32 ContextId, - Uint32 CommandQueueId, - std::shared_ptr GenerateMipsHelper) : + DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVkImpl, + bool bIsDeferred, + const EngineVkCreateInfo& EngineCI, + Uint32 ContextId, + Uint32 CommandQueueId, + std::shared_ptr GenerateMipsHelper) : TDeviceContextBase { pRefCounters, pDeviceVkImpl, ContextId, CommandQueueId, - bIsDeferred ? std::numeric_limits::max() : Attribs.NumCommandsToFlushCmdBuffer, + bIsDeferred ? std::numeric_limits::max() : EngineCI.NumCommandsToFlushCmdBuffer, bIsDeferred }, m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() }, @@ -76,13 +76,13 @@ namespace Diligent { *pDeviceVkImpl, GetContextObjectName("Upload heap", bIsDeferred, ContextId), - Attribs.UploadHeapPageSize + EngineCI.UploadHeapPageSize }, m_DynamicHeap { pDeviceVkImpl->GetDynamicMemoryManager(), GetContextObjectName("Dynamic heap", bIsDeferred, ContextId), - Attribs.DynamicHeapPageSize + EngineCI.DynamicHeapPageSize }, m_DynamicDescrSetAllocator { diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp new file mode 100644 index 00000000..acb6265a --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -0,0 +1,372 @@ +/* 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * 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. + */ + +/// \file +/// Routines that initialize Vulkan-based engine implementation + +#include "pch.h" +#include +#include "EngineFactoryVk.h" +#include "RenderDeviceVkImpl.h" +#include "DeviceContextVkImpl.h" +#include "SwapChainVkImpl.h" +#include "EngineMemory.h" +#include "CommandQueueVkImpl.h" +#include "VulkanUtilities/VulkanInstance.h" +#include "VulkanUtilities/VulkanPhysicalDevice.h" + +namespace Diligent +{ + +/// Engine factory for Vk implementation +class EngineFactoryVkImpl : public IEngineFactoryVk +{ +public: + static EngineFactoryVkImpl* GetInstance() + { + static EngineFactoryVkImpl TheFactory; + return &TheFactory; + } + + void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts)override final; + + void AttachToVulkanDevice(std::shared_ptr Instance, + std::unique_ptr PhysicalDevice, + std::shared_ptr LogicalDevice, + size_t CommandQueueCount, + ICommandQueueVk** ppCommandQueues, + const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts);//override final; + + void CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain)override final; +}; + +/// Creates render device and device contexts for Vulkan backend + +/// \param [in] EngineCI - Engine creation attributes. +/// \param [out] ppDevice - Address of the memory location where pointer to +/// the created device will be written +/// \param [out] ppContexts - Address of the memory location where pointers to +/// the contexts will be written. The new immediate +/// context goes at position 0. If NumDeferredContexts > 0, +/// pointers to the deferred contexts are written afterwards. +/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number +/// of deferred contexts is requested, pointers to the +/// contexts are written to ppContexts array starting +/// at position 1 +void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) +{ + VERIFY( ppDevice && ppContexts, "Null pointer provided" ); + if( !ppDevice || !ppContexts ) + return; + +#if 0 + for (Uint32 Type = Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < Vk_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type) + { + auto CPUHeapAllocSize = EngineCI.CPUDescriptorHeapAllocationSize[Type]; + Uint32 MaxSize = 1 << 20; + if (CPUHeapAllocSize > 1 << 20) + { + LOG_ERROR("CPU Heap allocation size is too large (", CPUHeapAllocSize, "). Max allowed size is ", MaxSize); + return; + } + + if ((CPUHeapAllocSize % 16) != 0) + { + LOG_ERROR("CPU Heap allocation size (", CPUHeapAllocSize, ") is expected to be multiple of 16"); + return; + } + } +#endif + + SetRawAllocator(EngineCI.pRawMemAllocator); + + *ppDevice = nullptr; + memset(ppContexts, 0, sizeof(*ppContexts) * (1 + NumDeferredContexts)); + + try + { + auto Instance = VulkanUtilities::VulkanInstance::Create( + EngineCI.EnableValidation, + EngineCI.GlobalExtensionCount, + EngineCI.ppGlobalExtensionNames, + reinterpret_cast(EngineCI.pVkAllocator)); + + auto vkDevice = Instance->SelectPhysicalDevice(); + auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice); + + // If an implementation exposes any queue family that supports graphics operations, + // at least one queue family of at least one physical device exposed by the implementation + // must support both graphics and compute operations. + + VkDeviceQueueCreateInfo QueueInfo{}; + QueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + QueueInfo.flags = 0; // reserved for future use + // All commands that are allowed on a queue that supports transfer operations are also allowed on a + // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family + // include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT + // capability separately for that queue family is optional (4.1). + QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); + QueueInfo.queueCount = 1; + const float defaultQueuePriority = 1.0f; // Ask for highest priority for our queue. (range [0,1]) + QueueInfo.pQueuePriorities = &defaultQueuePriority; + + VkDeviceCreateInfo DeviceCreateInfo = {}; + DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + DeviceCreateInfo.flags = 0; // Reserved for future use + // https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#extended-functionality-device-layer-deprecation + DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored. + DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored + DeviceCreateInfo.queueCreateInfoCount = 1; + DeviceCreateInfo.pQueueCreateInfos = &QueueInfo; + VkPhysicalDeviceFeatures DeviceFeatures = {}; + DeviceFeatures.depthBiasClamp = EngineCI.EnabledFeatures.depthBiasClamp ? VK_TRUE : VK_FALSE; + DeviceFeatures.fillModeNonSolid = EngineCI.EnabledFeatures.fillModeNonSolid ? VK_TRUE : VK_FALSE; + DeviceFeatures.depthClamp = EngineCI.EnabledFeatures.depthClamp ? VK_TRUE : VK_FALSE; + DeviceFeatures.independentBlend = EngineCI.EnabledFeatures.independentBlend ? VK_TRUE : VK_FALSE; + DeviceFeatures.samplerAnisotropy = EngineCI.EnabledFeatures.samplerAnisotropy ? VK_TRUE : VK_FALSE; + DeviceFeatures.geometryShader = EngineCI.EnabledFeatures.geometryShader ? VK_TRUE : VK_FALSE; + DeviceFeatures.tessellationShader = EngineCI.EnabledFeatures.tessellationShader ? VK_TRUE : VK_FALSE; + DeviceFeatures.dualSrcBlend = EngineCI.EnabledFeatures.dualSrcBlend ? VK_TRUE : VK_FALSE; + DeviceFeatures.multiViewport = EngineCI.EnabledFeatures.multiViewport ? VK_TRUE : VK_FALSE; + DeviceFeatures.imageCubeArray = EngineCI.EnabledFeatures.imageCubeArray ? VK_TRUE : VK_FALSE; + DeviceFeatures.textureCompressionBC = EngineCI.EnabledFeatures.textureCompressionBC ? VK_TRUE : VK_FALSE; + DeviceFeatures.vertexPipelineStoresAndAtomics = EngineCI.EnabledFeatures.vertexPipelineStoresAndAtomics ? VK_TRUE : VK_FALSE; + DeviceFeatures.fragmentStoresAndAtomics = EngineCI.EnabledFeatures.fragmentStoresAndAtomics ? VK_TRUE : VK_FALSE; + DeviceFeatures.shaderStorageImageExtendedFormats = EngineCI.EnabledFeatures.shaderStorageImageExtendedFormats ? VK_TRUE : VK_FALSE; + DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains + // boolean indicators of all the features to be enabled. + + std::vector DeviceExtensions = + { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height + }; + DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); + DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); + + auto vkAllocator = Instance->GetVkAllocator(); + auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle(); + auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator); + + RefCntAutoPtr pCmdQueueVk; + auto &RawMemAllocator = GetRawAllocator(); + pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex); + + std::array CommandQueues = {{pCmdQueueVk}}; + AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), EngineCI, ppDevice, ppContexts, NumDeferredContexts); + + FenceDesc Desc; + Desc.Name = "Command queue fence"; + // Render device owns command queue that in turn owns the fence, so it is an internal device object + bool IsDeviceInternal = true; + auto* pRenderDeviceVk = ValidatedCast(*ppDevice); + RefCntAutoPtr pFenceVk( NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal) ); + pCmdQueueVk->SetFence(std::move(pFenceVk)); + } + catch(std::runtime_error& ) + { + return; + } +} + +/// Attaches to existing Vulkan device + +/// \param [in] Instance - shared pointer to a VulkanUtilities::VulkanInstance object +/// \param [in] PhysicalDevice - pointer to the object representing physical device +/// \param [in] LogicalDevice - shared pointer to a VulkanUtilities::VulkanLogicalDevice object +/// \param [in] pCommandQueue - pointer to the implementation of command queue +/// \param [in] EngineCI - Engine creation attributes. +/// \param [out] ppDevice - Address of the memory location where pointer to +/// the created device will be written +/// \param [out] ppContexts - Address of the memory location where pointers to +/// the contexts will be written. Pointer to the immediate +/// context goes at position 0. If NumDeferredContexts > 0, +/// pointers to the deferred contexts go afterwards. +/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number +/// of deferred contexts is requested, pointers to the +/// contexts are written to ppContexts array starting +/// at position 1 +void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr Instance, + std::unique_ptr PhysicalDevice, + std::shared_ptr LogicalDevice, + size_t CommandQueueCount, + ICommandQueueVk** ppCommandQueues, + const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) +{ + VERIFY( ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" ); + if(!LogicalDevice || !ppCommandQueues || !ppDevice || !ppContexts ) + return; + + *ppDevice = nullptr; + memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); + + try + { + auto &RawMemAllocator = GetRawAllocator(); + RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineCI, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice, NumDeferredContexts ) ); + pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); + + std::shared_ptr GenerateMipsHelper(new GenerateMipsVkHelper(*pRenderDeviceVk)); + + RefCntAutoPtr pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineCI, 0, 0, GenerateMipsHelper) ); + // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will + // keep a weak reference to the context + pImmediateCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts) ); + pRenderDeviceVk->SetImmediateContext(pImmediateCtxVk); + + for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx) + { + RefCntAutoPtr pDeferredCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineCI, 1+DeferredCtx, 0, GenerateMipsHelper) ); + // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will + // keep a weak reference to the context + pDeferredCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts + 1 + DeferredCtx) ); + pRenderDeviceVk->SetDeferredContext(DeferredCtx, pDeferredCtxVk); + } + } + catch( const std::runtime_error & ) + { + if( *ppDevice ) + { + (*ppDevice)->Release(); + *ppDevice = nullptr; + } + for(Uint32 ctx=0; ctx < 1 + NumDeferredContexts; ++ctx) + { + if( ppContexts[ctx] != nullptr ) + { + ppContexts[ctx]->Release(); + ppContexts[ctx] = nullptr; + } + } + + LOG_ERROR( "Failed to create device and contexts" ); + } +} + + +/// Creates a swap chain for Direct3D12-based engine implementation + +/// \param [in] pDevice - Pointer to the render device +/// \param [in] pImmediateContext - Pointer to the immediate device context +/// \param [in] SCDesc - Swap chain description +/// \param [in] pNativeWndHandle - Platform-specific native handle of the window +/// the swap chain will be associated with: +/// * On Win32 platform, this should be window handle (HWND) +/// * On Universal Windows Platform, this should be reference to the +/// core window (Windows::UI::Core::CoreWindow) +/// +/// \param [out] ppSwapChain - Address of the memory location where pointer to the new +/// swap chain will be written +void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SCDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain) +{ + VERIFY( ppSwapChain, "Null pointer provided" ); + if( !ppSwapChain ) + return; + + *ppSwapChain = nullptr; + + try + { + auto *pDeviceVk = ValidatedCast( pDevice ); + auto *pDeviceContextVk = ValidatedCast(pImmediateContext); + auto &RawMemAllocator = GetRawAllocator(); + auto *pSwapChainVk = NEW_RC_OBJ(RawMemAllocator, "SwapChainVkImpl instance", SwapChainVkImpl)(SCDesc, pDeviceVk, pDeviceContextVk, pNativeWndHandle); + pSwapChainVk->QueryInterface( IID_SwapChain, reinterpret_cast(ppSwapChain) ); + + pDeviceContextVk->SetSwapChain(pSwapChainVk); + // Bind default render target + pDeviceContextVk->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); + // Set default viewport + pDeviceContextVk->SetViewports( 1, nullptr, 0, 0 ); + + auto NumDeferredCtx = pDeviceVk->GetNumDeferredContexts(); + for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) + { + if (auto pDeferredCtx = pDeviceVk->GetDeferredContext(ctx)) + { + auto *pDeferredCtxVk = pDeferredCtx.RawPtr(); + pDeferredCtxVk->SetSwapChain(pSwapChainVk); + // We cannot bind default render target here because + // there is no guarantee that deferred context will be used + // in this frame. It is an error to bind + // RTV of an inactive buffer in the swap chain + } + } + } + catch( const std::runtime_error & ) + { + if( *ppSwapChain ) + { + (*ppSwapChain)->Release(); + *ppSwapChain = nullptr; + } + + LOG_ERROR( "Failed to create the swap chain" ); + } +} + + +#ifdef DOXYGEN +/// Loads Direct3D12-based engine implementation and exports factory functions +/// \param [out] GetFactoryFunc - Pointer to the function that returns factory for Vk engine implementation. +/// See EngineFactoryVkImpl. +/// \remarks Depending on the configuration and platform, the function loads different dll: +/// Platform\\Configuration | Debug | Release +/// --------------------------|-------------------------------|---------------------------- +/// x86 | GraphicsEngineVk_32d.dll | GraphicsEngineVk_32r.dll +/// x64 | GraphicsEngineVk_64d.dll | GraphicsEngineVk_64r.dll +/// +void LoadGraphicsEngineVk(GetEngineFactoryVkType &GetFactoryFunc) +{ + // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO + #error This function must never be compiled; +} +#endif + +API_QUALIFIER +IEngineFactoryVk* GetEngineFactoryVk() +{ + return EngineFactoryVkImpl::GetInstance(); +} + +} diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp deleted file mode 100644 index a4ab8ae3..00000000 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* 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 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * 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. - */ - -/// \file -/// Routines that initialize Vulkan-based engine implementation - -#include "pch.h" -#include -#include "RenderDeviceFactoryVk.h" -#include "RenderDeviceVkImpl.h" -#include "DeviceContextVkImpl.h" -#include "SwapChainVkImpl.h" -#include "EngineMemory.h" -#include "CommandQueueVkImpl.h" -#include "VulkanUtilities/VulkanInstance.h" -#include "VulkanUtilities/VulkanPhysicalDevice.h" - -namespace Diligent -{ - -/// Engine factory for Vk implementation -class EngineFactoryVkImpl : public IEngineFactoryVk -{ -public: - static EngineFactoryVkImpl* GetInstance() - { - static EngineFactoryVkImpl TheFactory; - return &TheFactory; - } - - void CreateDeviceAndContextsVk( const EngineVkAttribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts)override final; - - void AttachToVulkanDevice(std::shared_ptr Instance, - std::unique_ptr PhysicalDevice, - std::shared_ptr LogicalDevice, - size_t CommandQueueCount, - ICommandQueueVk** ppCommandQueues, - const EngineVkAttribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts);//override final; - - void CreateSwapChainVk( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SwapChainDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain )override final; -}; - -/// Creates render device and device contexts for Vulkan backend - -/// \param [in] CreationAttribs - Engine creation attributes. -/// \param [out] ppDevice - Address of the memory location where pointer to -/// the created device will be written -/// \param [out] ppContexts - Address of the memory location where pointers to -/// the contexts will be written. The new immediate -/// context goes at position 0. If NumDeferredContexts > 0, -/// pointers to the deferred contexts are written afterwards. -/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number -/// of deferred contexts is requested, pointers to the -/// contexts are written to ppContexts array starting -/// at position 1 -void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) -{ - VERIFY( ppDevice && ppContexts, "Null pointer provided" ); - if( !ppDevice || !ppContexts ) - return; - -#if 0 - for (Uint32 Type = Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < Vk_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type) - { - auto CPUHeapAllocSize = CreationAttribs.CPUDescriptorHeapAllocationSize[Type]; - Uint32 MaxSize = 1 << 20; - if (CPUHeapAllocSize > 1 << 20) - { - LOG_ERROR("CPU Heap allocation size is too large (", CPUHeapAllocSize, "). Max allowed size is ", MaxSize); - return; - } - - if ((CPUHeapAllocSize % 16) != 0) - { - LOG_ERROR("CPU Heap allocation size (", CPUHeapAllocSize, ") is expected to be multiple of 16"); - return; - } - } -#endif - - SetRawAllocator(CreationAttribs.pRawMemAllocator); - - *ppDevice = nullptr; - memset(ppContexts, 0, sizeof(*ppContexts) * (1 + NumDeferredContexts)); - - try - { - auto Instance = VulkanUtilities::VulkanInstance::Create( - CreationAttribs.EnableValidation, - CreationAttribs.GlobalExtensionCount, - CreationAttribs.ppGlobalExtensionNames, - reinterpret_cast(CreationAttribs.pVkAllocator)); - - auto vkDevice = Instance->SelectPhysicalDevice(); - auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice); - - // If an implementation exposes any queue family that supports graphics operations, - // at least one queue family of at least one physical device exposed by the implementation - // must support both graphics and compute operations. - - VkDeviceQueueCreateInfo QueueInfo{}; - QueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - QueueInfo.flags = 0; // reserved for future use - // All commands that are allowed on a queue that supports transfer operations are also allowed on a - // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family - // include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT - // capability separately for that queue family is optional (4.1). - QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); - QueueInfo.queueCount = 1; - const float defaultQueuePriority = 1.0f; // Ask for highest priority for our queue. (range [0,1]) - QueueInfo.pQueuePriorities = &defaultQueuePriority; - - VkDeviceCreateInfo DeviceCreateInfo = {}; - DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - DeviceCreateInfo.flags = 0; // Reserved for future use - // https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#extended-functionality-device-layer-deprecation - DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored. - DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored - DeviceCreateInfo.queueCreateInfoCount = 1; - DeviceCreateInfo.pQueueCreateInfos = &QueueInfo; - VkPhysicalDeviceFeatures DeviceFeatures = {}; - DeviceFeatures.depthBiasClamp = CreationAttribs.EnabledFeatures.depthBiasClamp ? VK_TRUE : VK_FALSE; - DeviceFeatures.fillModeNonSolid = CreationAttribs.EnabledFeatures.fillModeNonSolid ? VK_TRUE : VK_FALSE; - DeviceFeatures.depthClamp = CreationAttribs.EnabledFeatures.depthClamp ? VK_TRUE : VK_FALSE; - DeviceFeatures.independentBlend = CreationAttribs.EnabledFeatures.independentBlend ? VK_TRUE : VK_FALSE; - DeviceFeatures.samplerAnisotropy = CreationAttribs.EnabledFeatures.samplerAnisotropy ? VK_TRUE : VK_FALSE; - DeviceFeatures.geometryShader = CreationAttribs.EnabledFeatures.geometryShader ? VK_TRUE : VK_FALSE; - DeviceFeatures.tessellationShader = CreationAttribs.EnabledFeatures.tessellationShader ? VK_TRUE : VK_FALSE; - DeviceFeatures.dualSrcBlend = CreationAttribs.EnabledFeatures.dualSrcBlend ? VK_TRUE : VK_FALSE; - DeviceFeatures.multiViewport = CreationAttribs.EnabledFeatures.multiViewport ? VK_TRUE : VK_FALSE; - DeviceFeatures.imageCubeArray = CreationAttribs.EnabledFeatures.imageCubeArray ? VK_TRUE : VK_FALSE; - DeviceFeatures.textureCompressionBC = CreationAttribs.EnabledFeatures.textureCompressionBC ? VK_TRUE : VK_FALSE; - DeviceFeatures.vertexPipelineStoresAndAtomics = CreationAttribs.EnabledFeatures.vertexPipelineStoresAndAtomics ? VK_TRUE : VK_FALSE; - DeviceFeatures.fragmentStoresAndAtomics = CreationAttribs.EnabledFeatures.fragmentStoresAndAtomics ? VK_TRUE : VK_FALSE; - DeviceFeatures.shaderStorageImageExtendedFormats = CreationAttribs.EnabledFeatures.shaderStorageImageExtendedFormats ? VK_TRUE : VK_FALSE; - DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains - // boolean indicators of all the features to be enabled. - - std::vector DeviceExtensions = - { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height - }; - DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); - DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); - - auto vkAllocator = Instance->GetVkAllocator(); - auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle(); - auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator); - - RefCntAutoPtr pCmdQueueVk; - auto &RawMemAllocator = GetRawAllocator(); - pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex); - - std::array CommandQueues = {{pCmdQueueVk}}; - AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), CreationAttribs, ppDevice, ppContexts, NumDeferredContexts); - - FenceDesc Desc; - Desc.Name = "Command queue fence"; - // Render device owns command queue that in turn owns the fence, so it is an internal device object - bool IsDeviceInternal = true; - auto* pRenderDeviceVk = ValidatedCast(*ppDevice); - RefCntAutoPtr pFenceVk( NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal) ); - pCmdQueueVk->SetFence(std::move(pFenceVk)); - } - catch(std::runtime_error& ) - { - return; - } -} - -/// Attaches to existing Vulkan device - -/// \param [in] Instance - shared pointer to a VulkanUtilities::VulkanInstance object -/// \param [in] PhysicalDevice - pointer to the object representing physical device -/// \param [in] LogicalDevice - shared pointer to a VulkanUtilities::VulkanLogicalDevice object -/// \param [in] pCommandQueue - pointer to the implementation of command queue -/// \param [in] EngineAttribs - Engine creation attributes. -/// \param [out] ppDevice - Address of the memory location where pointer to -/// the created device will be written -/// \param [out] ppContexts - Address of the memory location where pointers to -/// the contexts will be written. Pointer to the immediate -/// context goes at position 0. If NumDeferredContexts > 0, -/// pointers to the deferred contexts go afterwards. -/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number -/// of deferred contexts is requested, pointers to the -/// contexts are written to ppContexts array starting -/// at position 1 -void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr Instance, - std::unique_ptr PhysicalDevice, - std::shared_ptr LogicalDevice, - size_t CommandQueueCount, - ICommandQueueVk** ppCommandQueues, - const EngineVkAttribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) -{ - VERIFY( ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" ); - if(!LogicalDevice || !ppCommandQueues || !ppDevice || !ppContexts ) - return; - - *ppDevice = nullptr; - memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); - - try - { - auto &RawMemAllocator = GetRawAllocator(); - RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineAttribs, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice, NumDeferredContexts ) ); - pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); - - std::shared_ptr GenerateMipsHelper(new GenerateMipsVkHelper(*pRenderDeviceVk)); - - RefCntAutoPtr pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineAttribs, 0, 0, GenerateMipsHelper) ); - // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will - // keep a weak reference to the context - pImmediateCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts) ); - pRenderDeviceVk->SetImmediateContext(pImmediateCtxVk); - - for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx) - { - RefCntAutoPtr pDeferredCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineAttribs, 1+DeferredCtx, 0, GenerateMipsHelper) ); - // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will - // keep a weak reference to the context - pDeferredCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts + 1 + DeferredCtx) ); - pRenderDeviceVk->SetDeferredContext(DeferredCtx, pDeferredCtxVk); - } - } - catch( const std::runtime_error & ) - { - if( *ppDevice ) - { - (*ppDevice)->Release(); - *ppDevice = nullptr; - } - for(Uint32 ctx=0; ctx < 1 + NumDeferredContexts; ++ctx) - { - if( ppContexts[ctx] != nullptr ) - { - ppContexts[ctx]->Release(); - ppContexts[ctx] = nullptr; - } - } - - LOG_ERROR( "Failed to create device and contexts" ); - } -} - - -/// Creates a swap chain for Direct3D12-based engine implementation - -/// \param [in] pDevice - Pointer to the render device -/// \param [in] pImmediateContext - Pointer to the immediate device context -/// \param [in] SCDesc - Swap chain description -/// \param [in] pNativeWndHandle - Platform-specific native handle of the window -/// the swap chain will be associated with: -/// * On Win32 platform, this should be window handle (HWND) -/// * On Universal Windows Platform, this should be reference to the -/// core window (Windows::UI::Core::CoreWindow) -/// -/// \param [out] ppSwapChain - Address of the memory location where pointer to the new -/// swap chain will be written -void EngineFactoryVkImpl::CreateSwapChainVk( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SCDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain ) -{ - VERIFY( ppSwapChain, "Null pointer provided" ); - if( !ppSwapChain ) - return; - - *ppSwapChain = nullptr; - - try - { - auto *pDeviceVk = ValidatedCast( pDevice ); - auto *pDeviceContextVk = ValidatedCast(pImmediateContext); - auto &RawMemAllocator = GetRawAllocator(); - auto *pSwapChainVk = NEW_RC_OBJ(RawMemAllocator, "SwapChainVkImpl instance", SwapChainVkImpl)(SCDesc, pDeviceVk, pDeviceContextVk, pNativeWndHandle); - pSwapChainVk->QueryInterface( IID_SwapChain, reinterpret_cast(ppSwapChain) ); - - pDeviceContextVk->SetSwapChain(pSwapChainVk); - // Bind default render target - pDeviceContextVk->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); - // Set default viewport - pDeviceContextVk->SetViewports( 1, nullptr, 0, 0 ); - - auto NumDeferredCtx = pDeviceVk->GetNumDeferredContexts(); - for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) - { - if (auto pDeferredCtx = pDeviceVk->GetDeferredContext(ctx)) - { - auto *pDeferredCtxVk = pDeferredCtx.RawPtr(); - pDeferredCtxVk->SetSwapChain(pSwapChainVk); - // We cannot bind default render target here because - // there is no guarantee that deferred context will be used - // in this frame. It is an error to bind - // RTV of an inactive buffer in the swap chain - } - } - } - catch( const std::runtime_error & ) - { - if( *ppSwapChain ) - { - (*ppSwapChain)->Release(); - *ppSwapChain = nullptr; - } - - LOG_ERROR( "Failed to create the swap chain" ); - } -} - - -#ifdef DOXYGEN -/// Loads Direct3D12-based engine implementation and exports factory functions -/// \param [out] GetFactoryFunc - Pointer to the function that returns factory for Vk engine implementation. -/// See EngineFactoryVkImpl. -/// \remarks Depending on the configuration and platform, the function loads different dll: -/// Platform\\Configuration | Debug | Release -/// --------------------------|-------------------------------|---------------------------- -/// x86 | GraphicsEngineVk_32d.dll | GraphicsEngineVk_32r.dll -/// x64 | GraphicsEngineVk_64d.dll | GraphicsEngineVk_64r.dll -/// -void LoadGraphicsEngineVk(GetEngineFactoryVkType &GetFactoryFunc) -{ - // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO - #error This function must never be compiled; -} -#endif - -API_QUALIFIER -IEngineFactoryVk* GetEngineFactoryVk() -{ - return EngineFactoryVkImpl::GetInstance(); -} - -} diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 89ed5d01..a126a937 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -39,7 +39,7 @@ namespace Diligent RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator, - const EngineVkAttribs& CreationAttribs, + const EngineVkCreateInfo& EngineCI, size_t CommandQueueCount, ICommandQueueVk** CmdQueues, std::shared_ptr Instance, @@ -66,7 +66,7 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* m_VulkanInstance(Instance), m_PhysicalDevice(std::move(PhysicalDevice)), m_LogicalVkDevice(std::move(LogicalDevice)), - m_EngineAttribs(CreationAttribs), + m_EngineAttribs(EngineCI), m_FramebufferCache(*this), m_RenderPassCache(*this), m_DescriptorSetAllocator @@ -75,18 +75,18 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* "Main descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, CreationAttribs.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, CreationAttribs.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, CreationAttribs.MainDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, CreationAttribs.MainDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, CreationAttribs.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, CreationAttribs.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, }, - CreationAttribs.MainDescriptorPoolSize.MaxDescriptorSets, + EngineCI.MainDescriptorPoolSize.MaxDescriptorSets, true }, m_DynamicDescriptorPool @@ -95,27 +95,27 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* "Dynamic descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, CreationAttribs.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, CreationAttribs.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, CreationAttribs.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, CreationAttribs.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, CreationAttribs.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, CreationAttribs.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, }, - CreationAttribs.DynamicDescriptorPoolSize.MaxDescriptorSets, + EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets, false // Pools can only be reset }, m_TransientCmdPoolMgr(*this, "Transient command buffer pool manager", CmdQueues[0]->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT), - m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), CreationAttribs.DeviceLocalMemoryPageSize, CreationAttribs.HostVisibleMemoryPageSize, CreationAttribs.DeviceLocalMemoryReserveSize, CreationAttribs.HostVisibleMemoryReserveSize), + m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), EngineCI.DeviceLocalMemoryPageSize, EngineCI.HostVisibleMemoryPageSize, EngineCI.DeviceLocalMemoryReserveSize, EngineCI.HostVisibleMemoryReserveSize), m_DynamicMemoryManager { GetRawAllocator(), *this, - CreationAttribs.DynamicHeapSize, + EngineCI.DynamicHeapSize, ~Uint64{0} } { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 9f212fd4..e65aaa91 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -920,7 +920,7 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset); IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr(); if (!pObject) - LOG_ERROR_MESSAGE("No resource assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); auto DstOffset = DstRes.CacheOffset + ArrInd; IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp index 5fccdad8..57b55f15 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp @@ -165,22 +165,22 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast Block = TBase::AllocateMasterBlock(SizeInBytes, Alignment); if (!Block.IsValid()) { - LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms still no space is available. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms still no space is available. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } else { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } } else { if(SleepIterations == 0) { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. Increase the size of the heap buffer by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. Increase the size of the heap buffer by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } else { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } } } -- cgit v1.2.3