@@ -187,8 +187,57 @@ uint32_t getNumberOfChannels(VkFormat format)
187187 return 0 ;
188188}
189189
190+ // preprocessSpirv applies and freezes specializations into constants, inlines
191+ // all functions and performs constant folding.
192+ std::vector<uint32_t > preprocessSpirv (
193+ std::vector<uint32_t > const &code,
194+ VkSpecializationInfo const *specializationInfo)
195+ {
196+ spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1};
197+
198+ opt.SetMessageConsumer ([](spv_message_level_t level, const char *, const spv_position_t & p, const char * m) {
199+ switch (level)
200+ {
201+ case SPV_MSG_FATAL:
202+ case SPV_MSG_INTERNAL_ERROR:
203+ case SPV_MSG_ERROR:
204+ ERR (" %d:%d %s" , p.line , p.column , m);
205+ break ;
206+ case SPV_MSG_WARNING:
207+ case SPV_MSG_INFO:
208+ case SPV_MSG_DEBUG:
209+ TRACE (" %d:%d %s" , p.line , p.column , m);
210+ break ;
211+ }
212+ });
213+
214+ opt.RegisterPass (spvtools::CreateInlineExhaustivePass ());
215+
216+ // If the pipeline uses specialization, apply the specializations before freezing
217+ if (specializationInfo)
218+ {
219+ std::unordered_map<uint32_t , std::vector<uint32_t >> specializations;
220+ for (auto i = 0u ; i < specializationInfo->mapEntryCount ; ++i)
221+ {
222+ auto const &e = specializationInfo->pMapEntries [i];
223+ auto value_ptr =
224+ static_cast <uint32_t const *>(specializationInfo->pData ) + e.offset / sizeof (uint32_t );
225+ specializations.emplace (e.constantID ,
226+ std::vector<uint32_t >{value_ptr, value_ptr + e.size / sizeof (uint32_t )});
227+ }
228+ opt.RegisterPass (spvtools::CreateSetSpecConstantDefaultValuePass (specializations));
229+ }
230+ // Freeze specialization constants into normal constants, and propagate through
231+ opt.RegisterPass (spvtools::CreateFreezeSpecConstantValuePass ());
232+ opt.RegisterPass (spvtools::CreateFoldSpecConstantOpAndCompositePass ());
233+
234+ std::vector<uint32_t > optimized;
235+ opt.Run (code.data (), code.size (), &optimized);
236+ return optimized;
190237}
191238
239+ } // anonymous namespace
240+
192241namespace vk
193242{
194243
@@ -418,33 +467,10 @@ void GraphicsPipeline::compileShaders(const VkAllocationCallbacks* pAllocator, c
418467 {
419468 auto module = Cast (pStage->module );
420469
421- auto code = module ->getCode ();
422- spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1};
423- opt.RegisterPass (spvtools::CreateInlineExhaustivePass ());
424-
425- // If the pipeline uses specialization, apply the specializations before freezing
426- if (pStage->pSpecializationInfo )
427- {
428- std::unordered_map<uint32_t , std::vector<uint32_t >> specializations;
429- for (auto i = 0u ; i < pStage->pSpecializationInfo ->mapEntryCount ; ++i)
430- {
431- auto const &e = pStage->pSpecializationInfo ->pMapEntries [i];
432- auto value_ptr =
433- static_cast <uint32_t const *>(pStage->pSpecializationInfo ->pData ) + e.offset / sizeof (uint32_t );
434- specializations.emplace (e.constantID ,
435- std::vector<uint32_t >{value_ptr, value_ptr + e.size / sizeof (uint32_t )});
436- }
437- opt.RegisterPass (spvtools::CreateSetSpecConstantDefaultValuePass (specializations));
438- }
439- // Freeze specialization constants into normal constants, and propagate through
440- opt.RegisterPass (spvtools::CreateFreezeSpecConstantValuePass ());
441- opt.RegisterPass (spvtools::CreateFoldSpecConstantOpAndCompositePass ());
442-
443- std::vector<uint32_t > postOptCode;
444- opt.Run (code.data (), code.size (), &postOptCode);
470+ auto code = preprocessSpirv (module ->getCode (), pStage->pSpecializationInfo );
445471
446472 // TODO: also pass in any pipeline state which will affect shader compilation
447- auto spirvShader = new sw::SpirvShader{postOptCode };
473+ auto spirvShader = new sw::SpirvShader{code };
448474
449475 switch (pStage->stage )
450476 {
0 commit comments