blob: 114e649024c2f5cb90731c702e852b3c5da953c7 [file] [log] [blame]
/* 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;
}