FCT
载入中...
搜索中...
未找到
ShaderGenerator.cpp
浏览该文件的文档.
1
2#include "../FCTAPI.h"
3
4namespace FCT
5{
7 std::vector<TextureElement>& textureElements, std::vector<SamplerElement>& samplerElements)
8 {
9 textureElements.clear();
10 samplerElements.clear();
11 size_t textureCount = resourceLayout.getTextureCount();
12 size_t samplerCount = resourceLayout.getSamplerCount();
13 textureElements.reserve(textureCount);
14 samplerElements.reserve(samplerCount);
15 for (size_t i = 0; i < textureCount; ++i) {
16 textureElements.push_back(resourceLayout.getTexture(i));
17 }
18 for (size_t i = 0; i < samplerCount; ++i) {
19 samplerElements.push_back(resourceLayout.getSampler(i));
20 }
21 }
22
23 std::string ShaderGenerator::generateVertexShader(const std::map<uint32_t, VertexLayout>& vertexLayouts,
24 const PixelLayout& pixelLayout, const std::vector<ConstLayout>& uniformLayouts, RHI::ShaderBinary& binary,
25 ResourceLayout& resourceLayout, const std::string& userCode)
26 {
27 std::map<std::string, uint32_t> locations;
28 std::map<std::string, std::pair<uint32_t, uint32_t>> uniformsLocations;
29 std::map<std::string, std::pair<uint32_t, uint32_t>> constBufferLocations;
30
31 std::vector<TextureElement> texturesElements;
32 std::vector<SamplerElement> samplersElements;
33 ResourceLayoutToElements(resourceLayout, texturesElements, samplersElements);
34
35 std::stringstream ss;
36 ss << generateShaderIn(vertexLayouts, locations);
37 ss << generateShaderOut(pixelLayout);
38 ss << generateConstBuffer(binary,uniformLayouts);
39 ss << generateTexturesAndSamplers(binary,texturesElements, samplersElements);
40 ss << generateVertexMain(vertexLayouts, pixelLayout);
41 ss << userCode;
42
43 binary.location(locations);
44
45 return ss.str();
46 }
47
49 const std::vector<ConstLayout>& uniformLayouts, RHI::ShaderBinary& binary, ResourceLayout& resourceLayout,
50 const std::string& userCode)
51 {
52 std::stringstream ss;
53 std::vector<TextureElement> texturesElements;
54 std::vector<SamplerElement> samplersElements;
55 ResourceLayoutToElements(resourceLayout, texturesElements, samplersElements);
56
57 ss << generateShaderIn(layout);
58 ss << generateShaderOut();
59 ss << generateConstBuffer(binary,uniformLayouts);
60 ss << generateTexturesAndSamplers(binary,texturesElements, samplersElements);
61 ss << generatePixelMain(layout);
62 ss << userCode;
63
64
65 return ss.str();
66 }
67
69 const std::map<uint32_t, VertexLayout>& vertexLayouts,
70 const PixelLayout& pixelLayout)
71 {
72 std::stringstream ss;
73 ss << "//FCT Default User Vertex Main\n";
74 ss << "ShaderOut main(ShaderIn sIn) {\n";
75 ss << " ShaderOut sOut;\n";
76 ss << " \n";
77
78 for (const auto& [slot, layout] : vertexLayouts) {
79 for (size_t i = 0; i < layout.getElementCount(); i++) {
80 const VertexElement& inElement = layout.getElement(i);
81 const char* semantic = inElement.getSemantic();
82
83 if (inElement.getType() != VtxType::Custom) {
84 auto element = pixelLayout.getElementByType(inElement.getType());
85 if (element) {
86 ss << " sOut." << element->getSemantic() << " = sIn." << semantic << ";\n";
87 }
88 } else {
89 auto element = pixelLayout.getElementBySemantic(semantic);
90 if (element) {
91 ss << " sOut." << element->getSemantic() << " = sIn." << semantic << ";\n";
92 } else {
93 ss << " //属性 " << semantic << " 在自动生成时被忽略 \n";
94 }
95 }
96 }
97 }
98
99 ss << " \n";
100 ss << " return sOut;\n";
101 ss << "}\n";
102
103 return ss.str();
104 }
105
107 {
108 std::stringstream ss;
109 ss << "//FCT Default User Pixel Main\n";
110 ss << "ShaderOut main(ShaderIn sIn) {\n";
111 ss << " ShaderOut sOut;\n";
112
113 auto colorElement = pixelLayout.getElementByType(VtxType::Color4f);
114 if (!colorElement) {
115 colorElement = pixelLayout.getElementByType(VtxType::Color3f);
116 }
117
118 if (colorElement) {
119 const char* semantic = colorElement->getSemantic();
120 VtxType type = colorElement->getType();
121
122 if (type == VtxType::Color4f) {
123 ss << " sOut.target0 = sIn." << semantic << ";\n";
124 } else if (type == VtxType::Color3f) {
125 ss << " sOut.target0 = float4(sIn." << semantic << ", 1.0f);\n";
126 } else {
127 std::string typeStr = FormatToShaderType(colorElement->getFormat());
128 if (typeStr == "float4") {
129 ss << " sOut.target0 = sIn." << semantic << ";\n";
130 } else if (typeStr == "float3") {
131 ss << " sOut.target0 = float4(sIn." << semantic << ", 1.0f);\n";
132 } else if (typeStr == "float2") {
133 ss << " sOut.target0 = float4(sIn." << semantic << ", 0.0f, 1.0f);\n";
134 } else if (typeStr == "float") {
135 ss << " sOut.target0 = float4(sIn." << semantic << ", 0.0f, 0.0f, 1.0f);\n";
136 } else {
137 ss << " sOut.target0 = float4(1.0f, 1.0f, 1.0f, 1.0f);\n";
138 }
139 }
140 } else {
141 ss << " // 没有找到颜色属性\n";
142 ss << " sOut.target0 = float4(1.0f, 1.0f, 1.0f, 1.0f);\n";
143 }
144
145 ss << " sOut.target1 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
146 ss << " sOut.target2 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
147 ss << " sOut.target3 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
148 ss << " sOut.target4 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
149 ss << " sOut.target5 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
150 ss << " sOut.target6 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
151 ss << " sOut.target7 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n";
152
153 ss << " return sOut;\n";
154 ss << "}\n";
155
156 return ss.str();
157 }
158
160 const std::map<uint32_t, VertexLayout>& layouts,
161 std::map<std::string, uint32_t>& locationMap)
162 {
163 std::stringstream ss;
164 ss << "//FCT Input Structure\n";
165 ss << "struct ShaderIn {\n";
166
167 // 生成系统值
168 ss << " uint vertexID : SV_VertexID;\n";
169 ss << " uint instanceID : SV_InstanceID;\n\n";
170
171 // 检查语义冲突
172 std::set<std::string> usedSemantics;
173 for (const auto& [slot, layout] : layouts) {
174 for (size_t i = 0; i < layout.getElementCount(); i++) {
175 const VertexElement& element = layout.getElement(i);
176 const char* semantic = element.getSemantic();
177
178 if (usedSemantics.find(semantic) != usedSemantics.end()) {
179 throw std::runtime_error(std::string("Semantic conflict detected: ") + semantic);
180 }
181
182 usedSemantics.insert(semantic);
183 }
184 }
185
186 int nextLocation = 0;
187
188 for (const auto& [slot, layout] : layouts) {
189 ss << " // Vertex buffer slot " << slot << "\n";
190
191 for (size_t i = 0; i < layout.getElementCount(); i++) {
192 const VertexElement& element = layout.getElement(i);
193 std::string typeStr = FormatToShaderType(element.getFormat());
194 const char* semantic = element.getSemantic();
195
196 locationMap[semantic] = nextLocation;
197 ss << " [[vk::location(" << nextLocation << ")]] ";
198 ss << typeStr << " " << semantic << " : " << semantic << ";\n";
199
200 nextLocation++;
201 }
202
203 if (slot != layouts.rbegin()->first) {
204 ss << "\n";
205 }
206 }
207
208 ss << "};\n";
209 return ss.str();
210 }
211
213 {
214 std::stringstream ss;
215 ss << "//FCT Input Structure\n";
216 ss << "struct ShaderIn {\n";
217
218 ss << " float4 position : SV_POSITION;\n";
219 ss << generateFromPixelLayout(layout);
220 ss << "};\n";
221
222 return ss.str();
223 }
224
226 {
227 std::stringstream ss;
228 ss << "//FCT Output Structure\n";
229 ss << "struct ShaderOut {\n";
230
231 ss << " float4 outPosition : SV_POSITION; \n";
232 ss << generateFromPixelLayout(layout);
233 ss << "};\n";
234
235 return ss.str();
236 }
237
239 {
240 std::stringstream ss;
241 ss << "//FCT Output Structure\n";
242 ss << "struct ShaderOut {\n";
243 ss << " float4 target0 : SV_Target0;\n";
244 ss << " float4 target1 : SV_Target1;\n";
245 ss << " float4 target2 : SV_Target2;\n";
246 ss << " float4 target3 : SV_Target3;\n";
247 ss << " float4 target4 : SV_Target4;\n";
248 ss << " float4 target5 : SV_Target5;\n";
249 ss << " float4 target6 : SV_Target6;\n";
250 ss << " float4 target7 : SV_Target7;\n";
251 ss << "};\n";
252
253 return ss.str();
254 }
255
257 {
258 std::stringstream ss;
259 ss << " //PixelLayout\n";
260
261 for (size_t i = 0; i < layout.getElementCount(); i++) {
262 const VertexElement& element = layout.getElement(i);
263 std::string typeStr = FormatToShaderType(element.getFormat());
264 const char* semantic = element.getSemantic();
265
266 ss << " [[vk::location(" << i << ")]] ";
267 ss << typeStr << " " << semantic << " : " << semantic << ";\n";
268 }
269
270 return ss.str();
271 }
272
274 const std::map<uint32_t, VertexLayout>& vertexLayouts,
275 const PixelLayout& pixelLayout)
276 {
277 std::stringstream ss;
278 ss << "ShaderOut main(ShaderIn);\n";
279 ss << "ShaderOut FCTEntry(ShaderIn sIn)\n";
280 ss << " {\n";
281 ss << " ShaderOut sOut;\n";
282 ss << " \n";
283
284 bool hasPosition = false;
285 const VertexElement* posElement = nullptr;
286
287 posElement = pixelLayout.getElementByType(VtxType::Position4f);
288 if (posElement) {
289 hasPosition = true;
290 }
291
292 else if ((posElement = pixelLayout.getElementByType(VtxType::Position3f))) {
293 hasPosition = true;
294 }
295
296 else if ((posElement = pixelLayout.getElementByType(VtxType::Position2f))) {
297 hasPosition = true;
298 }
299
300 ss << " sOut = main(sIn);\n";
301
302 if (hasPosition && posElement) {
303 const char* semantic = posElement->getSemantic();
304 VtxType type = posElement->getType();
305
306 if (type == VtxType::Position4f) {
307 ss << " sOut.outPosition = sOut." << semantic << ";\n";
308 } else if (type == VtxType::Position3f) {
309 ss << " sOut.outPosition = float4(sOut." << semantic << ", 1.0f);\n";
310 } else if (type == VtxType::Position2f) {
311 ss << " sOut.outPosition = float4(sOut." << semantic << ", 0.0f, 1.0f);\n";
312 }
313 } else {
314 ss << " sOut.outPosition = float4(0.0f, 0.0f, 0.0f, 1.0f);\n";
315 }
316
317 ss << " \n";
318 ss << " return sOut;\n";
319 ss << "}\n";
320
321 return ss.str();
322 }
323
324 std::string ShaderGenerator::generatePixelMain(const PixelLayout& pixelLayout)
325 {
326 std::stringstream ss;
327 ss << "ShaderOut main(ShaderIn sIn);\n";
328 ss << "ShaderOut FCTEntry(ShaderIn sIn) {\n";
329 ss << " ShaderOut sOut;\n";
330 ss << " \n";
331 ss << " sOut = main(sIn);\n";
332 ss << " \n";
333 ss << " return sOut;\n";
334 ss << "}\n";
335
336 return ss.str();
337 }
338
339 std::pair<uint32_t, uint32_t> ShaderGenerator::allocateTextureBinding(const TextureElement& texture) {
340 UpdateFrequency frequency = texture.getUpdateFrequency();
341 ShaderStages stages = texture.getShaderStages();
342
343 uint32_t set;
344 switch (frequency) {
346 set = 0;
347 break;
349 set = 1;
350 break;
352 set = 2;
353 break;
355 set = 3;
356 break;
357 default:
358 set = 0;
359 break;
360 }
361
362 uint32_t binding;
363 bool found = false;
364
365 for (const auto& [storedTexture, setBinding] : m_textureSetBindings) {
366 if (storedTexture == texture) {
367 set = setBinding.first;
368 binding = setBinding.second;
369 found = true;
370 break;
371 }
372 }
373
374 if (!found) {
375 binding = m_frequencyBindingCount[frequency]++;
376 m_textureSetBindings.push_back({texture, {set, binding}});
377 }
378
379 return {set, binding};
380 }
381 std::pair<uint32_t, uint32_t> ShaderGenerator::allocateSamplerBinding(const SamplerElement& sampler) {
382 UpdateFrequency frequency = sampler.getUpdateFrequency();
383 ShaderStages stages = sampler.getShaderStages();
384
385 uint32_t set;
386 switch (frequency) {
388 set = 0;
389 break;
391 set = 1;
392 break;
394 set = 2;
395 break;
397 set = 3;
398 break;
399 default:
400 set = 0;
401 break;
402 }
403
404 uint32_t binding;
405 bool found = false;
406
407 for (const auto& [storedSampler, setBinding] : m_samplerSetBindings) {
408 if (storedSampler == sampler) {
409 set = setBinding.first;
410 binding = setBinding.second;
411 found = true;
412 break;
413 }
414 }
415
416 if (!found) {
417 binding = m_frequencyBindingCount[frequency]++;
418 m_samplerSetBindings.push_back({sampler, {set, binding}});
419 }
420
421 return {set, binding};
422 }
424 const std::vector<TextureElement>& textures, const std::vector<SamplerElement>& samplers)
425 {
426 std::stringstream ss;
427 ss << "//FCT Textures and Samplers\n";
428
429 for (const auto& texture : textures) {
430 auto [set, binding] = allocateTextureBinding(texture);
431
432 binary.addTextureLocation(texture, set, binding);
433
434 std::string textureType;
435 switch (texture.getType()) {
437 textureType = "Texture2D";
438 break;
440 textureType = "Texture3D";
441 break;
443 textureType = "TextureCube";
444 break;
446 textureType = "Texture2DArray";
447 break;
449 textureType = "Texture2D";
450 break;
451 default:
452 textureType = "Texture2D";
453 break;
454 }
455
456 ss << "[[vk::binding(" << binding << ", " << set << ")]] ";
457 ss << textureType << "<float4> " << texture.getName()
458 << " : register(t" << binding << ", space" << set << ");\n";
459 }
460
461 ss << "\n";
462
463 for (const auto& sampler : samplers) {
464 auto [set, binding] = allocateSamplerBinding(sampler);
465
466 binary.addSamplerLocation(sampler, set, binding);
467
468 ss << "[[vk::binding(" << binding << ", " << set << ")]] ";
469 ss << "SamplerState " << sampler.getName()
470 << " : register(s" << binding << ", space" << set << ");\n";
471 }
472
473 return ss.str();
474 }
475
477 {
478 switch (type) {
483 case ConstType::Mat4:
484 return "float4x4";
485 case ConstType::Mat3:
486 return "float3x3";
487 case ConstType::Vec4:
488 return "float4";
489 case ConstType::Vec3:
490 return "float3";
491 case ConstType::Vec2:
492 return "float2";
493 case ConstType::Float:
494 return "float";
495 case ConstType::Int:
496 return "int";
497 case ConstType::Bool:
498 return "bool";
502 default:
503 return "float4";
504 }
505 }
507 const std::vector<ConstLayout>& uniforms)
508 {
509 std::stringstream ss;
510 ss << "//FCT Constant Buffers\n";
511
512 for (const auto& layout : uniforms) {
513 UpdateFrequency frequency = layout.getUpdateFrequency();
514
515 uint32_t set;
516 switch (frequency) {
518 set = 0;
519 break;
521 set = 1;
522 break;
524 set = 2;
525 break;
527 set = 3;
528 break;
529 default:
530 set = 0;
531 break;
532 }
533
534 uint32_t binding;
535 bool found = false;
536
537 for (const auto& [storedLayout, setBinding] : m_layoutSetBindings) {
538 if (storedLayout == layout) {
539 set = setBinding.first;
540 binding = setBinding.second;
541 found = true;
542 break;
543 }
544 }
545
546 if (!found) {
547 binding = m_frequencyBindingCount[frequency]++;
548
549 m_layoutSetBindings.push_back({layout, {set, binding}});
550 }
551
552 binary.addConstBufferLocation(layout, set, binding);
553
554 ss << "[[vk::binding(" << binding << ", " << set << ")]] ";
555 ss << "cbuffer " << layout.getName() << " : register(b" << binding << ", space" << set << ") {\n";
556
557 for (size_t i = 0; i < layout.getElementCount(); i++) {
558 const ConstElement& element = layout.getElement(i);
559 std::string typeStr = uniformTypeToShaderType(element.getType());
560 const char* name = element.getName();
561 if (element.isArray()) {
562 size_t arraySize = element.getElementCount();
563 ss << " " << typeStr << " " << name << "[" << arraySize << "];\n";
564 } else {
565 ss << " " << typeStr << " " << name << ";\n";
566 }
567 }
568
569 ss << "};\n\n";
570 }
571
572 return ss.str();
573 }
574}
constexpr bool isArray() const noexcept
constexpr size_t getElementCount() const noexcept
constexpr ConstType getType() const noexcept
constexpr const char * getName() const noexcept
constexpr const VertexElement * getElementByType(VtxType type) const noexcept
constexpr size_t getElementCount() const noexcept
constexpr const VertexElement & getElement(size_t index) const noexcept
constexpr const VertexElement * getElementBySemantic(const char *semantic) const noexcept
void location(std::map< std::string, uint32_t > locations)
void addConstBufferLocation(ConstLayout layout, uint32_t set, uint32_t location)
void addTextureLocation(TextureElement texture, uint32_t set, uint32_t binding)
void addSamplerLocation(SamplerElement sampler, uint32_t set, uint32_t binding)
constexpr size_t getSamplerCount() const noexcept
constexpr const TextureElement & getTexture(size_t index) const noexcept
constexpr size_t getTextureCount() const noexcept
constexpr const SamplerElement & getSampler(size_t index) const noexcept
constexpr ShaderStages getShaderStages() const noexcept
constexpr UpdateFrequency getUpdateFrequency() const noexcept
std::string generateTexturesAndSamplers(RHI::ShaderBinary &binary, const std::vector< TextureElement > &textures, const std::vector< SamplerElement > &samplers)
std::string generateVertexShader(const std::map< uint32_t, VertexLayout > &vertexLayouts, const PixelLayout &pixelLayout, const std::vector< ConstLayout > &uniformLayouts, RHI::ShaderBinary &binary, ResourceLayout &resourceLayout, const std::string &userCode)
std::pair< uint32_t, uint32_t > allocateTextureBinding(const TextureElement &texture)
std::string generateShaderIn(const std::map< uint32_t, VertexLayout > &layouts, std::map< std::string, uint32_t > &locationMap)
std::string uniformTypeToShaderType(ConstType type)
std::vector< std::pair< SamplerElement, std::pair< uint32_t, uint32_t > > > m_samplerSetBindings
void ResourceLayoutToElements(ResourceLayout &resourceLayout, std::vector< TextureElement > &textureElements, std::vector< SamplerElement > &samplerElements)
std::vector< std::pair< ConstLayout, std::pair< uint32_t, uint32_t > > > m_layoutSetBindings
std::string generateDefaultPixelMain(const PixelLayout &pixelLayout)
std::string generateDefaultVertexMain(const std::map< uint32_t, VertexLayout > &vertexLayouts, const PixelLayout &pixelLayout)
std::string generatePixelShader(const PixelLayout &layout, const std::vector< ConstLayout > &uniformLayouts, RHI::ShaderBinary &binary, ResourceLayout &resourceLayout, const std::string &userCode)
std::pair< uint32_t, uint32_t > allocateSamplerBinding(const SamplerElement &sampler)
std::string generateVertexMain(const std::map< uint32_t, VertexLayout > &vertexLayouts, const PixelLayout &pixelLayout)
std::string generateConstBuffer(RHI::ShaderBinary &binary, const std::vector< ConstLayout > &uniforms)
std::string generatePixelMain(const PixelLayout &pixelLayout)
std::vector< std::pair< TextureElement, std::pair< uint32_t, uint32_t > > > m_textureSetBindings
std::string generateFromPixelLayout(const PixelLayout &layout)
std::unordered_map< UpdateFrequency, uint32_t > m_frequencyBindingCount
constexpr ShaderStages getShaderStages() const noexcept
constexpr UpdateFrequency getUpdateFrequency() const noexcept
constexpr VtxType getType() const noexcept
constexpr Format getFormat() const noexcept
constexpr const char * getSemantic() const noexcept
UpdateFrequency
constexpr const char * FormatToShaderType(Format format) noexcept