diff --git a/layers/vulkansc/state_tracker/sc_pipeline_state.cpp b/layers/vulkansc/state_tracker/sc_pipeline_state.cpp index dc5856cf5..36cc3741e 100644 --- a/layers/vulkansc/state_tracker/sc_pipeline_state.cpp +++ b/layers/vulkansc/state_tracker/sc_pipeline_state.cpp @@ -29,59 +29,7 @@ namespace vvl::sc { -PipelineCache::PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache, - const VkPipelineCacheCreateInfo* pCreateInfo) - : vvl::PipelineCache(pipeline_cache, pCreateInfo), pipelines_() { - vvl::sc::PipelineCacheData pipeline_cache_data(*pCreateInfo); - - for (uint32_t pipeline_index = 0; pipeline_index < pipeline_cache_data.PipelineIndexCount(); ++pipeline_index) { - auto cache_entry = pipeline_cache_data.PipelineIndexEntry(pipeline_index); - if (cache_entry) { - pipelines_.emplace(cache_entry.PipelineID(), Entry(state_data, cache_entry)); - } - } -} - -PipelineCache::Entry::StageModules PipelineCache::Entry::InitShaderModules(const DeviceState& state_data, - const PipelineCacheData::Entry& cache_entry) { - Entry::StageModules stage_modules; - stage_modules.reserve(cache_entry.StageIndexCount()); - - for (uint32_t stage_index = 0; stage_index < cache_entry.StageIndexCount(); ++stage_index) { - auto code = cache_entry.StageSPIRV(stage_index); - - if (code.size() > 0) { - spirv::StatelessData stateless_data{}; - auto spirv_module = vvl::CreateSpirvModuleState(code.size() * sizeof(uint32_t), code.data(), state_data.global_settings, &stateless_data); - - if (stateless_data.has_group_decoration) { - // Run optimizer to flatten group decorations - spv_target_env spirv_environment = PickSpirvEnv(state_data.api_version, true); - spvtools::Optimizer optimizer(spirv_environment); - optimizer.RegisterPass(spvtools::CreateFlattenDecorationPass()); - std::vector optimized_binary; - auto result = optimizer.Run(spirv_module->words_.data(), spirv_module->words_.size(), &optimized_binary, - spvtools::ValidatorOptions(), true); - if (result) { - spirv_module = std::make_shared(optimized_binary); - } - } - - // We use the SPIR-V module pointer as the internal shader module handle - auto handle = (VkShaderModule)spirv_module.get(); - auto module_state = std::make_shared(handle, spirv_module); - - stage_modules.emplace_back(std::move(module_state)); - } else { - stage_modules.emplace_back(nullptr); - } - } - return stage_modules; -} - -PipelineCache::Entry::JsonData PipelineCache::Entry::ParseJsonData(const PipelineCacheData::Entry& cache_entry) { - PipelineCache::Entry::JsonData data{}; - +PipelineJsonData::PipelineJsonData(const PipelineCacheData::Entry& cache_entry) { auto parse_entrypoint_name = [](const Json::Value& entrypoint_name) -> std::string { if (entrypoint_name.isString()) { auto result = entrypoint_name.asString(); @@ -145,31 +93,80 @@ PipelineCache::Entry::JsonData PipelineCache::Entry::ParseJsonData(const Pipelin std::istringstream json_stream(json_string); std::string json_errors{}; Json::CharReaderBuilder builder{}; - bool parse_ok = Json::parseFromStream(builder, json_stream, &data.json, &json_errors); + bool parse_ok = Json::parseFromStream(builder, json_stream, &this->json, &json_errors); if (parse_ok) { - auto graphics_pipe_state = data.json["GraphicsPipelineState"]; + auto graphics_pipe_state = this->json["GraphicsPipelineState"]; if (graphics_pipe_state != Json::nullValue) { auto stages = graphics_pipe_state["GraphicsPipeline"]["pStages"]; uint32_t stage_count = graphics_pipe_state["GraphicsPipeline"]["stageCount"].asUInt(); - data.entrypoint_name.reserve(stage_count); - data.specialization_info.reserve(stage_count); + this->entrypoint_name.reserve(stage_count); + this->specialization_info.reserve(stage_count); for (uint32_t stage_index = 0; stage_index < stage_count; ++stage_index) { auto stage = stages[stage_index]; - data.entrypoint_name.push_back(parse_entrypoint_name(stage["pName"])); - data.specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"])); + this->entrypoint_name.push_back(parse_entrypoint_name(stage["pName"])); + this->specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"])); } } - auto compute_pipe_state = data.json["ComputePipelineState"]; + auto compute_pipe_state = this->json["ComputePipelineState"]; if (compute_pipe_state != Json::nullValue) { auto stage = compute_pipe_state["ComputePipeline"]["stage"]; - data.entrypoint_name.push_back(parse_entrypoint_name(stage["pName"])); - data.specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"])); + this->entrypoint_name.push_back(parse_entrypoint_name(stage["pName"])); + this->specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"])); } } } +} + +PipelineCache::PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache, + const VkPipelineCacheCreateInfo* pCreateInfo) + : vvl::PipelineCache(pipeline_cache, pCreateInfo), pipelines_() { + vvl::sc::PipelineCacheData pipeline_cache_data(*pCreateInfo); - return data; + for (uint32_t pipeline_index = 0; pipeline_index < pipeline_cache_data.PipelineIndexCount(); ++pipeline_index) { + auto cache_entry = pipeline_cache_data.PipelineIndexEntry(pipeline_index); + if (cache_entry) { + pipelines_.emplace(cache_entry.PipelineID(), Entry(state_data, cache_entry)); + } + } +} + +PipelineCache::Entry::StageModules PipelineCache::Entry::InitShaderModules(const DeviceState& state_data, + const PipelineCacheData::Entry& cache_entry) { + Entry::StageModules stage_modules; + stage_modules.reserve(cache_entry.StageIndexCount()); + + for (uint32_t stage_index = 0; stage_index < cache_entry.StageIndexCount(); ++stage_index) { + auto code = cache_entry.StageSPIRV(stage_index); + + if (code.size() > 0) { + spirv::StatelessData stateless_data{}; + auto spirv_module = vvl::CreateSpirvModuleState(code.size() * sizeof(uint32_t), code.data(), state_data.global_settings, + &stateless_data); + + if (stateless_data.has_group_decoration) { + // Run optimizer to flatten group decorations + spv_target_env spirv_environment = PickSpirvEnv(state_data.api_version, true); + spvtools::Optimizer optimizer(spirv_environment); + optimizer.RegisterPass(spvtools::CreateFlattenDecorationPass()); + std::vector optimized_binary; + auto result = optimizer.Run(spirv_module->words_.data(), spirv_module->words_.size(), &optimized_binary, + spvtools::ValidatorOptions(), true); + if (result) { + spirv_module = std::make_shared(optimized_binary); + } + } + + // We use the SPIR-V module pointer as the internal shader module handle + auto handle = (VkShaderModule)spirv_module.get(); + auto module_state = std::make_shared(handle, spirv_module); + + stage_modules.emplace_back(std::move(module_state)); + } else { + stage_modules.emplace_back(nullptr); + } + } + return stage_modules; } } // namespace vvl::sc diff --git a/layers/vulkansc/state_tracker/sc_pipeline_state.h b/layers/vulkansc/state_tracker/sc_pipeline_state.h index 23dbdd3d1..83858a027 100644 --- a/layers/vulkansc/state_tracker/sc_pipeline_state.h +++ b/layers/vulkansc/state_tracker/sc_pipeline_state.h @@ -161,6 +161,14 @@ class PipelineCacheData { } }; +struct PipelineJsonData { + Json::Value json{}; + std::vector entrypoint_name{}; + std::vector> specialization_info{}; + + PipelineJsonData(const PipelineCacheData::Entry& cache_entry); +}; + class PipelineCache : public vvl::PipelineCache { public: class Entry { @@ -169,9 +177,7 @@ class PipelineCache : public vvl::PipelineCache { using StageModules = std::vector>; Entry(const DeviceState& state_data, const PipelineCacheData::Entry& cache_entry) - : id_(cache_entry.PipelineID()), - shader_modules_(InitShaderModules(state_data, cache_entry)), - json_data_(ParseJsonData(cache_entry)) {} + : id_(cache_entry.PipelineID()), shader_modules_(InitShaderModules(state_data, cache_entry)), json_data_(cache_entry) {} ID PipelineID() const { return id_; } @@ -200,18 +206,11 @@ class PipelineCache : public vvl::PipelineCache { } private: - struct JsonData { - Json::Value json{}; - std::vector entrypoint_name{}; - std::vector> specialization_info{}; - }; - StageModules InitShaderModules(const DeviceState& state_data, const PipelineCacheData::Entry& cache_entry); - JsonData ParseJsonData(const PipelineCacheData::Entry& cache_entry); ID id_; const StageModules shader_modules_; - JsonData json_data_; + PipelineJsonData json_data_; }; PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache, const VkPipelineCacheCreateInfo* pCreateInfo); diff --git a/scripts/vksc_convert_tests.json b/scripts/vksc_convert_tests.json index 17e394195..b4b2d099b 100644 --- a/scripts/vksc_convert_tests.json +++ b/scripts/vksc_convert_tests.json @@ -292,7 +292,15 @@ ] }, { - "reason": "TODO: These tests fail due to some SPIR-V Tools bugs and do not happen to show up upstream as they do spec constant folding and other optimizations on SPIR-V before validation, unlike our device-create-time SPIR-V validation", + "reason": "TODO: These tests fail due to a combination of glslang and SPIR-V Tools bugs", + "details": [ + "The two bugs that cause this are as follows:", + " - glslang incorrectly generates the InputAttachmentArrayDynamicIndexing cap into the SPIR-V", + " - spirv-val claims that InputAttachmentArrayDynamicIndexing is not supported in Vulkan 1.2 (which it is)", + "This does not happen upstream because the shader is built with the Vulkan 1.0 SPIR-V environment not, Vulkan 1.2, therefore:", + " - glslang does not generate the InputAttachmentArrayDynamicIndexing into the SPIR-V because it does not exist in that version", + " - hence spirv-val does not complain" + ], "cases": [ "NegativeSubpass.InputAttachmentMissingSpecConstant", "PositiveSubpass.InputAttachmentMissingSpecConstant"