Skip to content

Commit

Permalink
refine gpu feature requirement
Browse files Browse the repository at this point in the history
  • Loading branch information
K1ngst0m committed Jan 14, 2024
1 parent 48355a5 commit b284660
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 65 deletions.
19 changes: 9 additions & 10 deletions engine/api/gpuResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
65 changes: 60 additions & 5 deletions engine/api/vulkan/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ std::unique_ptr<Device> 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);
Expand Down Expand Up @@ -114,21 +141,49 @@ std::unique_ptr<Device> 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<const char*> 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<uint32_t>(queueCreateInfos.size()),
.pQueueCreateInfos = queueCreateInfos.data(),
.enabledExtensionCount = static_cast<uint32_t>(createInfo.enabledExtensions.size()),
.ppEnabledExtensionNames = createInfo.enabledExtensions.data(),
.enabledExtensionCount = static_cast<uint32_t>(exts.size()),
.ppEnabledExtensionNames = exts.data(),
};

VkDevice handle = VK_NULL_HANDLE;
Expand Down
2 changes: 1 addition & 1 deletion engine/api/vulkan/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ using DeviceCreateFlags = uint32_t;
struct DeviceCreateInfo
{
DeviceCreateFlags flags;
std::vector<const char*> enabledExtensions;
GPUFeature enabledFeatures;
PhysicalDevice* pPhysicalDevice = nullptr;
Instance* pInstance = nullptr;
};
Expand Down
89 changes: 47 additions & 42 deletions engine/api/vulkan/physicalDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 7 additions & 7 deletions engine/renderer/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,16 @@ Renderer::Renderer(const RenderConfig& config) : m_config(config)

// create device
{
std::vector<const char*> 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,
};
Expand Down

0 comments on commit b284660

Please sign in to comment.