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.\n VkShaderEXT create flags: %s\n VkPipelineLayout "
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\n Create 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+
690818bool 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);
0 commit comments