Commit 45faa084 by Ben Clayton

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/+/26188Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 952d2738
...@@ -28,6 +28,8 @@ namespace sw ...@@ -28,6 +28,8 @@ namespace sw
outputs{MAX_INTERFACE_COMPONENTS}, outputs{MAX_INTERFACE_COMPONENTS},
serialID{serialCounter++}, modes{} serialID{serialCounter++}, modes{}
{ {
ASSERT(insns.size() > 0);
// Simplifying assumptions (to be satisfied by earlier transformations) // Simplifying assumptions (to be satisfied by earlier transformations)
// - There is exactly one entrypoint in the module, and it's the one we want // - There is exactly one entrypoint in the module, and it's the one we want
// - The only input/output OpVariables present are those used by the entrypoint // - The only input/output OpVariables present are those used by the entrypoint
......
...@@ -187,8 +187,57 @@ uint32_t getNumberOfChannels(VkFormat format) ...@@ -187,8 +187,57 @@ uint32_t getNumberOfChannels(VkFormat format)
return 0; 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 namespace vk
{ {
...@@ -418,33 +467,10 @@ void GraphicsPipeline::compileShaders(const VkAllocationCallbacks* pAllocator, c ...@@ -418,33 +467,10 @@ void GraphicsPipeline::compileShaders(const VkAllocationCallbacks* pAllocator, c
{ {
auto module = Cast(pStage->module); auto module = Cast(pStage->module);
auto code = module->getCode(); auto code = preprocessSpirv(module->getCode(), pStage->pSpecializationInfo);
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);
// TODO: also pass in any pipeline state which will affect shader compilation // 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) switch (pStage->stage)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment