From dc9a4e784c8bb97fbb16a01624c7b8f0544977a4 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 11 Aug 2020 22:48:23 +0300 Subject: Added mesh shader added mesh shader support to DX12 and Vulkan, added DXIL compiler for Shader Model 6.x --- .../include/DeviceContextVkImpl.hpp | 4 +++ .../include/PipelineStateVkImpl.hpp | 2 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 26 ++++++++++++++++++ .../include/VulkanUtilities/VulkanInstance.hpp | 2 ++ .../VulkanUtilities/VulkanPhysicalDevice.hpp | 24 ++++++++++++++--- .../src/DeviceContextVkImpl.cpp | 31 +++++++++++++++++++--- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 22 +++++++++++++-- .../src/GenerateMipsVkHelper.cpp | 2 +- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 16 ++++++----- .../src/PipelineStateVkImpl.cpp | 22 +++++++++------ .../src/RenderDeviceVkImpl.cpp | 4 +++ .../src/VulkanUtilities/VulkanInstance.cpp | 21 ++++++++++++++- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 31 +++++++++++++++++++--- 13 files changed, 179 insertions(+), 28 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index 83e2c077..4dd6ae1e 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -142,6 +142,10 @@ public: virtual void DILIGENT_CALL_TYPE DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; /// Implementation of IDeviceContext::DrawIndexedIndirect() in Vulkan backend. virtual void DILIGENT_CALL_TYPE DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContext::DrawMesh() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawMeshIndirect() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; /// Implementation of IDeviceContext::DispatchCompute() in Vulkan backend. virtual void DILIGENT_CALL_TYPE DispatchCompute (const DispatchComputeAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index aca69cac..01f37a76 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -156,7 +156,7 @@ private: VulkanUtilities::PipelineWrapper m_Pipeline; PipelineLayout m_PipelineLayout; - Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex; bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; }; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 1465024b..5e4f5062 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -138,6 +138,32 @@ public: vkCmdDrawIndexedIndirect(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride); } + __forceinline void DrawMesh(uint32_t TaskCount, uint32_t FirstTask) + { +#ifdef VK_NV_mesh_shader + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass (19.3)"); + VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound"); + + vkCmdDrawMeshTasksNV(m_VkCmdBuffer, TaskCount, FirstTask); +#else + UNSUPPORTED("DrawMesh is not supported in current Vulkan headers"); +#endif + } + + __forceinline void DrawMeshIndirect(VkBuffer Buffer, VkDeviceSize Offset, uint32_t DrawCount, uint32_t Stride) + { +#ifdef VK_NV_mesh_shader + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass (19.3)"); + VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound"); + + vkCmdDrawMeshTasksIndirectNV(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride); +#else + UNSUPPORTED("DrawMeshIndirect is not supported in current Vulkan headers"); +#endif + } + __forceinline void Dispatch(uint32_t GroupCountX, uint32_t GroupCountY, uint32_t GroupCountZ) { VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp index 3fcb736d..0ca092c6 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp @@ -63,6 +63,7 @@ public: // clang-format off bool IsLayerAvailable (const char* LayerName) const; bool IsExtensionAvailable(const char* ExtensionName)const; + bool IsExtensionEnabled (const char* ExtensionName)const; VkPhysicalDevice SelectPhysicalDevice()const; @@ -82,6 +83,7 @@ private: std::vector m_Layers; std::vector m_Extensions; + std::vector m_EnabledExtensions; std::vector m_PhysicalDevices; }; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index 24212950..17bc2e4a 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -29,13 +29,25 @@ #include #include -#include "VulkanHeaders.h" +#include "VulkanInstance.hpp" namespace VulkanUtilities { class VulkanPhysicalDevice { +public: + struct ExtensionFeatures + { +#ifdef VK_NV_mesh_shader + VkPhysicalDeviceMeshShaderFeaturesNV MeshShader; +#endif + }; + + struct ExtensionProperties + { + }; + public: // clang-format off VulkanPhysicalDevice (const VulkanPhysicalDevice&) = delete; @@ -44,7 +56,8 @@ public: VulkanPhysicalDevice& operator = (VulkanPhysicalDevice&&) = delete; // clang-format on - static std::unique_ptr Create(VkPhysicalDevice vkDevice); + static std::unique_ptr Create(VkPhysicalDevice vkDevice, + std::shared_ptr Instance); // clang-format off uint32_t FindQueueFamily (VkQueueFlags QueueFlags) const; @@ -59,15 +72,20 @@ public: const VkPhysicalDeviceProperties& GetProperties() const { return m_Properties; } const VkPhysicalDeviceFeatures& GetFeatures() const { return m_Features; } + const ExtensionProperties& GetExtProperties() const { return m_ExtProperties; } + const ExtensionFeatures& GetExtFeatures() const { return m_ExtFeatures; } VkFormatProperties GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const; private: - VulkanPhysicalDevice(VkPhysicalDevice vkDevice); + VulkanPhysicalDevice(VkPhysicalDevice vkDevice, + std::shared_ptr Instance); const VkPhysicalDevice m_VkDevice; VkPhysicalDeviceProperties m_Properties = {}; VkPhysicalDeviceFeatures m_Features = {}; VkPhysicalDeviceMemoryProperties m_MemoryProperties = {}; + ExtensionProperties m_ExtProperties = {}; + ExtensionFeatures m_ExtFeatures = {}; std::vector m_QueueFamilyProperties; std::vector m_SupportedExtensions; }; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index d61ddc97..a8ec8364 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -256,7 +256,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) // This is necessary because if the command list had been flushed // and the first PSO set on the command list was a compute pipeline, // the states would otherwise never be committed (since m_pPipelineState != nullptr) - CommitStates = OldPSODesc.IsComputePipeline; + CommitStates = OldPSODesc.IsComputePipeline(); // We also need to update scissor rect if ScissorEnable state was disabled in previous pipeline CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable; } @@ -264,7 +264,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) TDeviceContextBase::SetPipelineState(pPipelineStateVk, 0 /*Dummy*/); EnsureVkCmdBuffer(); - if (PSODesc.IsComputePipeline) + if (PSODesc.IsComputePipeline()) { auto vkPipeline = pPipelineStateVk->GetVkPipeline(); m_CommandBuffer.BindComputePipeline(vkPipeline); @@ -553,6 +553,31 @@ void DeviceContextVkImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& ++m_State.NumCommands; } +void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs) +{ + if (!DvpVerifyDrawMeshArguments(Attribs)) + return; + + PrepareForDraw(Attribs.Flags); + + m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0); + ++m_State.NumCommands; +} + +void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer)) + return; + + // We must prepare indirect draw attribs buffer first because state transitions must + // be performed outside of render pass, and PrepareForDraw commits render pass + BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode); + + PrepareForDraw(Attribs.Flags); + + m_CommandBuffer.DrawMeshIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0); + ++m_State.NumCommands; +} void DeviceContextVkImpl::PrepareForDispatchCompute() { @@ -1067,7 +1092,7 @@ void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U if (m_pPipelineState) { const auto& PSODesc = m_pPipelineState->GetDesc(); - if (!PSODesc.IsComputePipeline && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) + if (PSODesc.IsAnyGraphicsPipeline() && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) { VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects"); CommitScissorRects(); diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 8d72a0b5..58aea393 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -144,7 +144,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E reinterpret_cast(EngineCI.pVkAllocator)); auto vkDevice = Instance->SelectPhysicalDevice(); - auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice); + auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice, Instance); const auto& PhysicalDeviceFeatures = PhysicalDevice->GetFeatures(); // If an implementation exposes any queue family that supports graphics operations, @@ -155,7 +155,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E 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 + // 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); @@ -200,6 +200,24 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height }; + + // To enable some device extensions you must enable instance extension VK_KHR_get_physical_device_properties2 + // and add feature description to DeviceCreateInfo.pNext. + bool SupportsFeatures2 = Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + void** NextExt = const_cast(&DeviceCreateInfo.pNext); + + // Enable mesh shader extension. +#ifdef VK_NV_mesh_shader + VkPhysicalDeviceMeshShaderFeaturesNV MeshShaderFeats = PhysicalDevice->GetExtFeatures().MeshShader; + + if (SupportsFeatures2 && PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME)) + { + DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME); + *NextExt = &MeshShaderFeats; + NextExt = &MeshShaderFeats.pNext; + } +#endif + DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp index 7742cd63..be1bf51d 100644 --- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp +++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp @@ -157,7 +157,7 @@ std::array, 4> GenerateMipsVkHelper::CreatePSOs(TE PipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; - PSODesc.IsComputePipeline = true; + PSODesc.PipelineType = COMPUTE_PIPELINE; PSODesc.Name = name.c_str(); PSODesc.ComputePipeline.pCS = pCS; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 32a68780..8fa63070 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -46,12 +46,16 @@ static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE Shader switch (ShaderType) { // clang-format off - case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; - case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; - case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; - case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; + case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; + case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; + case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; + case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; +#ifdef VK_NV_mesh_shader + case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV; + case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV; +#endif // clang-format on default: UNEXPECTED("Unknown shader type"); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 99b27d2c..063978f9 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -173,6 +173,8 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2); m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders); m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders); + m_ResourceLayoutIndex.fill(-1); + for (Uint32 s = 0; s < m_NumShaders; ++s) { new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(LogicalDevice); @@ -228,12 +230,16 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun switch (ShaderType) { // clang-format off - case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break; - case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break; - case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break; - case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break; - case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; - case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break; + case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break; + case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break; + case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break; + case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break; + case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; + case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break; +#ifdef VK_NV_mesh_shader + case SHADER_TYPE_AMPLIFICATION: StageCI.stage = VK_SHADER_STAGE_TASK_BIT_NV; break; + case SHADER_TYPE_MESH: StageCI.stage = VK_SHADER_STAGE_MESH_BIT_NV; break; +#endif default: UNEXPECTED("Unknown shader type"); // clang-format on } @@ -269,7 +275,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun } // Create pipeline - if (m_Desc.IsComputePipeline) + if (m_Desc.IsComputePipeline()) { auto& ComputePipeline = m_Desc.ComputePipeline; @@ -642,7 +648,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } // Prepare descriptor sets, and also bind them if there are no dynamic descriptors VERIFY_EXPR(pDescrSetBindInfo != nullptr); - m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); + m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline(), ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools // are released at the end of the frame by DeviceContextVkImpl::FinishFrame(). } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 4e6049b0..66ea8716 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -156,6 +156,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* auto& Features = m_DeviceCaps.Features; const auto& vkDeviceFeatures = m_PhysicalDevice->GetFeatures(); + const auto& vkExtFeatures = m_PhysicalDevice->GetExtFeatures(); Features.SeparablePrograms = True; Features.IndirectRendering = True; @@ -179,6 +180,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* Features.PixelUAVWritesAndAtomics = vkDeviceFeatures.fragmentStoresAndAtomics != VK_FALSE; Features.TextureUAVExtendedFormats = vkDeviceFeatures.shaderStorageImageExtendedFormats != VK_FALSE; + // All devices that supports mesh shader also supports task shader, so it is not necessary to use two separate features. + Features.MeshShaders = vkExtFeatures.MeshShader.meshShader != VK_FALSE && vkExtFeatures.MeshShader.taskShader != VK_FALSE; + const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits; auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index aa6235f3..603da02a 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -27,6 +27,7 @@ #include #include +#include "VulkanUtilities/VulkanInstance.hpp" #if DILIGENT_USE_VOLK # define VOLK_IMPLEMENTATION @@ -34,7 +35,6 @@ #endif #include "VulkanErrors.hpp" -#include "VulkanUtilities/VulkanInstance.hpp" #include "VulkanUtilities/VulkanDebug.hpp" #if !DILIGENT_NO_GLSLANG @@ -64,6 +64,15 @@ bool VulkanInstance::IsExtensionAvailable(const char* ExtensionName) const return false; } +bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const +{ + for (const auto& Extension : m_EnabledExtensions) + if (strcmp(Extension, ExtensionName) == 0) + return true; + + return false; +} + std::shared_ptr VulkanInstance::Create(bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, @@ -138,6 +147,14 @@ VulkanInstance::VulkanInstance(bool EnableValidation, #endif }; + // This extension added to core in 1.1, but current version is 1.0 +#ifdef VK_KHR_get_physical_device_properties2 + if (IsExtensionAvailable(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + { + GlobalExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + } +#endif + if (ppGlobalExtensionNames != nullptr) { for (uint32_t ext = 0; ext < GlobalExtensionCount; ++ext) @@ -213,6 +230,8 @@ VulkanInstance::VulkanInstance(bool EnableValidation, volkLoadInstance(m_VkInstance); #endif + m_EnabledExtensions = std::move(GlobalExtensions); + // If requested, we enable the default validation layers for debugging if (m_DebugUtilsEnabled) { diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 22eee45e..f18d6872 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -33,13 +33,15 @@ namespace VulkanUtilities { -std::unique_ptr VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice) +std::unique_ptr VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice, + std::shared_ptr Instance) { - auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice}; + auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice, Instance}; return std::unique_ptr{PhysicalDevice}; } -VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) : +VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, + std::shared_ptr Instance) : m_VkDevice{vkDevice} { VERIFY_EXPR(m_VkDevice != VK_NULL_HANDLE); @@ -65,6 +67,29 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) : (void)res; VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size()); } + + if (Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + { + VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; + VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; + void** NextFeat = &Feats2.pNext; + //void** NextProp = &Props2.pNext; + + // Enable mesh shader extension. +#ifdef VK_NV_mesh_shader + if (IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME)) + { + *NextFeat = &m_ExtFeatures.MeshShader; + NextFeat = &m_ExtFeatures.MeshShader.pNext; + m_ExtFeatures.MeshShader.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV; + } +#endif + + // Initialize device extension features by current physical device features. + // Some flags may not be supported by hardware. + vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2); + vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2); + } } uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags) const -- cgit v1.2.3