diff --git a/engine/api/gpuResource.h b/engine/api/gpuResource.h index d05b6cee..738e836f 100644 --- a/engine/api/gpuResource.h +++ b/engine/api/gpuResource.h @@ -256,6 +256,14 @@ struct GPUVendorPreset uint32_t rtCoresCount; }; +struct GPUFeature +{ + bool meshShading : 1 = false; + bool multiDrawIndirect : 1 = false; + bool tessellationSupported : 1 = false; + bool samplerAnisotropySupported : 1 = false; +}; + struct GPUSettings { uint64_t vram; @@ -268,16 +276,7 @@ struct GPUSettings WaveOpsSupportFlags waveOpsSupportFlags; GPUVendorPreset GpuVendorPreset; - uint8_t multiDrawIndirect : 1; - uint8_t indirectRootConstant : 1; - uint8_t builtinDrawID : 1; - uint8_t indirectCommandBuffer : 1; - uint8_t rovsSupported : 1; - uint8_t tessellationSupported : 1; - uint8_t geometryShaderSupported : 1; - uint8_t gpuBreadcrumbs : 1; - uint8_t hdrSupported : 1; - uint8_t samplerAnisotropySupported : 1; + GPUFeature feature; }; struct DrawArguments diff --git a/engine/api/vulkan/device.cpp b/engine/api/vulkan/device.cpp index 02a34a76..b0540866 100644 --- a/engine/api/vulkan/device.cpp +++ b/engine/api/vulkan/device.cpp @@ -51,6 +51,33 @@ std::unique_ptr Device::Create(const DeviceCreateInfo& createInfo) }; } + // verify feature support + { + const auto& requiredFeature = createInfo.enabledFeatures; + const auto& supportFeature = physicalDevice->getSettings().feature; + + if(requiredFeature.meshShading && !supportFeature.meshShading) + { + CM_LOG_ERR("Mesh Shading feature not supported!"); + APH_ASSERT(false); + } + if(requiredFeature.multiDrawIndirect && !supportFeature.multiDrawIndirect) + { + CM_LOG_ERR("Multi Draw Indrect not supported!"); + APH_ASSERT(false); + } + if(requiredFeature.tessellationSupported && !supportFeature.tessellationSupported) + { + CM_LOG_ERR("some gpu feature not supported!"); + APH_ASSERT(false); + } + if(requiredFeature.samplerAnisotropySupported && !supportFeature.samplerAnisotropySupported) + { + CM_LOG_ERR("some gpu feature not supported!"); + APH_ASSERT(false); + } + } + // Enable all physical device available features. VkPhysicalDeviceFeatures supportedFeatures = {}; vkGetPhysicalDeviceFeatures(physicalDevice->getHandle(), &supportedFeatures); @@ -114,21 +141,49 @@ std::unique_ptr Device::Create(const DeviceCreateInfo& createInfo) VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeature{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT, .pNext = &hostQueryResetFeature, - .taskShader = VK_TRUE, - .meshShader = VK_TRUE, + .taskShader = VK_FALSE, + .meshShader = VK_FALSE, + }; + + VkPhysicalDeviceMultiDrawFeaturesEXT multiDrawFeature{ + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT, + .pNext = &meshShaderFeature, + .multiDraw = VK_FALSE, }; - supportedFeatures2.pNext = &meshShaderFeature; + supportedFeatures2.pNext = &multiDrawFeature; supportedFeatures2.features = supportedFeatures; + std::vector exts; + { + const auto& feature = createInfo.enabledFeatures; + if(feature.meshShading) + { + meshShaderFeature.taskShader = VK_TRUE; + meshShaderFeature.meshShader = VK_TRUE; + exts.push_back(VK_EXT_MESH_SHADER_EXTENSION_NAME); + } + if(feature.multiDrawIndirect) + { + multiDrawFeature.multiDraw = VK_TRUE; + exts.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + } + + exts.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + exts.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + exts.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + exts.push_back(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + exts.push_back(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME); + } + // Create the Vulkan device. VkDeviceCreateInfo deviceCreateInfo{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &supportedFeatures2, .queueCreateInfoCount = static_cast(queueCreateInfos.size()), .pQueueCreateInfos = queueCreateInfos.data(), - .enabledExtensionCount = static_cast(createInfo.enabledExtensions.size()), - .ppEnabledExtensionNames = createInfo.enabledExtensions.data(), + .enabledExtensionCount = static_cast(exts.size()), + .ppEnabledExtensionNames = exts.data(), }; VkDevice handle = VK_NULL_HANDLE; diff --git a/engine/api/vulkan/device.h b/engine/api/vulkan/device.h index a2578bf9..9ae87dc6 100644 --- a/engine/api/vulkan/device.h +++ b/engine/api/vulkan/device.h @@ -36,7 +36,7 @@ using DeviceCreateFlags = uint32_t; struct DeviceCreateInfo { DeviceCreateFlags flags; - std::vector enabledExtensions; + GPUFeature enabledFeatures; PhysicalDevice* pPhysicalDevice = nullptr; Instance* pInstance = nullptr; }; diff --git a/engine/api/vulkan/physicalDevice.cpp b/engine/api/vulkan/physicalDevice.cpp index 3558eed5..a73974bc 100644 --- a/engine/api/vulkan/physicalDevice.cpp +++ b/engine/api/vulkan/physicalDevice.cpp @@ -80,44 +80,53 @@ PhysicalDevice::PhysicalDevice(HandleType handle) : ResourceHandle(handle) auto* gpuProperties2 = &m_properties2; auto* gpuSettings = &m_settings; auto* gpuFeatures = &m_features2; - gpuSettings->uniformBufferAlignment = - (uint32_t)gpuProperties2->properties.limits.minUniformBufferOffsetAlignment; - gpuSettings->uploadBufferTextureAlignment = - (uint32_t)gpuProperties2->properties.limits.optimalBufferCopyOffsetAlignment; - gpuSettings->uploadBufferTextureRowAlignment = - (uint32_t)gpuProperties2->properties.limits.optimalBufferCopyRowPitchAlignment; - gpuSettings->maxVertexInputBindings = gpuProperties2->properties.limits.maxVertexInputBindings; - gpuSettings->multiDrawIndirect = gpuFeatures->features.multiDrawIndirect; - gpuSettings->indirectRootConstant = false; - gpuSettings->builtinDrawID = true; - - gpuSettings->waveLaneCount = subgroupProperties.subgroupSize; - gpuSettings->waveOpsSupportFlags = WAVE_OPS_SUPPORT_FLAG_NONE; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_BASIC_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_VOTE_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_ARITHMETIC_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_BALLOT_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_SHUFFLE_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_SHUFFLE_RELATIVE_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_CLUSTERED_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_QUAD_BIT; - if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) - gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_PARTITIONED_BIT_NV; -#if VK_EXT_fragment_shader_interlock - gpuSettings->rovsSupported = (bool)fragmentShaderInterlockFeatures.fragmentShaderPixelInterlock; -#endif - gpuSettings->tessellationSupported = gpuFeatures->features.tessellationShader; - gpuSettings->geometryShaderSupported = gpuFeatures->features.geometryShader; - gpuSettings->samplerAnisotropySupported = gpuFeatures->features.samplerAnisotropy; + { + gpuSettings->uniformBufferAlignment = + (uint32_t)gpuProperties2->properties.limits.minUniformBufferOffsetAlignment; + gpuSettings->uploadBufferTextureAlignment = + (uint32_t)gpuProperties2->properties.limits.optimalBufferCopyOffsetAlignment; + gpuSettings->uploadBufferTextureRowAlignment = + (uint32_t)gpuProperties2->properties.limits.optimalBufferCopyRowPitchAlignment; + gpuSettings->maxVertexInputBindings = gpuProperties2->properties.limits.maxVertexInputBindings; + + gpuSettings->waveLaneCount = subgroupProperties.subgroupSize; + gpuSettings->waveOpsSupportFlags = WAVE_OPS_SUPPORT_FLAG_NONE; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_BASIC_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_VOTE_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_ARITHMETIC_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_BALLOT_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_SHUFFLE_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_SHUFFLE_RELATIVE_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_CLUSTERED_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_QUAD_BIT; + if(subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) + gpuSettings->waveOpsSupportFlags |= WAVE_OPS_SUPPORT_FLAG_PARTITIONED_BIT_NV; + } + + // feature support + { + gpuSettings->feature.multiDrawIndirect = gpuFeatures->features.multiDrawIndirect; + gpuSettings->feature.tessellationSupported = gpuFeatures->features.tessellationShader; + gpuSettings->feature.samplerAnisotropySupported = gpuFeatures->features.samplerAnisotropy; + + gpuSettings->feature.meshShading = false; + for(const auto& ext : m_supportedExtensions) + { + if(ext == VK_EXT_MESH_SHADER_EXTENSION_NAME) + { + gpuSettings->feature.meshShading = true; + } + } + } { char buffer[1024]; @@ -306,11 +315,7 @@ VkPipelineStageFlags utils::determinePipelineStageFlags(PhysicalDevice* pGPU, Vk { flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - if(gpuSupport->geometryShaderSupported) - { - flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; - } - if(gpuSupport->tessellationSupported) + if(gpuSupport->feature.tessellationSupported) { flags |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT; flags |= VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; diff --git a/engine/renderer/renderer.cpp b/engine/renderer/renderer.cpp index 72b7e6ec..3359ceaa 100644 --- a/engine/renderer/renderer.cpp +++ b/engine/renderer/renderer.cpp @@ -112,16 +112,16 @@ Renderer::Renderer(const RenderConfig& config) : m_config(config) // create device { - std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, - VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, VK_KHR_MAINTENANCE_4_EXTENSION_NAME, - VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_EXT_MESH_SHADER_EXTENSION_NAME, - }; - uint32_t gpuIdx = 0; DeviceCreateInfo createInfo{ - .enabledExtensions = std::move(deviceExtensions), // TODO select physical device + .enabledFeatures = + { + .meshShading = false, + .multiDrawIndirect = true, + .tessellationSupported = true, + .samplerAnisotropySupported = true, + }, .pPhysicalDevice = m_pInstance->getPhysicalDevices(gpuIdx), .pInstance = m_pInstance, };