From 319218437b33d160ca4eb4e284bfb11e515540e7 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 15 Mar 2016 10:12:48 +1300 Subject: layers: validate capabilities against device features V2: squashed in feedback. V3: More careful about VkBool32 Signed-off-by: Chris Forbes --- demos/tri.c | 13 +++ layers/core_validation.cpp | 158 ++++++++++++++++++++++++++++++++++ layers/core_validation.h | 2 + layers/vk_validation_layer_details.md | 2 + 4 files changed, 175 insertions(+) diff --git a/demos/tri.c b/demos/tri.c index 9f3cfac6..aa0fbced 100644 --- a/demos/tri.c +++ b/demos/tri.c @@ -2068,6 +2068,14 @@ static void demo_init_vk(struct demo *demo) { demo->queue_props); assert(demo->queue_count >= 1); + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(demo->gpu, &features); + + if (!features.shaderClipDistance) { + ERR_EXIT("Required device feature `shaderClipDistance` not supported\n", + "GetPhysicalDeviceFeatures failure"); + } + // Graphics queue and MemMgr queue can be separate. // TODO: Add support for separate queues, including synchronization, // and appropriate tracking for QueueSubmit @@ -2084,6 +2092,10 @@ static void demo_init_device(struct demo *demo) { .queueCount = 1, .pQueuePriorities = queue_priorities}; + VkPhysicalDeviceFeatures features = { + .shaderClipDistance = VK_TRUE, + }; + VkDeviceCreateInfo device = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = NULL, @@ -2096,6 +2108,7 @@ static void demo_init_device(struct demo *demo) { : NULL), .enabledExtensionCount = demo->enabled_extension_count, .ppEnabledExtensionNames = (const char *const *)demo->extension_names, + .pEnabledFeatures = &features, }; err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device); diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index b6a81e30..b0cb2754 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2519,6 +2519,161 @@ static bool descriptor_type_match(layer_data *my_data, shader_module const *modu } } +static VkBool32 require_feature(layer_data *my_data, VkBool32 feature, char const *feature_name) { + if (!feature) { + if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, + /* dev */ 0, __LINE__, SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", + "Shader requires VkPhysicalDeviceFeatures::%s but is not " + "enabled on the device", + feature_name)) { + return false; + } + } + + return true; +} + +static VkBool32 validate_shader_capabilities(layer_data *my_data, VkDevice dev, shader_module const *src) +{ + VkBool32 pass = VK_TRUE; + + auto enabledFeatures = &my_data->physDevProperties.features; + + for (auto insn : *src) { + if (insn.opcode() == spv::OpCapability) { + switch (insn.word(1)) { + case spv::CapabilityMatrix: + case spv::CapabilityShader: + case spv::CapabilityInputAttachment: + case spv::CapabilitySampled1D: + case spv::CapabilityImage1D: + case spv::CapabilitySampledBuffer: + case spv::CapabilityImageBuffer: + case spv::CapabilityImageQuery: + case spv::CapabilityDerivativeControl: + // Always supported by a Vulkan 1.0 implementation -- no feature bits. + break; + + case spv::CapabilityGeometry: + pass &= require_feature(my_data, enabledFeatures->geometryShader, "geometryShader"); + break; + + case spv::CapabilityTessellation: + pass &= require_feature(my_data, enabledFeatures->tessellationShader, "tessellationShader"); + break; + + case spv::CapabilityFloat64: + pass &= require_feature(my_data, enabledFeatures->shaderFloat64, "shaderFloat64"); + break; + + case spv::CapabilityInt64: + pass &= require_feature(my_data, enabledFeatures->shaderInt64, "shaderInt64"); + break; + + case spv::CapabilityTessellationPointSize: + case spv::CapabilityGeometryPointSize: + pass &= require_feature(my_data, enabledFeatures->shaderTessellationAndGeometryPointSize, + "shaderTessellationAndGeometryPointSize"); + break; + + case spv::CapabilityImageGatherExtended: + pass &= require_feature(my_data, enabledFeatures->shaderImageGatherExtended, "shaderImageGatherExtended"); + break; + + case spv::CapabilityStorageImageMultisample: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample"); + break; + + case spv::CapabilityUniformBufferArrayDynamicIndexing: + pass &= require_feature(my_data, enabledFeatures->shaderUniformBufferArrayDynamicIndexing, + "shaderUniformBufferArrayDynamicIndexing"); + break; + + case spv::CapabilitySampledImageArrayDynamicIndexing: + pass &= require_feature(my_data, enabledFeatures->shaderSampledImageArrayDynamicIndexing, + "shaderSampledImageArrayDynamicIndexing"); + break; + + case spv::CapabilityStorageBufferArrayDynamicIndexing: + pass &= require_feature(my_data, enabledFeatures->shaderStorageBufferArrayDynamicIndexing, + "shaderStorageBufferArrayDynamicIndexing"); + break; + + case spv::CapabilityStorageImageArrayDynamicIndexing: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageArrayDynamicIndexing, + "shaderStorageImageArrayDynamicIndexing"); + break; + + case spv::CapabilityClipDistance: + pass &= require_feature(my_data, enabledFeatures->shaderClipDistance, "shaderClipDistance"); + break; + + case spv::CapabilityCullDistance: + pass &= require_feature(my_data, enabledFeatures->shaderCullDistance, "shaderCullDistance"); + break; + + case spv::CapabilityImageCubeArray: + pass &= require_feature(my_data, enabledFeatures->imageCubeArray, "imageCubeArray"); + break; + + case spv::CapabilitySampleRateShading: + pass &= require_feature(my_data, enabledFeatures->sampleRateShading, "sampleRateShading"); + break; + + case spv::CapabilitySparseResidency: + pass &= require_feature(my_data, enabledFeatures->shaderResourceResidency, "shaderResourceResidency"); + break; + + case spv::CapabilityMinLod: + pass &= require_feature(my_data, enabledFeatures->shaderResourceMinLod, "shaderResourceMinLod"); + break; + + case spv::CapabilitySampledCubeArray: + pass &= require_feature(my_data, enabledFeatures->imageCubeArray, "imageCubeArray"); + break; + + case spv::CapabilityImageMSArray: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageMultisample, "shaderStorageImageMultisample"); + break; + + case spv::CapabilityStorageImageExtendedFormats: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageExtendedFormats, + "shaderStorageImageExtendedFormats"); + break; + + case spv::CapabilityInterpolationFunction: + pass &= require_feature(my_data, enabledFeatures->sampleRateShading, "sampleRateShading"); + break; + + case spv::CapabilityStorageImageReadWithoutFormat: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageReadWithoutFormat, + "shaderStorageImageReadWithoutFormat"); + break; + + case spv::CapabilityStorageImageWriteWithoutFormat: + pass &= require_feature(my_data, enabledFeatures->shaderStorageImageWriteWithoutFormat, + "shaderStorageImageWriteWithoutFormat"); + break; + + case spv::CapabilityMultiViewport: + pass &= require_feature(my_data, enabledFeatures->multiViewport, "multiViewport"); + break; + + default: + if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, /* dev */0, + __LINE__, SHADER_CHECKER_BAD_CAPABILITY, "SC", + "Shader declares capability %u, not supported in Vulkan.", + insn.word(1))) + pass = VK_FALSE; + break; + } + } + } + + return pass; +} + + // Validate that the shaders used by the given pipeline // As a side effect this function also records the sets that are actually used by the pipeline static VkBool32 validate_pipeline_shaders(layer_data *my_data, VkDevice dev, PIPELINE_NODE *pPipeline) { @@ -2564,6 +2719,9 @@ static VkBool32 validate_pipeline_shaders(layer_data *my_data, VkDevice dev, PIP } } + /* validate shader capabilities against enabled device features */ + pass = validate_shader_capabilities(my_data, dev, module) && pass; + /* mark accessible ids */ std::unordered_set accessible_ids; mark_accessible_ids(module, entrypoints[stage_id], accessible_ids); diff --git a/layers/core_validation.h b/layers/core_validation.h index 8d8941f5..fea8ffde 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -404,6 +404,8 @@ typedef enum _SHADER_CHECKER_ERROR { SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, // Push constant range exists, but not accessible from stage SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, // Descriptor type does not match shader resource type SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, // Descriptor used by shader, but not accessible from stage + SHADER_CHECKER_FEATURE_NOT_ENABLED, // Shader uses capability requiring a feature not enabled on device + SHADER_CHECKER_BAD_CAPABILITY, // Shader uses capability not supported by Vulkan (OpenCL features) } SHADER_CHECKER_ERROR; typedef enum _DRAW_TYPE { diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md index ec36b3bc..7bc554e9 100644 --- a/layers/vk_validation_layer_details.md +++ b/layers/vk_validation_layer_details.md @@ -136,6 +136,8 @@ It flags errors when inconsistencies are found across interfaces between shader | Push constant not accessible from stage | Flags error if the push constant range containing a push constant block member is not accessible from the current shader stage. | PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE | vkCreateGraphicsPipelines | TBD | NA | | Descriptor not accessible from stage | Flags error if a descriptor used by a shader stage does not include that stage in its stageFlags | DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE | vkCreateGraphicsPipelines | TBD | NA | | Descriptor type mismatch | Flags error if a descriptor type does not match the shader resource type. | DESCRIPTOR_TYPE_MISMATCH | vkCreateGraphicsPipelines | TBD | NA | +| Feature not enabled | Flags error if a capability declared by the shader requires a feature not enabled on the device | FEATURE_NOT_ENABLED | vkCreateGraphicsPipelines | TBD | NA | +| Bad capability | Flags error if a capability declared by the shader is not supported by Vulkan shaders | BAD_CAPABILITY | vkCreateGraphicsPipelines | TBD | NA | | NA | Enum used for informational messages | NONE | | NA | None | ### VK_LAYER_LUNARG_core_validation Shader Checker Pending Work -- cgit v1.2.3