VKPipeline: Log any errors produced by the SPIR-V optimizer Some dEQP tests were not made for SPV_ENV_VULKAN_1_1, and error in the optimizer. This produces 0 words of SPIR-V, that then goes and explodes in SpirvShader. Add an assert to catch the 0-word case. Bug: b/127454276 Change-Id: I60576e6691a9cf74656dfcd9c53aeed7ab578de1 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26188 Tested-by: Ben Clayton <bclayton@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp index a446e64..3e512a5 100644 --- a/src/Vulkan/VkPipeline.cpp +++ b/src/Vulkan/VkPipeline.cpp
@@ -187,8 +187,57 @@ return 0; } +// preprocessSpirv applies and freezes specializations into constants, inlines +// all functions and performs constant folding. +std::vector<uint32_t> preprocessSpirv( + std::vector<uint32_t> const &code, + VkSpecializationInfo const *specializationInfo) +{ + spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1}; + + opt.SetMessageConsumer([](spv_message_level_t level, const char*, const spv_position_t& p, const char* m) { + switch (level) + { + case SPV_MSG_FATAL: + case SPV_MSG_INTERNAL_ERROR: + case SPV_MSG_ERROR: + ERR("%d:%d %s", p.line, p.column, m); + break; + case SPV_MSG_WARNING: + case SPV_MSG_INFO: + case SPV_MSG_DEBUG: + TRACE("%d:%d %s", p.line, p.column, m); + break; + } + }); + + opt.RegisterPass(spvtools::CreateInlineExhaustivePass()); + + // If the pipeline uses specialization, apply the specializations before freezing + if (specializationInfo) + { + std::unordered_map<uint32_t, std::vector<uint32_t>> specializations; + for (auto i = 0u; i < specializationInfo->mapEntryCount; ++i) + { + auto const &e = specializationInfo->pMapEntries[i]; + auto value_ptr = + static_cast<uint32_t const *>(specializationInfo->pData) + e.offset / sizeof(uint32_t); + specializations.emplace(e.constantID, + std::vector<uint32_t>{value_ptr, value_ptr + e.size / sizeof(uint32_t)}); + } + opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations)); + } + // Freeze specialization constants into normal constants, and propagate through + opt.RegisterPass(spvtools::CreateFreezeSpecConstantValuePass()); + opt.RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass()); + + std::vector<uint32_t> optimized; + opt.Run(code.data(), code.size(), &optimized); + return optimized; } +} // anonymous namespace + namespace vk { @@ -418,33 +467,10 @@ { auto module = Cast(pStage->module); - auto code = module->getCode(); - spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1}; - opt.RegisterPass(spvtools::CreateInlineExhaustivePass()); - - // If the pipeline uses specialization, apply the specializations before freezing - if (pStage->pSpecializationInfo) - { - std::unordered_map<uint32_t, std::vector<uint32_t>> specializations; - for (auto i = 0u; i < pStage->pSpecializationInfo->mapEntryCount; ++i) - { - auto const &e = pStage->pSpecializationInfo->pMapEntries[i]; - auto value_ptr = - static_cast<uint32_t const *>(pStage->pSpecializationInfo->pData) + e.offset / sizeof(uint32_t); - specializations.emplace(e.constantID, - std::vector<uint32_t>{value_ptr, value_ptr + e.size / sizeof(uint32_t)}); - } - opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations)); - } - // Freeze specialization constants into normal constants, and propagate through - opt.RegisterPass(spvtools::CreateFreezeSpecConstantValuePass()); - opt.RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass()); - - std::vector<uint32_t> postOptCode; - opt.Run(code.data(), code.size(), &postOptCode); + auto code = preprocessSpirv(module->getCode(), pStage->pSpecializationInfo); // TODO: also pass in any pipeline state which will affect shader compilation - auto spirvShader = new sw::SpirvShader{postOptCode}; + auto spirvShader = new sw::SpirvShader{code}; switch (pStage->stage) {