Skip to content

Commit

Permalink
VKPipeline: Log any errors produced by the SPIR-V optimizer
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ben-clayton committed Mar 7, 2019
1 parent 952d273 commit 45faa08
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 25 deletions.
2 changes: 2 additions & 0 deletions src/Pipeline/SpirvShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace sw
outputs{MAX_INTERFACE_COMPONENTS},
serialID{serialCounter++}, modes{}
{
ASSERT(insns.size() > 0);

// Simplifying assumptions (to be satisfied by earlier transformations)
// - 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
Expand Down
76 changes: 51 additions & 25 deletions src/Vulkan/VkPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,57 @@ uint32_t getNumberOfChannels(VkFormat format)
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
{

Expand Down Expand Up @@ -418,33 +467,10 @@ void GraphicsPipeline::compileShaders(const VkAllocationCallbacks* pAllocator, c
{
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)
{
Expand Down

0 comments on commit 45faa08

Please sign in to comment.