1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "common/debug/Dump.hpp"
10 
11 #include "common/debug/TeeOutputStream.hpp"
12 
13 #include "AdaptorCommon/customApi.hpp"
14 #include "Compiler/CodeGenPublic.h"
15 #include "Compiler/CISACodeGen/ShaderCodeGen.hpp"
16 #include "Compiler/CISACodeGen/PixelShaderCodeGen.hpp"
17 #include "common/igc_regkeys.hpp"
18 
19 #include <iStdLib/utility.h>
20 
21 #include "common/LLVMWarningsPush.hpp"
22 #include <llvm/IR/Value.h>
23 #include <llvm/Support/raw_ostream.h>
24 #include <llvm/Support/raw_os_ostream.h>
25 #include <llvm/Support/FormattedStream.h>
26 #include <llvm/Support/FileSystem.h>
27 #include "common/LLVMWarningsPop.hpp"
28 
29 #include <stdarg.h>
30 #include <fstream>
31 #include <sstream>
32 #include <iomanip>
33 #include <mutex>
34 #include <algorithm>
35 #include <regex>
36 #include "Probe/Assertion.h"
37 
38 using namespace IGC;
39 using namespace IGC::Debug;
40 using namespace std;
41 
42 namespace IGC
43 {
44 namespace Debug
45 {
46 
47 char ModuleFlushDumpPass::ID = 0;
48 char FunctionFlushDumpPass::ID = 0;
49 
50 /*************************************************************************************************\
51  *  Generic
52  */
53 
DumpName(std::string const & dumpName)54 DumpName::DumpName( std::string const& dumpName )
55     : m_dumpName(dumpName)
56 {
57 }
58 
DumpName()59 DumpName::DumpName()
60 {
61 }
62 
ShaderName(std::string const & name) const63 DumpName DumpName::ShaderName(std::string const& name) const
64 {
65     IGC_ASSERT_MESSAGE(name.find(' ') == std::string::npos, "Shader name must not contain spaces");
66     DumpName copy(*this);
67     copy.m_shaderName = name;
68     return copy;
69 }
70 
Type(ShaderType type) const71 DumpName DumpName::Type(ShaderType type) const
72 {
73     DumpName copy(*this);
74     copy.m_type = type;
75     return copy;
76 }
77 
PSPhase(PixelShaderPhaseType phase) const78 DumpName DumpName::PSPhase(PixelShaderPhaseType phase) const
79 {
80     DumpName copy(*this);
81     copy.m_psPhase = phase;
82     return copy;
83 }
84 
Retry(unsigned retryId) const85 DumpName DumpName::Retry(unsigned retryId) const
86 {
87     DumpName copy(*this);
88     copy.m_retryId = retryId;
89     return copy;
90 }
91 
Extension(std::string const & extension) const92 DumpName DumpName::Extension(std::string const& extension) const
93 {
94     IGC_ASSERT_MESSAGE((extension.size() == 0) || (extension.at(0) != '.'),
95         "Extension shouldn't start with a '.', and shouldn't be empty");
96     IGC_ASSERT_MESSAGE(extension.find(' ') == std::string::npos, "Extension must not contain spaces");
97     DumpName copy(*this);
98     copy.m_extension = extension;
99     return copy;
100 }
101 
StagedInfo(void const * context) const102 DumpName DumpName::StagedInfo(void const* context) const
103 {
104     DumpName copy(*this);
105     if (!context)
106     {
107         return copy;
108     }
109 
110     IGC::CodeGenContext const* ctx = static_cast<IGC::CodeGenContext const*>(context);
111     if (!IsStage2RestSIMDs(ctx->m_StagingCtx) &&
112         ctx->m_CgFlag != FLAG_CG_ALL_SIMDS)
113     {
114         copy.m_cgFlag = ctx->m_CgFlag;
115     }
116     else if (IsStage2RestSIMDs(ctx->m_StagingCtx))
117     {
118         copy.m_cgFlag = FLAG_CG_ALL_SIMDS;
119     }
120     return copy;
121 }
122 
SIMDSize(SIMDMode width) const123 DumpName DumpName::SIMDSize(SIMDMode width) const
124 {
125     DumpName copy(*this);
126     copy.m_simdWidth = width;
127     return copy;
128 }
129 
DispatchMode(ShaderDispatchMode mode) const130 DumpName DumpName::DispatchMode(ShaderDispatchMode mode) const
131 {
132     DumpName copy(*this);
133     switch(mode)
134     {
135     case ShaderDispatchMode::SINGLE_PATCH:
136     case ShaderDispatchMode::DUAL_PATCH:
137     case ShaderDispatchMode::EIGHT_PATCH:
138         copy.m_ShaderMode = mode;
139         break;
140     default:
141         break;
142     }
143     return copy;
144 }
145 
Hash(ShaderHash hash) const146 DumpName DumpName::Hash(ShaderHash hash) const
147 {
148     DumpName copy(*this);
149     copy.m_hash = hash;
150     return copy;
151 }
152 
PostFix(std::string const & postfixStr) const153 DumpName DumpName::PostFix(std::string const& postfixStr) const
154 {
155     DumpName copy(*this);
156     copy.m_postfixStr = postfixStr;
157     return copy;
158 }
159 
Pass(std::string const & name,llvm::Optional<unsigned int> index) const160 DumpName DumpName::Pass(std::string const& name, llvm::Optional<unsigned int> index) const
161 {
162     std::string newName = name;
163     //remove spaces
164     newName.erase(remove_if(
165         newName.begin(),
166         newName.end(),
167         [](char c) { return isspace(static_cast<unsigned char>(c)); }),
168         newName.end());
169     std::replace_if(newName.begin(), newName.end(),
170         [](const char s) { return s == '/' || s == '\\'; }, '_');
171     IGC_ASSERT_MESSAGE(newName.find(' ') == std::string::npos, "Pass name must not contain spaces");
172     DumpName copy(*this);
173     CPassDescriptor pd = { newName, index };
174     copy.m_pass = pd;
175     return copy;
176 }
177 
178 std::unordered_map<QWORD, unsigned int> shaderHashMap;
179 std::mutex DumpName::hashMapLock;
180 unsigned int DumpName::shaderNum = 1;
181 
AbsolutePath(OutputFolderName folder) const182 std::string DumpName::AbsolutePath(OutputFolderName folder) const
183 {
184     std::stringstream ss;
185     bool underscore = false;  /// Determines whether the next segment prints a leading underscore
186 
187     ss << folder;
188 
189     //    m_dumpName = IGC::Debug::GetShaderOutputName();
190 
191     if(m_dumpName.hasValue() && m_dumpName.getValue() != "")
192     {
193         ss << m_dumpName.getValue();
194         underscore = true;
195     }
196     if(m_shaderName.hasValue())
197     {
198         ss << (underscore ? "_" : "")
199             << m_shaderName.getValue();
200         underscore = true;
201     }
202     if(m_type.hasValue())
203     {
204         ss << (underscore ? "_" : "");
205         switch(m_type.getValue())
206         {
207         case ShaderType::OPENCL_SHADER: ss << "OCL"; break;
208         case ShaderType::PIXEL_SHADER: ss << "PS"; break;
209         case ShaderType::DOMAIN_SHADER: ss << "DS"; break;
210         case ShaderType::HULL_SHADER: ss << "HS"; break;
211         case ShaderType::VERTEX_SHADER: ss << "VS"; break;
212         case ShaderType::GEOMETRY_SHADER: ss << "GS"; break;
213         case ShaderType::COMPUTE_SHADER: ss << "CS"; break;
214         case ShaderType::UNKNOWN:
215         default: IGC_ASSERT_MESSAGE(0, "Unknown Shader Type"); break;
216         }
217         underscore = true;
218     }
219     if(m_psPhase.hasValue())
220     {
221         if(m_psPhase.getValue() != PixelShaderPhaseType::PSPHASE_LEGACY)
222         {
223             ss << (underscore ? "_" : "");
224             switch(m_psPhase.getValue())
225             {
226             case PixelShaderPhaseType::PSPHASE_COARSE: ss << "CPS"; break;
227             case PixelShaderPhaseType::PSPHASE_PIXEL: ss << "PS"; break;
228             default: IGC_ASSERT(0); break;
229             }
230         }
231     }
232     if(m_hash.hasValue())
233     {
234 
235         if (m_type.hasValue() && IGC_IS_FLAG_ENABLED(EnableShaderNumbering)) {
236             bool increment = shaderHashMap.insert({ m_hash->asmHash, shaderNum }).second;
237             //Need to serialize access to the shaderNum counter in case different threads need to dump the same shader at once.
238             hashMapLock.lock();
239             if (increment) shaderNum++;
240             hashMapLock.unlock();
241             ss << "_"
242                << shaderHashMap[m_hash->asmHash]
243                << "_";
244         }
245 
246         if (m_hash->asmHash != 0) {
247             ss << (underscore ? "_" : "")
248                 << "asm"
249                 << std::hex
250                 << std::setfill('0')
251                 << std::setw(sizeof(m_hash->asmHash) * CHAR_BIT / 4)
252                 << m_hash->asmHash
253                 << std::dec
254                 << std::setfill(' ');
255         }
256 
257         if (m_hash->nosHash != 0)
258         {
259             ss << "_"
260                << "nos"
261                << std::hex
262                << std::setfill('0')
263                << std::setw(sizeof(m_hash->nosHash) * CHAR_BIT / 4)
264                << m_hash->nosHash
265                << std::dec
266                << std::setfill(' ');
267         }
268 
269         if (m_hash->psoHash != 0)
270         {
271             ss << "_"
272                 << "pso"
273                 << std::hex
274                 << std::setfill('0')
275                 << std::setw(sizeof(m_hash->psoHash) * CHAR_BIT / 4)
276                 << m_hash->psoHash
277                 << std::dec
278                 << std::setfill(' ');
279         }
280 
281         if (m_hash->perShaderPsoHash != 0)
282         {
283             ss << "_"
284                 << "spec"
285                 << std::hex
286                 << std::setfill('0')
287                 << std::setw(sizeof(m_hash->perShaderPsoHash) * CHAR_BIT / 4)
288                 << m_hash->perShaderPsoHash
289                 << std::dec
290                 << std::setfill(' ');
291         }
292 
293         underscore = true;
294     }
295     if(m_pass.hasValue())
296     {
297         if(m_pass->m_index.hasValue())
298         {
299             ss << (underscore ? "_" : "")
300                 << std::setfill('0')
301                 << std::setw(4)
302                 << m_pass->m_index.getValue()
303                 << std::setfill(' ');
304             underscore = true;
305         }
306         ss << (underscore ? "_" : "")
307             << m_pass->m_name;
308         underscore = true;
309     }
310 
311     if (m_cgFlag.hasValue() && m_cgFlag.getValue() != FLAG_CG_ALL_SIMDS)
312     {
313         ss << (underscore ? "_" : "");
314         if (m_cgFlag.getValue() == FLAG_CG_STAGE1_FAST_COMPILE)
315         {
316             ss << "FastStage1";
317         }
318         else if (m_cgFlag.getValue() == FLAG_CG_STAGE1_BEST_PERF)
319         {
320             ss << "BestStage1";
321         }
322         else
323         {
324             IGC_ASSERT(m_cgFlag.getValue() == FLAG_CG_STAGE1_FASTEST_COMPILE);
325             ss << "FastestStage1";
326         }
327 
328         underscore = true;
329     }
330     else if (m_cgFlag.hasValue())
331     {
332         ss << (underscore ? "_" : "");
333         ss << "RestStage2";
334         underscore = true;
335     }
336 
337     if (m_retryId.hasValue())
338     {
339         if (m_retryId.getValue())
340         {
341             ss << "_" << m_retryId.getValue();
342         }
343     }
344     if(m_simdWidth.hasValue())
345     {
346         ss << (underscore ? "_" : "")
347             << "simd"
348             << numLanes(m_simdWidth.getValue());
349         underscore = true;
350     }
351 
352     if(m_ShaderMode.hasValue())
353     {
354         if(m_ShaderMode.getValue() == ShaderDispatchMode::SINGLE_PATCH)
355         {
356             ss << (underscore ? "_" : "")
357                 << "SinglePatch";
358             underscore = true;
359         }
360         if (m_ShaderMode.getValue() == ShaderDispatchMode::DUAL_PATCH)
361         {
362             ss << (underscore ? "_" : "")
363                 << "DualPatch";
364             underscore = true;
365         }
366         if(m_ShaderMode.getValue() == ShaderDispatchMode::EIGHT_PATCH)
367         {
368             ss << (underscore ? "_" : "")
369                 << "EightPatch";
370             underscore = true;
371         }
372     }
373 
374     if(m_postfixStr.hasValue() && !m_postfixStr.getValue().empty())
375     {
376         std::string s = m_postfixStr.getValue();
377         // sanitize the function name
378         std::replace(s.begin(), s.end(), (char)1, '_');
379         std::replace(s.begin(), s.end(), '/', '_');
380         std::replace(s.begin(), s.end(), '\\', '_');
381         std::replace(s.begin(), s.end(), ':', '_');
382         std::replace(s.begin(), s.end(), '*', '_');
383         std::replace(s.begin(), s.end(), '?', '_');
384         std::replace(s.begin(), s.end(), '\"', '_');
385         std::replace(s.begin(), s.end(), '<', '_');
386         std::replace(s.begin(), s.end(), '>', '_');
387         std::replace(s.begin(), s.end(), '|', '_');
388 
389         // vISA does not support string of length >= 255. Truncate if this
390         // exceeds the limit. Note that vISA may append an extension, so relax
391         // it to a random number 240 here. And this assumes postfix string is
392         // the last chunk to compose the dump name before adding the extension.
393         // TODO: The existing WA does not guarantee the uniqueness of the
394         // filename when truncating the postfix. Will need to fix it.
395         const size_t MAX_VISA_STRING_LENGTH = 240;
396         const size_t curLen = static_cast<size_t>(ss.tellp());
397         const size_t extSize =
398             !m_extension.hasValue() ? 0 : 1 + m_extension.getValue().size();
399         if (curLen + 1 + s.size() + extSize > MAX_VISA_STRING_LENGTH)
400         {
401             s.resize(MAX_VISA_STRING_LENGTH - curLen - 1 - extSize);
402         }
403         ss << "_"
404             << s;
405     }
406 
407     if(m_extension.hasValue())
408     {
409         ss << "." << m_extension.getValue();
410     }
411     return ss.str();
412 }
413 
GetKernelName() const414 std::string DumpName::GetKernelName() const
415 {
416     std::string kernelName = "";
417     if (m_postfixStr.hasValue() && !m_postfixStr.getValue().empty())
418     {
419         kernelName = m_postfixStr.getValue();
420     }
421     return kernelName;
422 }
423 
str() const424 std::string DumpName::str() const
425 {
426     return AbsolutePath(IGC::Debug::GetShaderOutputFolder());
427 }
428 
overridePath() const429 std::string DumpName::overridePath() const
430 {
431     return AbsolutePath(IGC::Debug::GetShaderOverridePath());
432 }
433 
RelativePath() const434 std::string DumpName::RelativePath() const
435 {
436     return AbsolutePath("");
437 }
438 
allow() const439 bool DumpName::allow() const
440 {
441     const char* regex = IGC_GET_REGKEYSTRING(ShaderDumpFilter);
442     if (!regex || *regex == '\0')
443         return true;
444 
445     std::regex fileRegex(regex);
446 
447     return std::regex_search(RelativePath(), fileRegex);
448 }
449 
450 namespace {
isText(DumpType type)451     bool isText( DumpType type )
452     {
453         switch ( type )
454         {
455         case DumpType::NOS_TEXT              : return true;
456         case DumpType::CIS_TEXT              : return true;
457         case DumpType::COS_TEXT              : return true;
458         case DumpType::ASM_TEXT              : return true;
459         case DumpType::ASM_BC                : return false;
460         case DumpType::TRANSLATED_IR_TEXT    : return true;
461         case DumpType::TRANSLATED_IR_BC      : return false;
462         case DumpType::PASS_IR_TEXT          : return true;
463         case DumpType::PASS_IR_BC            : return false;
464         case DumpType::OptIR_TEXT            : return true;
465         case DumpType::OptIR_BC              : return false;
466         case DumpType::VISA_TEXT             : return true;
467         case DumpType::VISA_BC               : return false;
468         case DumpType::GENX_ISA_TEXT         : return true;
469         case DumpType::GENX_ISA_BC           : return false;
470         case DumpType::LLVM_OPT_STAT_TEXT    : return true;
471         case DumpType::TIME_STATS_TEXT       : return true;
472         case DumpType::TIME_STATS_CSV        : return true;
473         case DumpType::DBG_MSG_TEXT          : return true;
474         default                              : IGC_ASSERT_MESSAGE(0, "unreachable"); return true;
475         }
476     }
477 
commentPrefix(DumpType type)478     const char* commentPrefix( DumpType type )
479     {
480         IGC_ASSERT_MESSAGE(isText(type), "Only text types are supported");
481         switch ( type )
482         {
483         case DumpType::NOS_TEXT              : return "// ";
484         case DumpType::CIS_TEXT              : return "// ";
485         case DumpType::COS_TEXT              : return "// ";
486         case DumpType::ASM_TEXT              : return "// ";
487         case DumpType::TRANSLATED_IR_TEXT    : return "; ";
488         case DumpType::PASS_IR_TEXT          : return "; ";
489         case DumpType::OptIR_TEXT            : return "; ";
490         case DumpType::VISA_TEXT             : return "/// ";
491         case DumpType::GENX_ISA_TEXT         : return "/// ";
492         case DumpType::LLVM_OPT_STAT_TEXT    : return "";
493         case DumpType::TIME_STATS_TEXT       : return "";
494         case DumpType::DBG_MSG_TEXT          : return "";
495         case DumpType::TIME_STATS_CSV        : IGC_ASSERT_MESSAGE(0, "CSV doesn't have comments"); return "";
496         default                              : IGC_ASSERT_MESSAGE(0, "unreachable"); return "#";
497         }
498     }
499 
isConsolePrintable(DumpType type)500     bool isConsolePrintable( DumpType type )
501     {
502         return isText( type ) && type != DumpType::TIME_STATS_CSV;
503     }
504 }
505 
506 namespace
507 {
508     /// Writes a prefix to the underlying stream upon first write. Forwards to the underlying
509     /// stream on every subsequent write.
510     class PrefixStream
511         : public llvm::raw_ostream
512     {
513     public:
PrefixStream(std::string const & prefix,Colors color,llvm::raw_ostream * pUnder,bool deleteStream)514         PrefixStream( std::string const& prefix, Colors color, llvm::raw_ostream* pUnder, bool deleteStream )
515             : llvm::raw_ostream( true /* unbuffered */ )
516             , m_prefix(prefix)
517             , m_prefixColor(color)
518             , m_pUnder(pUnder)
519             , m_deleteStream(deleteStream)
520             , m_isFirstWrite(true)
521         {
522         }
523 
~PrefixStream()524         virtual ~PrefixStream()
525         {
526             flush();
527             if (m_deleteStream)
528             {
529                 m_pUnder->flush();
530                 delete m_pUnder;
531             }
532         }
533 
current_pos() const534         virtual uint64_t current_pos() const override
535         {
536             return 0;
537         }
538 
changeColor(enum Colors Color,bool Bold=false,bool BG=false)539         virtual raw_ostream& changeColor(enum Colors Color, bool Bold=false, bool BG=false) override
540         {
541             m_pUnder->changeColor(Color,Bold,BG);
542             return *this;
543         }
544 
resetColor()545         virtual raw_ostream& resetColor() override
546         {
547             m_pUnder->resetColor();
548             return *this;
549         }
550 
reverseColor()551         virtual raw_ostream& reverseColor() override
552         {
553             m_pUnder->reverseColor();
554             return *this;
555         }
556 
is_displayed() const557         virtual bool is_displayed() const override
558         {
559             return m_pUnder->is_displayed();
560         }
561 
has_colors() const562         virtual bool has_colors() const override
563         {
564             return m_pUnder->has_colors();
565         }
566 
567     protected:
preferred_buffer_size() const568         virtual size_t preferred_buffer_size() const override
569         {
570             return 0;
571         }
572 
573     private:
write_impl(const char * Ptr,size_t Size)574         void write_impl(const char* Ptr, size_t Size) override
575         {
576             if (m_isFirstWrite)
577             {
578                 ods().changeColor(m_prefixColor, true, false);
579                 *m_pUnder << m_prefix;
580                 ods().resetColor();
581                 m_isFirstWrite = false;
582             }
583             m_pUnder->write(Ptr,Size);
584         }
585 
586     private:
587         const std::string        m_prefix;
588         const Colors             m_prefixColor;
589         llvm::raw_ostream* const m_pUnder;
590         const bool               m_deleteStream;
591         bool                     m_isFirstWrite;
592     };
593 } // anonymous namespace
594 
595 // Note: This constructor is not allowed to hold on to the dumpName reference after it finishes
596 // (In the case where Dump is on the heap and DumpName is on the stack, the reference would go bad
597 // when the calling function returns)
Dump(DumpName const & dumpName,DumpType type)598 Dump::Dump( DumpName const& dumpName, DumpType type )
599     : m_name( dumpName )
600     , m_pStream(std::make_unique<llvm::raw_string_ostream>(m_string)) // buffered stream!
601     , m_pStringStream( nullptr )
602     , m_type(type)
603     , m_ClearFile(true)
604 {
605     m_pStringStream = m_pStream.get();
606     if (isConsolePrintable(m_type))
607     {
608         if (IGC_IS_FLAG_ENABLED(PrintToConsole))
609         {
610             m_pStream->SetUnbuffered();
611             m_pStream.reset(new TeeOutputStream(&ods(), false, m_pStream.release(), true));
612         }
613 
614         std::stringstream ss;
615         ss << commentPrefix(m_type) << "------------------------------------------------\n";
616         ss << commentPrefix(m_type) << dumpName.RelativePath() << "\n";
617         ss << commentPrefix(m_type) << "------------------------------------------------\n";
618         m_pStream.reset(
619             new PrefixStream(
620                 ss.str(),
621                 llvm::raw_ostream::Colors::YELLOW,
622                 m_pStream.release(),
623                 true));
624     }
625 }
626 
flush()627 void Dump::flush()
628 {
629     m_pStringStream->flush();
630     if (m_string.empty() && !m_ClearFile)
631     {
632         return;
633     }
634     std::ios_base::openmode mode = std::ios_base::out;
635     if (m_ClearFile)
636     {
637         m_ClearFile = false;
638     }
639     else
640     {
641         mode |= std::ios_base::app;
642     }
643     if (!isText(m_type))
644         mode |= std::ios_base::binary;
645     std::ofstream asmFile(m_name.str(), mode);
646     asmFile << m_string;
647     asmFile.close();
648     m_string.clear();
649 }
650 
~Dump()651 Dump::~Dump()
652 {
653     flush();
654 }
655 
stream() const656 llvm::raw_ostream& Dump::stream() const
657 {
658     return *m_pStream;
659 }
660 
DumpLLVMIRText(llvm::Module * pModule,const DumpName & dumpName,llvm::AssemblyAnnotationWriter * optionalAnnotationWriter)661 void DumpLLVMIRText(
662     llvm::Module*             pModule,
663     const DumpName&           dumpName,
664     llvm::AssemblyAnnotationWriter*  optionalAnnotationWriter /* = nullptr */)
665 {
666 #if defined(IGC_DEBUG_VARIABLES)
667     if (dumpName.allow())
668     {
669         auto dump = Dump(dumpName, DumpType::PASS_IR_TEXT);
670 
671         IGC::Debug::DumpLock();
672         pModule->print(dump.stream(), optionalAnnotationWriter);
673         IGC::Debug::DumpUnlock();
674     }
675 #endif
676 }
677 
PrintDebugMsgV(const Dump * dump,const char * fmt,va_list ap)678 int PrintDebugMsgV(
679     const Dump* dump,
680     const char* fmt,
681     va_list ap)
682 {
683 #if defined( _DEBUG ) || defined( _INTERNAL )
684     if (dump)
685     {
686         char buf[512];
687         int r;
688         r = vsnprintf(buf, sizeof(buf), fmt, ap);
689         buf[sizeof(buf) - 1] = '\0';
690         dump->stream() << buf;
691         return r;
692     }
693 #endif
694     return 0;
695 }
696 
PrintDebugMsg(const Dump * dump,const char * fmt,...)697 void PrintDebugMsg(
698     const Dump* dump,
699     const char* fmt,
700     ...)
701 {
702 #if defined( _DEBUG ) || defined( _INTERNAL )
703     va_list ap;
704     va_start(ap, fmt);
705     PrintDebugMsgV(dump, fmt, ap);
706     va_end(ap);
707 #endif
708 }
709 
ShaderHashOCL(const UINT * pShaderCode,size_t size)710 ShaderHash ShaderHashOCL(const UINT* pShaderCode, size_t size)
711 {
712     ShaderHash hash;
713     hash.asmHash = iSTD::Hash(reinterpret_cast<const DWORD*>(pShaderCode), int_cast<DWORD>(size));
714     hash.nosHash = 0;
715     return hash;
716 }
717 
ShaderHashOGL(QWORD glslHash,QWORD nosHash)718 ShaderHash ShaderHashOGL(QWORD glslHash, QWORD nosHash)
719 {
720     ShaderHash shaderHash;
721     shaderHash.asmHash = glslHash;
722     shaderHash.nosHash = nosHash;
723     return shaderHash;
724 }
725 
GetDumpName(const IGC::CShader * pProgram,const char * ext)726 std::string GetDumpName(const IGC::CShader* pProgram, const char* ext)
727 {
728     return GetDumpNameObj(pProgram, ext).str();
729 }
730 
GetDumpNameObj(const IGC::CShader * pProgram,const char * ext)731 DumpName GetDumpNameObj(const IGC::CShader* pProgram, const char* ext)
732 {
733     IGC::CodeGenContext* context = pProgram->GetContext();
734     DumpName dumpName =
735         IGC::Debug::DumpName(IGC::Debug::GetShaderOutputName())
736         .Type(context->type)
737         .Hash(context->hash)
738         .StagedInfo(context);
739 
740     if(pProgram->entry->getName() != "entry")
741     {
742         dumpName = dumpName.PostFix(pProgram->entry->getName().str());
743     }
744     if (pProgram->GetShaderType() == ShaderType::PIXEL_SHADER)
745     {
746         const IGC::CPixelShader* psProgram = static_cast<const IGC::CPixelShader*>(pProgram);
747         dumpName = dumpName.PSPhase(psProgram->GetPhase());
748     }
749     else if (pProgram->GetShaderType() == ShaderType::VERTEX_SHADER)
750     {
751         if (context->getModule()->getModuleFlag("IGC::PositionOnlyVertexShader"))
752         {
753             dumpName = dumpName.PostFix("posh");
754         }
755     }
756     dumpName = dumpName.DispatchMode(pProgram->m_ShaderDispatchMode);
757     dumpName = dumpName.SIMDSize(pProgram->m_dispatchSize).Retry(context->m_retryManager.GetRetryId()).Extension(ext);
758 
759     return dumpName;
760 }
761 
GetLLDumpName(IGC::CodeGenContext * pContext,const char * dumpName)762 DumpName GetLLDumpName(IGC::CodeGenContext* pContext, const char* dumpName)
763 {
764     auto name =
765         DumpName(GetShaderOutputName())
766             .Hash(pContext->hash)
767             .Type(pContext->type)
768             .Pass(dumpName)
769             .Retry(pContext->m_retryManager.GetRetryId())
770             .Extension("ll");
771     return name;
772 }
773 
774 } // namespace Debug
775 } // namespace IGC
776