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