Skip to content

Commit 6815cd5

Browse files
layers: Add VK_KHR_maintenance11
1 parent 1abb656 commit 6815cd5

25 files changed

Lines changed: 673 additions & 44 deletions

layers/core_checks/cc_copy_blit_resolve.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,16 @@ bool CoreChecks::ValidateBufferImageCopyData(const vvl::CommandBuffer& cb_state,
766766
}
767767
}
768768

769-
if (!IsIntegerMultipleOf(region.bufferOffset, 4)) {
769+
if (!enabled_features.maintenance11 && !IsIntegerMultipleOf(region.bufferOffset, 4)) {
770770
const VkQueueFlags required_flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
771771
if (!HasRequiredQueueFlags(cb_state, *physical_device_state, required_flags)) {
772772
const char* vuid = GetCopyBufferImageDeviceVUID(region_loc, vvl::CopyError::BufferOffset_07737).c_str();
773773
const LogObjectList objlist(cb_state.Handle(), cb_state.command_pool->Handle());
774-
skip |=
775-
LogError(vuid, objlist, region_loc.dot(Field::bufferOffset), "(%" PRIu64 ") is not a multiple of 4, but is %s",
776-
region.bufferOffset, DescribeRequiredQueueFlag(cb_state, *physical_device_state, required_flags).c_str());
774+
skip |= LogError(
775+
vuid, objlist, region_loc.dot(Field::bufferOffset),
776+
"(%" PRIu64
777+
") is not a multiple of 4, but is %s\nHint: This can be allowed in some cases if maintenance11 feature is enabled.",
778+
region.bufferOffset, DescribeRequiredQueueFlag(cb_state, *physical_device_state, required_flags).c_str());
777779
}
778780
}
779781

layers/core_checks/cc_image.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,10 +2008,19 @@ bool CoreChecks::ValidateImageViewCreateInfo(const VkImageViewCreateInfo& create
20082008
}
20092009

20102010
const bool multiplane_image = vkuFormatIsMultiplane(image_format);
2011-
if (multiplane_image && IsMultiplePlaneAspect(aspect_mask)) {
2012-
skip |= LogError("VUID-VkImageViewCreateInfo-subresourceRange-07818", create_info.image,
2013-
create_info_loc.dot(Field::subresourceRange).dot(Field::aspectMask), "(%s) is invalid for %s.",
2014-
string_VkImageAspectFlags(aspect_mask).c_str(), string_VkFormat(image_format));
2011+
if (multiplane_image) {
2012+
if (IsMultiplePlaneAspect(aspect_mask)) {
2013+
skip |= LogError("VUID-VkImageViewCreateInfo-subresourceRange-07818", create_info.image,
2014+
create_info_loc.dot(Field::subresourceRange).dot(Field::aspectMask), "(%s) is invalid for %s.",
2015+
string_VkImageAspectFlags(aspect_mask).c_str(), string_VkFormat(image_format));
2016+
}
2017+
2018+
if (image_flags & VK_IMAGE_CREATE_ALIAS_SINGLE_LAYER_DESCRIPTOR_BIT_KHR) {
2019+
skip |= LogError("VUID-VkImageViewCreateInfo-image-13357", create_info.image, create_info_loc.dot(Field::format),
2020+
"(%s) is a multiplane format, but the image was created with flag "
2021+
"VK_IMAGE_CREATE_ALIAS_SINGLE_LAYER_DESCRIPTOR_BIT_KHR. (image flags: %s).",
2022+
string_VkFormat(view_format), string_VkImageCreateFlags(image_flags).c_str());
2023+
}
20152024
}
20162025

20172026
if ((image_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && (image_format != view_format)) {

layers/core_checks/cc_shader_object.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <vulkan/vulkan_core.h>
1818
#include <spirv/unified1/spirv.hpp>
19+
#include <sstream>
1920
#include "chassis/chassis_modification_state.h"
2021
#include "core_validation.h"
2122
#include "error_message/logging.h"
@@ -687,6 +688,133 @@ bool CoreChecks::ValidateDrawShaderObjectBoundShader(const LastBound& last_bound
687688
return skip;
688689
}
689690

691+
bool CoreChecks::ValidateDrawShaderObjectFlags(const LastBound& last_bound_state, const Location& loc) const {
692+
bool skip = false;
693+
694+
const vvl::ShaderObject* shader_with_independent_sets{};
695+
const vvl::ShaderObject* shader_without_independent_sets{};
696+
for (const vvl::ShaderObject* shader : last_bound_state.shader_object_states) {
697+
if (!shader || !shader->stage.HasSpirv()) {
698+
continue;
699+
}
700+
701+
if (shader->safe_create_info.flags & VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR) {
702+
shader_with_independent_sets = shader;
703+
} else {
704+
shader_without_independent_sets = shader;
705+
}
706+
707+
constexpr VkShaderCreateFlagsEXT independent_and_no_task =
708+
VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR | VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT;
709+
if ((shader->safe_create_info.flags & independent_and_no_task) == independent_and_no_task) {
710+
if (!(last_bound_state.desc_set_pipeline_layout->create_flags & VK_PIPELINE_LAYOUT_CREATE_NO_TASK_SHADER_BIT_KHR)) {
711+
const LogObjectList objlist(last_bound_state.cb_state.Handle(),
712+
last_bound_state.desc_set_pipeline_layout->VkHandle(),
713+
shader_with_independent_sets->VkHandle());
714+
skip |=
715+
LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INDEPENDENT_SETS_13364), objlist, loc,
716+
"Shader object bound at stage %s has both VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR and "
717+
"VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT but the VkPipelineLayout (bound with %s) was created without "
718+
"VK_PIPELINE_LAYOUT_CREATE_NO_TASK_SHADER_BIT_KHR.\nVkShaderEXT create flags: %s\nVkPipelineLayout "
719+
"create flags: %s",
720+
string_VkShaderStageFlagBits(shader->safe_create_info.stage),
721+
vvl::String(last_bound_state.GetDescriptorModeFunc()),
722+
string_VkShaderCreateFlagsEXT(shader->safe_create_info.flags).c_str(),
723+
string_VkPipelineLayoutCreateFlags(last_bound_state.desc_set_pipeline_layout->create_flags).c_str());
724+
}
725+
726+
if (last_bound_state.IsValidShaderObjectBound(ShaderObjectStage::TASK)) {
727+
const LogObjectList objlist(last_bound_state.cb_state.Handle());
728+
skip |= LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INDEPENDENT_SETS_13365), objlist, loc,
729+
"A shader object bound with VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT is bound, but a task "
730+
"stage shader object is also bound.");
731+
}
732+
}
733+
}
734+
735+
if (shader_with_independent_sets && shader_without_independent_sets) {
736+
const LogObjectList objlist(last_bound_state.cb_state.Handle(), shader_with_independent_sets->VkHandle(),
737+
shader_without_independent_sets->VkHandle());
738+
skip |= LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INDEPENDENT_SETS_13361), objlist, loc,
739+
"Shader object bound at stage %s has flag VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR but shader object "
740+
"bound at stage %s does not.",
741+
string_VkShaderStageFlagBits(shader_with_independent_sets->safe_create_info.stage),
742+
string_VkShaderStageFlagBits(shader_without_independent_sets->safe_create_info.stage));
743+
}
744+
745+
if (shader_with_independent_sets && last_bound_state.desc_set_pipeline_layout) {
746+
if (!(last_bound_state.desc_set_pipeline_layout->create_flags & VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT)) {
747+
const LogObjectList objlist(last_bound_state.cb_state.Handle(), last_bound_state.desc_set_pipeline_layout->VkHandle(),
748+
shader_with_independent_sets->VkHandle());
749+
skip |= LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INDEPENDENT_SETS_13362), objlist, loc,
750+
"Shader object bound at stage %s has flag VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR but the "
751+
"VkPipelineLayout (bound with %s) "
752+
"was created without the INDEPENDENT_SETS flag\nCreate flags: %s.",
753+
string_VkShaderStageFlagBits(shader_with_independent_sets->safe_create_info.stage),
754+
vvl::String(last_bound_state.GetDescriptorModeFunc()),
755+
string_VkPipelineLayoutCreateFlags(last_bound_state.desc_set_pipeline_layout->create_flags).c_str());
756+
}
757+
758+
std::optional<std::pair<uint32_t, uint32_t>> binding_with_pre_rast_stage;
759+
std::optional<std::pair<uint32_t, uint32_t>> binding_with_mesh_stage;
760+
const auto& set_layouts_list = last_bound_state.desc_set_pipeline_layout->set_layouts.list;
761+
for (auto [dsl_i, dsl] : vvl::enumerate(set_layouts_list)) {
762+
if (!dsl) {
763+
continue;
764+
}
765+
if (binding_with_pre_rast_stage.has_value() && binding_with_mesh_stage.has_value()) {
766+
break;
767+
}
768+
769+
// While there are few sets, the binding lists may be large
770+
// The goal is to only search the binding list if we can detect possible mixing of mesh/non-mesh pre-raster stages
771+
if ((dsl->HasTaskMesh() && !binding_with_mesh_stage.has_value()) ||
772+
(dsl->HasNonMeshPreRaster() && !binding_with_pre_rast_stage.has_value())) {
773+
for (uint32_t binding_idx = 0; binding_idx < dsl->GetBindingCount(); binding_idx++) {
774+
const VkDescriptorSetLayoutBinding* binding = dsl->GetDescriptorSetLayoutBindingPtrFromIndex(binding_idx);
775+
if (binding->stageFlags & (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
776+
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT)) {
777+
binding_with_pre_rast_stage = std::make_pair((uint32_t)dsl_i, binding->binding);
778+
}
779+
if (binding->stageFlags & (VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT)) {
780+
binding_with_mesh_stage = std::make_pair((uint32_t)dsl_i, binding->binding);
781+
}
782+
}
783+
}
784+
}
785+
786+
if (binding_with_pre_rast_stage.has_value() && binding_with_mesh_stage.has_value()) {
787+
const auto pre_raster_dsl = set_layouts_list[binding_with_pre_rast_stage->first];
788+
const auto mesh_dsl = set_layouts_list[binding_with_mesh_stage->first];
789+
790+
std::ostringstream ss;
791+
ss << "Shader object bound at stage "
792+
<< string_VkShaderStageFlagBits(shader_with_independent_sets->safe_create_info.stage)
793+
<< " has flag VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR but the VkPipelineLayout (bound with ";
794+
ss << vvl::String(last_bound_state.GetDescriptorModeFunc())
795+
<< ") is mixing mesh and non-mesh pre-rasterization shader stages\n";
796+
ss << FormatHandle(pre_raster_dsl->VkHandle()) << " at set " << binding_with_pre_rast_stage->first << ", binding "
797+
<< binding_with_pre_rast_stage->second << " has stageFlags "
798+
<< string_VkShaderStageFlags(
799+
pre_raster_dsl->GetDescriptorSetLayoutBindingPtrFromBinding(binding_with_pre_rast_stage->second)->stageFlags)
800+
<< '\n';
801+
if (pre_raster_dsl != mesh_dsl) {
802+
ss << FormatHandle(mesh_dsl->VkHandle()) << " at set " << binding_with_mesh_stage->first << ", binding "
803+
<< binding_with_mesh_stage->second << " has stageFlags "
804+
<< string_VkShaderStageFlags(
805+
mesh_dsl->GetDescriptorSetLayoutBindingPtrFromBinding(binding_with_mesh_stage->second)->stageFlags)
806+
<< '\n';
807+
}
808+
const LogObjectList objlist(last_bound_state.cb_state.Handle(), last_bound_state.desc_set_pipeline_layout->VkHandle(),
809+
pre_raster_dsl->VkHandle(), mesh_dsl->VkHandle(), shader_with_independent_sets->VkHandle());
810+
skip |= LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INDEPENDENT_SETS_13363), objlist, loc, "%s",
811+
ss.str().c_str());
812+
}
813+
}
814+
815+
return skip;
816+
}
817+
690818
bool CoreChecks::ValidateDrawShaderObject(const LastBound& last_bound_state, const Location& loc) const {
691819
bool skip = false;
692820
const vvl::CommandBuffer& cb_state = last_bound_state.cb_state;
@@ -707,6 +835,7 @@ bool CoreChecks::ValidateDrawShaderObject(const LastBound& last_bound_state, con
707835

708836
skip |= ValidateDrawShaderObjectNextStage(last_bound_state, loc);
709837
skip |= ValidateDrawShaderObjectBoundShader(last_bound_state, loc);
838+
skip |= ValidateDrawShaderObjectFlags(last_bound_state, loc);
710839
skip |= ValidateDrawShaderObjectLinking(last_bound_state, loc);
711840
skip |= ValidateDrawShaderObjectPushConstantAndLayout(last_bound_state, loc);
712841
skip |= ValidateDrawShaderObjectMesh(last_bound_state, loc);

layers/core_checks/core_validation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ class CoreChecks : public vvl::DeviceProxy {
741741
const vvl::DrawDispatchVuid& vuid) const;
742742
bool ValidateDrawShaderObjectNextStage(const LastBound& last_bound_state, const Location& loc) const;
743743
bool ValidateDrawShaderObjectBoundShader(const LastBound& last_bound_state, const Location& loc) const;
744+
bool ValidateDrawShaderObjectFlags(const LastBound& last_bound_state, const Location& loc) const;
744745
bool ValidateDrawShaderObject(const LastBound& last_bound_state, const Location& loc) const;
745746
bool ValidateDrawShaderObjectLinking(const LastBound& last_bound_state, const Location& loc) const;
746747
bool ValidateDrawShaderObjectPushConstantAndLayout(const LastBound& last_bound_state, const Location& loc) const;

layers/drawdispatch/drawdispatch_vuids.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,16 @@ std::string CreateActionVuid(vvl::Func function, const ActionVUID id) {
774774

775775
// ### VUID-vkCmdDraw-None-08601
776776
case ActionVUID::PUSH_CONSTANT_08601: suffix = "None-08601"; break;
777+
// ### VUID-vkCmdDraw-flags-13361
778+
case ActionVUID::INDEPENDENT_SETS_13361: suffix = "flags-13361"; break;
779+
// ### VUID-vkCmdDraw-flags-13362
780+
case ActionVUID::INDEPENDENT_SETS_13362: suffix = "flags-13362"; break;
781+
// ### VUID-vkCmdDraw-flags-13363
782+
case ActionVUID::INDEPENDENT_SETS_13363: suffix = "flags-13363"; break;
783+
// ### VUID-vkCmdDraw-flags-13364
784+
case ActionVUID::INDEPENDENT_SETS_13364: suffix = "flags-13364"; break;
785+
// ### VUID-vkCmdDraw-flags-13365
786+
case ActionVUID::INDEPENDENT_SETS_13365: suffix = "flags-13365"; break;
777787

778788
// ### VUID-vkCmdDraw-None-08608
779789
case ActionVUID::DYNAMIC_STATE_ALL_SET_08608: suffix = "None-08608"; break;

layers/drawdispatch/drawdispatch_vuids.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ enum class ActionVUID {
133133
FILTER_CUBIC_02695,
134134
IMAGE_LAYOUT_00344,
135135
PUSH_CONSTANT_08601,
136+
INDEPENDENT_SETS_13361,
137+
INDEPENDENT_SETS_13362,
138+
INDEPENDENT_SETS_13363,
139+
INDEPENDENT_SETS_13364,
140+
INDEPENDENT_SETS_13365,
136141

137142
DYNAMIC_STATE_ALL_SET_08608,
138143
DYNAMIC_DEPTH_COMPARE_OP_07845,

layers/error_message/unimplementable_validation.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ const char* unimplementable_validation[] = {
334334
"VUID-VkAccelerationStructureTrianglesOpacityMicromapEXT-ppUsageCounts-parameter",
335335
"VUID-VkAccelerationStructureTrianglesDisplacementMicromapNV-pUsageCounts-parameter",
336336
"VUID-VkAccelerationStructureTrianglesDisplacementMicromapNV-ppUsageCounts-parameter",
337-
"VUID-VkShaderCreateInfoEXT-pSetLayouts-parameter",
338337
"VUID-VkShaderCreateInfoEXT-pPushConstantRanges-parameter",
339338
"VUID-VkLatencySurfaceCapabilitiesNV-pPresentModes-parameter",
340339
"VUID-vkCmdBeginTransformFeedbackEXT-pCounterBufferOffsets-parameter",

layers/object_tracker/object_lifetime_validation.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,4 +1952,32 @@ bool Device::PreCallValidateWriteResourceDescriptorsEXT(VkDevice device, uint32_
19521952

19531953
return skip;
19541954
}
1955+
1956+
bool Device::PreCallValidateCreateShadersEXT(VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos,
1957+
const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders,
1958+
const ErrorObject& error_obj) const {
1959+
bool skip = false;
1960+
// Checked by chassis: device: "VUID-vkCreateShadersEXT-device-parameter"
1961+
if (pCreateInfos) {
1962+
for (uint32_t index0 = 0; index0 < createInfoCount; ++index0) {
1963+
[[maybe_unused]] const Location index0_loc = error_obj.location.dot(Field::pCreateInfos, index0);
1964+
1965+
const bool has_independent_set_flags = pCreateInfos[index0].flags & VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR;
1966+
// VK_KHR_maintenance11 added flag to allow null objects
1967+
bool null_allowed = has_independent_set_flags;
1968+
const char* vuid = null_allowed ? "VUID-VkShaderCreateInfoEXT-setLayoutCount-13360"
1969+
: "VUID-VkShaderCreateInfoEXT-setLayoutCount-13359";
1970+
if ((pCreateInfos[index0].setLayoutCount > 0) && (pCreateInfos[index0].pSetLayouts)) {
1971+
for (uint32_t index1 = 0; index1 < pCreateInfos[index0].setLayoutCount; ++index1) {
1972+
skip |= ValidateObject(pCreateInfos[index0].pSetLayouts[index1], kVulkanObjectTypeDescriptorSetLayout,
1973+
null_allowed, vuid, "UNASSIGNED-VkShaderCreateInfoEXT-pSetLayouts-parent",
1974+
index0_loc.dot(Field::pSetLayouts, index1));
1975+
}
1976+
}
1977+
}
1978+
}
1979+
1980+
return skip;
1981+
}
1982+
19551983
} // namespace object_lifetimes

layers/state_tracker/descriptor_sets.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ vvl::DescriptorSetLayoutDef::DescriptorSetLayoutDef(vvl::DeviceState& device_sta
277277
const VkDescriptorSetLayoutCreateInfo* p_create_info)
278278
: flags_(p_create_info->flags),
279279
has_ycbcr_samplers_(false),
280+
has_task_mask_(false),
281+
has_non_mesh_pre_raster_(false),
280282
binding_count_(0),
281283
descriptor_count_(0),
282284
non_inline_descriptor_count_(0),
@@ -330,6 +332,15 @@ vvl::DescriptorSetLayoutDef::DescriptorSetLayoutDef(vvl::DeviceState& device_sta
330332
binding_type_stats_.non_dynamic_buffer_count++;
331333
}
332334
}
335+
336+
if (binding_info.stageFlags & (VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT)) {
337+
has_task_mask_ = true;
338+
}
339+
if (binding_info.stageFlags & (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
340+
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT)) {
341+
has_non_mesh_pre_raster_ = true;
342+
}
343+
333344
// Get immutable samplers info
334345
if (binding_info.pImmutableSamplers != nullptr) {
335346
// Lazy allocation to avoid allocating array for layouts that don't use immutable samplers.

0 commit comments

Comments
 (0)