diff options
Diffstat (limited to 'layers/stateless_validation.h')
-rw-r--r-- | layers/stateless_validation.h | 140 |
1 files changed, 117 insertions, 23 deletions
diff --git a/layers/stateless_validation.h b/layers/stateless_validation.h index 7f0bd5784..199536ccc 100644 --- a/layers/stateless_validation.h +++ b/layers/stateless_validation.h @@ -21,8 +21,6 @@ #pragma once -#include <bitset> - #include "parameter_name.h" #include "vk_typemap_helper.h" @@ -44,6 +42,7 @@ static const char DECORATE_UNUSED *kVUID_PVError_DeviceLimit = "UNASSIGNED-Gener static const char DECORATE_UNUSED *kVUID_PVError_DeviceFeature = "UNASSIGNED-GeneralParameterError-DeviceFeature"; static const char DECORATE_UNUSED *kVUID_PVError_FailureCode = "UNASSIGNED-GeneralParameterError-FailureCode"; static const char DECORATE_UNUSED *kVUID_PVError_ExtensionNotEnabled = "UNASSIGNED-GeneralParameterError-ExtensionNotEnabled"; +static const char DECORATE_UNUSED *kVUID_PVPerfWarn_SuboptimalSwapchain = "UNASSIGNED-GeneralParameterPerfWarn-SuboptimalSwapchain"; #undef DECORATE_UNUSED @@ -54,6 +53,7 @@ extern const VkColorComponentFlags AllVkColorComponentFlagBits; extern const VkShaderStageFlags AllVkShaderStageFlagBits; extern const VkQueryControlFlags AllVkQueryControlFlagBits; extern const VkImageUsageFlags AllVkImageUsageFlagBits; +extern const VkSampleCountFlags AllVkSampleCountFlagBits; extern const std::vector<VkCompareOp> AllVkCompareOpEnums; extern const std::vector<VkStencilOp> AllVkStencilOpEnums; @@ -62,6 +62,9 @@ extern const std::vector<VkBlendOp> AllVkBlendOpEnums; extern const std::vector<VkLogicOp> AllVkLogicOpEnums; extern const std::vector<VkBorderColor> AllVkBorderColorEnums; extern const std::vector<VkImageLayout> AllVkImageLayoutEnums; +extern const std::vector<VkFormat> AllVkFormatEnums; +extern const std::vector<VkVertexInputRate> AllVkVertexInputRateEnums; +extern const std::vector<VkPrimitiveTopology> AllVkPrimitiveTopologyEnums; // String returned by string_VkStructureType for an unrecognized type. const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType"; @@ -87,7 +90,8 @@ struct LogMiscParams { class StatelessValidation : public ValidationObject { public: VkPhysicalDeviceLimits device_limits = {}; - VkPhysicalDeviceFeatures physical_device_features = {}; + safe_VkPhysicalDeviceFeatures2 physical_device_features2; + const VkPhysicalDeviceFeatures &physical_device_features = physical_device_features2.features; // Override chassis read/write locks for this validation object // This override takes a deferred lock. i.e. it is not acquired. @@ -700,6 +704,8 @@ class StatelessValidation : public ValidationObject { return skip_call; } + enum FlagType { kRequiredFlags, kOptionalFlags, kRequiredSingleBit, kOptionalSingleBit }; + /** * Validate a Vulkan bitmask value. * @@ -711,27 +717,37 @@ class StatelessValidation : public ValidationObject { * @param flag_bits_name Name of the VkFlags type being validated. * @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated. * @param value VkFlags value to validate. - * @param flags_required The 'value' parameter may not be 0 when true. - * @param singleFlag The 'value' parameter may not contain more than one bit from all_flags. + * @param flag_type The type of flag, like optional, or single bit. + * @param vuid VUID used for flag that is outside defined bits (or has more than one bit for Bits type). + * @param flags_zero_vuid VUID used for non-optional Flags that are zero. * @return Boolean value indicating that the call should be skipped. */ bool validate_flags(const char *api_name, const ParameterName ¶meter_name, const char *flag_bits_name, VkFlags all_flags, - VkFlags value, bool flags_required, bool singleFlag, const char *vuid) { + VkFlags value, const FlagType flag_type, const char *vuid, const char *flags_zero_vuid = nullptr) { bool skip_call = false; - if (value == 0) { - if (flags_required) { - skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid, - "%s: value of %s must not be 0.", api_name, parameter_name.get_name().c_str()); - } - } else if ((value & (~all_flags)) != 0) { - skip_call |= - log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, - kVUID_PVError_UnrecognizedValue, "%s: value of %s contains flag bits that are not recognized members of %s", - api_name, parameter_name.get_name().c_str(), flag_bits_name); - } else if (singleFlag && (std::bitset<sizeof(VkFlags) * 8>(value).count() > 1)) { - skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, - kVUID_PVError_UnrecognizedValue, + if ((value & ~all_flags) != 0) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid, + "%s: value of %s contains flag bits that are not recognized members of %s", api_name, + parameter_name.get_name().c_str(), flag_bits_name); + } + + const bool required = flag_type == kRequiredFlags || flag_type == kRequiredSingleBit; + const char *zero_vuid = flag_type == kRequiredFlags ? flags_zero_vuid : vuid; + if (required && value == 0) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, zero_vuid, + "%s: value of %s must not be 0.", api_name, parameter_name.get_name().c_str()); + } + + const auto HasMaxOneBitSet = [](const VkFlags f) { + // Decrement flips bits from right upto first 1. + // Rest stays same, and if there was any other 1s &ded together they would be non-zero. QED + return f == 0 || !(f & (f - 1)); + }; + + const bool is_bits_type = flag_type == kRequiredSingleBit || flag_type == kOptionalSingleBit; + if (is_bits_type && !HasMaxOneBitSet(value)) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, vuid, "%s: value of %s contains multiple members of %s when only a single value is allowed", api_name, parameter_name.get_name().c_str(), flag_bits_name); } @@ -821,6 +837,52 @@ class StatelessValidation : public ValidationObject { enum RenderPassCreateVersion { RENDER_PASS_VERSION_1 = 0, RENDER_PASS_VERSION_2 = 1 }; template <typename RenderPassCreateInfoGeneric> + bool ValidateSubpassGraphicsFlags(const debug_report_data *report_data, const RenderPassCreateInfoGeneric *pCreateInfo, + uint32_t dependency_index, uint32_t subpass, VkPipelineStageFlags stages, const char *vuid, + const char *target) { + const VkPipelineStageFlags kCommonStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + const VkPipelineStageFlags kFramebufferStages = + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + const VkPipelineStageFlags kPrimitiveShadingPipelineStages = + kCommonStages | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT | VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV | kFramebufferStages; + const VkPipelineStageFlags kMeshShadingPipelineStages = + kCommonStages | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV | + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV | VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV | kFramebufferStages; + const VkPipelineStageFlags kFragmentDensityStages = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT; + const VkPipelineStageFlags kConditionalRenderingStages = VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT; + const VkPipelineStageFlags kCommandProcessingPipelineStages = kCommonStages | VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX; + + const VkPipelineStageFlags kGraphicsStages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | kPrimitiveShadingPipelineStages | + kMeshShadingPipelineStages | kFragmentDensityStages | + kConditionalRenderingStages | kCommandProcessingPipelineStages; + + bool skip = false; + + const auto IsPipeline = [pCreateInfo](uint32_t subpass, const VkPipelineBindPoint stage) { + if (subpass == VK_SUBPASS_EXTERNAL) + return false; + else + return pCreateInfo->pSubpasses[subpass].pipelineBindPoint == stage; + }; + + const bool is_all_graphics_stages = (stages & ~kGraphicsStages) == 0; + if (IsPipeline(subpass, VK_PIPELINE_BIND_POINT_GRAPHICS) && !is_all_graphics_stages) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 0, vuid, + "Dependency pDependencies[%" PRIu32 + "] specifies a %sStageMask that contains stages (%s) that are not part " + "of the Graphics pipeline, as specified by the %sSubpass (= %" PRIu32 ") in pipelineBindPoint.", + dependency_index, target, string_VkPipelineStageFlags(stages & ~kGraphicsStages).c_str(), target, subpass); + } + + return skip; + }; + + template <typename RenderPassCreateInfoGeneric> bool CreateRenderPassGeneric(VkDevice device, const RenderPassCreateInfoGeneric *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass, RenderPassCreateVersion rp_version) { @@ -859,6 +921,22 @@ class StatelessValidation : public ValidationObject { pCreateInfo->pSubpasses[i].colorAttachmentCount, max_color_attachments); } } + + for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { + const auto &dependency = pCreateInfo->pDependencies[i]; + + // Spec currently only supports Graphics pipeline in render pass -- so only that pipeline is currently checked + vuid = + use_rp2 ? "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054" : "VUID-VkRenderPassCreateInfo-pDependencies-00837"; + skip |= ValidateSubpassGraphicsFlags(report_data, pCreateInfo, i, dependency.srcSubpass, dependency.srcStageMask, vuid, + "src"); + + vuid = + use_rp2 ? "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03055" : "VUID-VkRenderPassCreateInfo-pDependencies-00838"; + skip |= ValidateSubpassGraphicsFlags(report_data, pCreateInfo, i, dependency.dstSubpass, dependency.dstStageMask, vuid, + "dst"); + } + return skip; } @@ -900,7 +978,14 @@ class StatelessValidation : public ValidationObject { bool ValidateDeviceQueueFamily(uint32_t queue_family, const char *cmd_name, const char *parameter_name, const std::string &error_code, bool optional); - bool ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV &info); + bool ValidateGeometryTrianglesNV(const VkGeometryTrianglesNV &triangles, VkDebugReportObjectTypeEXT object_type, + uint64_t object_handle, const char *func_name) const; + bool ValidateGeometryAABBNV(const VkGeometryAABBNV &geometry, VkDebugReportObjectTypeEXT object_type, uint64_t object_handle, + const char *func_name) const; + bool ValidateGeometryNV(const VkGeometryNV &geometry, VkDebugReportObjectTypeEXT object_type, uint64_t object_handle, + const char *func_name) const; + bool ValidateAccelerationStructureInfoNV(const VkAccelerationStructureInfoNV &info, VkDebugReportObjectTypeEXT object_type, + uint64_t object_handle, const char *func_nam) const; bool OutputExtensionError(const std::string &api_name, const std::string &extension_name); @@ -915,6 +1000,8 @@ class StatelessValidation : public ValidationObject { void PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance, VkResult result); + void PostCallRecordQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo, VkResult result); + bool manual_PreCallValidateCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool); @@ -930,9 +1017,6 @@ class StatelessValidation : public ValidationObject { bool manual_PreCallValidateCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage); - bool manual_PreCallValidateCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkImageView *pView); - bool manual_PreCallValidateViewport(const VkViewport &viewport, const char *fn_name, const ParameterName ¶meter_name, VkDebugReportObjectTypeEXT object_type, uint64_t object); @@ -1069,5 +1153,15 @@ class StatelessValidation : public ValidationObject { bool PreCallValidateGetDeviceGroupSurfacePresentModes2EXT(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR *pModes); #endif // VK_USE_PLATFORM_WIN32_KHR + + bool manual_PreCallValidateCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer); + + bool manual_PreCallValidateCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, + uint16_t lineStipplePattern); + + bool manual_PreCallValidateCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkIndexType indexType); + #include "parameter_validation.h" }; // Class StatelessValidation |