| /* Copyright (c) 2023 Nintendo |
| * Copyright (c) 2023 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "stateless/stateless_validation.h" |
| |
| bool StatelessValidation::manual_PreCallValidateCreateShadersEXT(VkDevice device, uint32_t createInfoCount, |
| const VkShaderCreateInfoEXT *pCreateInfos, |
| const VkAllocationCallbacks *pAllocator, VkShaderEXT *pShaders, |
| const ErrorObject &error_obj) const { |
| bool skip = false; |
| |
| for (uint32_t i = 0; i < createInfoCount; ++i) { |
| const Location create_info_loc = error_obj.location.dot(Field::pCreateInfos, i); |
| const VkShaderCreateInfoEXT &createInfo = pCreateInfos[i]; |
| if (createInfo.codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT && SafeModulo(createInfo.codeSize, 4) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-codeSize-08735", device, create_info_loc.dot(Field::codeSize), |
| "(%" PRIu64 ") is not a multiple of 4.", static_cast<uint64_t>(createInfo.codeSize)); |
| } |
| |
| auto pCode = reinterpret_cast<std::uintptr_t>(createInfo.pCode); |
| if (createInfo.codeType == VK_SHADER_CODE_TYPE_BINARY_EXT) { |
| if (SafeModulo(pCode, 16 * sizeof(unsigned char)) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-pCode-08492", device, create_info_loc.dot(Field::codeType), |
| "is VK_SHADER_CODE_TYPE_BINARY_EXT, but pCodde is not aligned to 16 bytes."); |
| } |
| } else if (createInfo.codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT) { |
| if (SafeModulo(pCode, 4 * sizeof(unsigned char)) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-pCode-08493", device, create_info_loc.dot(Field::codeType), |
| "is VK_SHADER_CODE_TYPE_SPIRV_EXT, but pCodde is not aligned to 4 bytes."); |
| } |
| } |
| |
| const VkShaderStageFlags linkedStages = VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT | |
| VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | |
| VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | |
| VK_SHADER_STAGE_FRAGMENT_BIT; |
| if ((createInfo.stage & linkedStages) == 0 && (createInfo.flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08412", device, create_info_loc.dot(Field::flags), |
| "is %s and stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| if ((createInfo.stage != VK_SHADER_STAGE_COMPUTE_BIT) && |
| ((createInfo.flags & VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT) != 0)) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08485", device, create_info_loc.dot(Field::flags), |
| "is %s and stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| if (createInfo.stage != VK_SHADER_STAGE_FRAGMENT_BIT) { |
| if ((createInfo.flags & VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08486", device, create_info_loc.dot(Field::flags), |
| "is %s and stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| if ((createInfo.flags & VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08488", device, create_info_loc.dot(Field::flags), |
| "is %s and stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| } |
| |
| if (createInfo.stage != VK_SHADER_STAGE_MESH_BIT_EXT && (createInfo.flags & VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08414", device, create_info_loc.dot(Field::flags), |
| "is %s and stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| |
| if (createInfo.stage == VK_SHADER_STAGE_VERTEX_BIT) { |
| if ((createInfo.nextStage & |
| ~(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08427", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_VERTEX_BIT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { |
| if ((createInfo.nextStage & ~(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08430", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { |
| if ((createInfo.nextStage & ~(VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08431", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_GEOMETRY_BIT) { |
| if ((createInfo.nextStage & ~VK_SHADER_STAGE_FRAGMENT_BIT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08433", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_GEOMETRY_BIT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT || createInfo.stage == VK_SHADER_STAGE_COMPUTE_BIT) { |
| if (createInfo.nextStage != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08434", device, create_info_loc.dot(Field::stage), |
| "is %s, but nextStage is %s.", string_VkShaderStageFlagBits(createInfo.stage), |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_TASK_BIT_EXT) { |
| if ((createInfo.nextStage & ~VK_SHADER_STAGE_MESH_BIT_EXT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08435", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_TASK_BIT_EXT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_MESH_BIT_EXT) { |
| if ((createInfo.nextStage & ~VK_SHADER_STAGE_FRAGMENT_BIT) != 0) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-nextStage-08436", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_MESH_BIT_EXT, but nextStage is %s.", |
| string_VkShaderStageFlags(createInfo.nextStage).c_str()); |
| } |
| } else if (createInfo.stage == VK_SHADER_STAGE_ALL_GRAPHICS) { |
| // string_VkShaderStageFlagBits can't print these, so list manually |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08418", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_ALL_GRAPHICS."); |
| } else if (createInfo.stage == VK_SHADER_STAGE_ALL) { |
| // string_VkShaderStageFlagBits can't print these, so list manually |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08418", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_ALL."); |
| } else if (createInfo.stage == VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08425", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI."); |
| } else if (createInfo.stage == VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-stage-08426", device, create_info_loc.dot(Field::stage), |
| "is VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI."); |
| } |
| |
| if (((createInfo.flags & VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT) != 0) && |
| ((createInfo.stage & (VK_SHADER_STAGE_MESH_BIT_EXT | VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_COMPUTE_BIT)) == |
| 0)) { |
| skip |= LogError("VUID-VkShaderCreateInfoEXT-flags-08992", device, create_info_loc.dot(Field::flags), |
| "is %s, but stage is %s.", string_VkShaderCreateFlagsEXT(createInfo.flags).c_str(), |
| string_VkShaderStageFlagBits(createInfo.stage)); |
| } |
| } |
| |
| return skip; |
| } |
| |
| bool StatelessValidation::manual_PreCallValidateGetShaderBinaryDataEXT(VkDevice device, VkShaderEXT shader, size_t *pDataSize, |
| void *pData, const ErrorObject &error_obj) const { |
| bool skip = false; |
| |
| if (pData) { |
| auto ptr = reinterpret_cast<std::uintptr_t>(pData); |
| if (SafeModulo(ptr, 16 * sizeof(unsigned char)) != 0) { |
| skip |= LogError("VUID-vkGetShaderBinaryDataEXT-None-08499", device, error_obj.location.dot(Field::pData), |
| "is not aligned to 16 bytes."); |
| } |
| } |
| |
| return skip; |
| } |