1+ /*
2+ ** Copyright (c) 2025 LunarG, Inc.
3+ ** Copyright (c) 2025-2026 Arm Limited and/or its affiliates <open-source-office@arm.com>
4+ **
5+ ** Permission is hereby granted, free of charge, to any person obtaining a
6+ ** copy of this software and associated documentation files (the "Software"),
7+ ** to deal in the Software without restriction, including without limitation
8+ ** the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+ ** and/or sell copies of the Software, and to permit persons to whom the
10+ ** Software is furnished to do so, subject to the following conditions:
11+ **
12+ ** The above copyright notice and this permission notice shall be included in
13+ ** all copies or substantial portions of the Software.
14+ **
15+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+ ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21+ ** DEALINGS IN THE SOFTWARE.
22+ */
23+
24+ #include " graphics/dx12_shader_tool.h"
25+
26+ #include " util/file_path.h"
27+ #include " util/logging.h"
28+ #include " util/platform.h"
29+
30+ GFXRECON_BEGIN_NAMESPACE (gfxrecon)
31+ GFXRECON_BEGIN_NAMESPACE(graphics)
32+
33+ const char* Dx12ShaderTool::ShaderTypeToString(ShaderType type)
34+ {
35+ switch (type)
36+ {
37+ case ShaderType::kVertex :
38+ return " vertex" ;
39+ case ShaderType::kDomain :
40+ return " domain" ;
41+ case ShaderType::kHull :
42+ return " hull" ;
43+ case ShaderType::kGeometry :
44+ return " geometry" ;
45+ case ShaderType::kPixel :
46+ return " pixel" ;
47+ case ShaderType::kCompute :
48+ return " compute" ;
49+ case ShaderType::kStateObjectDxilLibrary :
50+ return " dxil_library" ;
51+ default :
52+ return " unknown" ;
53+ }
54+ }
55+
56+ std::string Dx12ShaderTool::MakePipelineShaderFileName (uint64_t handle_id, ShaderType type)
57+ {
58+ std::string suffix;
59+ switch (type)
60+ {
61+ case ShaderType::kVertex :
62+ suffix = " .vs.cso" ;
63+ break ;
64+ case ShaderType::kPixel :
65+ suffix = " .ps.cso" ;
66+ break ;
67+ case ShaderType::kDomain :
68+ suffix = " .ds.cso" ;
69+ break ;
70+ case ShaderType::kHull :
71+ suffix = " .hs.cso" ;
72+ break ;
73+ case ShaderType::kGeometry :
74+ suffix = " .gs.cso" ;
75+ break ;
76+ case ShaderType::kCompute :
77+ suffix = " .cs.cso" ;
78+ break ;
79+ default :
80+ suffix = " .cso" ;
81+ break ;
82+ }
83+
84+ return " sh" + std::to_string (handle_id) + suffix;
85+ }
86+
87+ std::string Dx12ShaderTool::MakeStateObjectDxilLibraryFileName (uint64_t handle_id, uint32_t subobject_index)
88+ {
89+ return " sh" + std::to_string (handle_id) + " _" + std::to_string (subobject_index) + " .cso" ;
90+ }
91+
92+ bool Dx12ShaderTool::ExtractShaderToDir (const std::string& extract_dir,
93+ const std::string& file_name,
94+ const void * code,
95+ size_t code_size)
96+ {
97+ if ((code == nullptr ) || (code_size == 0 ))
98+ {
99+ return false ;
100+ }
101+
102+ std::string file_path = util::filepath::Join (extract_dir, file_name);
103+
104+ FILE* fp = nullptr ;
105+ auto result = util::platform::FileOpen (&fp, file_path.c_str (), " wb" );
106+ if ((result == 0 ) && (fp != nullptr ))
107+ {
108+ if (!util::platform::FileWrite (code, code_size, fp))
109+ {
110+ GFXRECON_WRITE_CONSOLE (" Error while writing file %s: Could not complete" , file_name.c_str ());
111+ util::platform::FileClose (fp);
112+ return false ;
113+ }
114+ util::platform::FileClose (fp);
115+ return true ;
116+ }
117+
118+ GFXRECON_WRITE_CONSOLE (" Error while writing file %s: Could not open" , file_name.c_str ());
119+ return false ;
120+ }
121+
122+ bool Dx12ShaderTool::ExtractPipelineShaderToDir (
123+ const std::string& extract_dir, uint64_t handle_id, ShaderType type, const void * code, size_t code_size)
124+ {
125+ return ExtractShaderToDir (extract_dir, MakePipelineShaderFileName (handle_id, type), code, code_size);
126+ }
127+
128+ bool Dx12ShaderTool::ExtractStateObjectDxilLibraryToDir (const std::string& extract_dir,
129+ uint64_t state_object_handle_id,
130+ uint32_t subobject_index,
131+ const void * code,
132+ size_t code_size)
133+ {
134+ return ExtractShaderToDir (
135+ extract_dir, MakeStateObjectDxilLibraryFileName (state_object_handle_id, subobject_index), code, code_size);
136+ }
137+
138+ bool Dx12ShaderTool::LoadReplacementShaderFromDir (const std::string& replace_shader_dir,
139+ const std::string& file_name,
140+ std::unique_ptr<char []>& out_code,
141+ size_t & out_size)
142+ {
143+ out_code.reset ();
144+ out_size = 0 ;
145+
146+ if (replace_shader_dir.empty ())
147+ {
148+ return false ;
149+ }
150+
151+ std::string file_path = util::filepath::Join (replace_shader_dir, file_name);
152+ FILE* fp = nullptr ;
153+ int32_t result = util::platform::FileOpen (&fp, file_path.c_str (), " rb" );
154+ if ((result != 0 ) || (fp == nullptr ))
155+ {
156+ return false ;
157+ }
158+
159+ util::platform::FileSeek (fp, 0L , util::platform::FileSeekEnd);
160+ size_t file_size = static_cast <size_t >(util::platform::FileTell (fp));
161+ util::platform::FileSeek (fp, 0L , util::platform::FileSeekSet);
162+ if (file_size == 0 )
163+ {
164+ util::platform::FileClose (fp);
165+ return false ;
166+ }
167+
168+ auto buffer = std::make_unique<char []>(file_size);
169+ util::platform::FileRead (buffer.get (), file_size, fp);
170+ util::platform::FileClose (fp);
171+
172+ out_code = std::move (buffer);
173+ out_size = file_size;
174+ return true ;
175+ }
176+
177+ bool Dx12ShaderTool::LoadReplacementPipelineShaderFromDir (const std::string& replace_shader_dir,
178+ uint64_t handle_id,
179+ ShaderType type,
180+ std::unique_ptr<char []>& out_code,
181+ size_t & out_size)
182+ {
183+ return LoadReplacementShaderFromDir (
184+ replace_shader_dir, MakePipelineShaderFileName (handle_id, type), out_code, out_size);
185+ }
186+
187+ bool Dx12ShaderTool::LoadReplacementStateObjectDxilLibraryFromDir (const std::string& replace_shader_dir,
188+ uint64_t handle_id,
189+ uint32_t subobject_index,
190+ std::unique_ptr<char []>& out_code,
191+ size_t & out_size)
192+ {
193+ return LoadReplacementShaderFromDir (
194+ replace_shader_dir, MakeStateObjectDxilLibraryFileName (handle_id, subobject_index), out_code, out_size);
195+ }
196+
197+ GFXRECON_END_NAMESPACE (graphics)
198+ GFXRECON_END_NAMESPACE(gfxrecon)
0 commit comments