1#include "ShaderBuilder.h"
3#include "Utilities/Strings.h"
4#include "Utilities/Preprocessor.h"
5#include "ResourceStore.h"
6#include "Renderer/EnginePermutations.h"
7#include "Rendering/IGraphicsDevice.h"
9#include "Foundation/Logging/Logger.h"
19 constexpr size_t InitialBufferCapasity = 4096u;
21 constexpr std::array semanticNames
34 std::string_view getSemanticName(
size_t semantic_ind) {
35 std::string_view name;
36 if (semantic_ind < semanticNames.size()) {
37 name = semanticNames[semantic_ind];
45 enum ShaderInterface { None = 0, VertexIn = 1, VertexOut = 2, FragmentIn = 4, FragmentOut = 8 };
47 struct BuiltinAttributeDescription {
48 std::string builtinName;
50 ShaderInterface stage = ShaderInterface::None;
53 struct BuiltinAttributes {
54 ShaderInterfaceMemberDefinition::SemanticName semanticName;
55 BuiltinAttributeDescription desc;
58 const std::array<BuiltinAttributes, 5> builtinAttributes{
59 BuiltinAttributes{ShaderInterfaceMemberDefinition::SemanticName::SV_InstanceID, {
"instance_index", MaterialDataType::UInt, ShaderInterface::VertexIn}},
60 BuiltinAttributes{ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID, {
"vertex_index", MaterialDataType::UInt, ShaderInterface::VertexIn}},
61 BuiltinAttributes{ShaderInterfaceMemberDefinition::SemanticName::Position, {
"position", MaterialDataType::Float4, ShaderInterface(ShaderInterface::VertexOut | ShaderInterface::FragmentIn)}},
62 BuiltinAttributes{ShaderInterfaceMemberDefinition::SemanticName::SV_IsFrontFace, {
"front_facing", MaterialDataType::Bool, ShaderInterface::FragmentIn}},
63 BuiltinAttributes{ShaderInterfaceMemberDefinition::SemanticName::SV_VFace, {
"front_facing", MaterialDataType::Bool, ShaderInterface::FragmentIn}},
66 struct BuiltinDataType {
68 BuiltinAttributeDescription desc;
71 const std::array builtinDataTypes {
72 BuiltinDataType{MaterialDataType::SV_InstanceID, {
"instance_index", MaterialDataType::UInt, ShaderInterface::VertexIn} },
73 BuiltinDataType{MaterialDataType::Position, {
"position", MaterialDataType::Float4, ShaderInterface(ShaderInterface::VertexOut | ShaderInterface::FragmentIn)}},
75 BuiltinDataType{MaterialDataType::Position, {
"position", MaterialDataType::Float4, ShaderInterface::FragmentIn} },
76 BuiltinDataType{MaterialDataType::SV_IsFrontFace, {
"front_facing", MaterialDataType::Bool, ShaderInterface::FragmentIn} },
77 BuiltinDataType{MaterialDataType::VFACE, {
"front_facing", MaterialDataType::Bool, ShaderInterface::FragmentIn}},
80 const std::array requiredEngineBuffers = {
86 const std::array optionalEngineBuffers = {
90 struct EngineTexture {
93 bool isDepthTexture =
false;
96 const std::array engineTextures = {
97 EngineTexture{.name =
"environmentSky", .dimensions = TextureDimensions::TexureCube},
98 EngineTexture{.name =
"environmentRadiance", .dimensions = TextureDimensions::TexureCube},
99 EngineTexture{.name =
"environmentIrradiance", .dimensions = TextureDimensions::TexureCube},
100 EngineTexture{.name =
"ambientIrradiance", .dimensions = TextureDimensions::TexureCube},
101 EngineTexture{.name =
"brdfLUT", .dimensions = TextureDimensions::Texture2D},
102 EngineTexture{.name =
"cascadedShadowMap", .dimensions = TextureDimensions::Texture2DArray, .isDepthTexture =
true},
103 EngineTexture{.name =
"cubeShadowMap", .dimensions = TextureDimensions::TexureCube, .isDepthTexture =
true},
106 struct WebGPULocation {
110 bool isDepthTexture =
false;
111 WebGPULocation(
size_t location,
const std::string &name,
Cogs::Core::TextureDimensions dimensions = Cogs::Core::TextureDimensions::Texture2D,
bool isDepthTexture =
false) :
112 location(location), name(name), dimensions(dimensions), isDepthTexture(isDepthTexture) { }
113 WebGPULocation() =
default;
117 using WebGPUBindingGroup = std::vector<WebGPULocation>;
118 using WebGPUBindingGroupVector = std::vector<WebGPUBindingGroup>;
121 bool hasBinding(
const WebGPUBindingGroupVector& bindingGroups, std::string_view name) {
122 for (
const WebGPUBindingGroup& bindings : bindingGroups) {
123 for (
const WebGPULocation& location : bindings) {
124 if (location.name == name) {
132 void createBufferBinding(WebGPUBindingGroupVector& bindingGroups,
const MaterialDefinition& materialDefinition) {
133 if (bindingGroups.empty()) {
134 bindingGroups.emplace_back();
136 WebGPUBindingGroup& locations = bindingGroups[0];
137 locations.emplace_back(0,
"BLOCKED");
138 for (
auto& buffer : requiredEngineBuffers) {
139 WebGPULocation loc(locations.size(), buffer);
140 locations.push_back(loc);
143 for (
auto& buffer : optionalEngineBuffers) {
144 locations.emplace_back(locations.size(), buffer);
148 for (
auto& buffer : materialDefinition.properties.buffers) {
149 if (std::find(std::begin(requiredEngineBuffers), std::end(requiredEngineBuffers), buffer.name) == std::end(requiredEngineBuffers)) {
150 if (!hasBinding(bindingGroups, buffer.name)) {
151 locations.emplace_back(locations.size(), buffer.name);
158 std::string convertDefinesToConstExpressions(
const std::string& s) {
159 std::map<std::string, std::string> addedDefines;
161 result.reserve(s.size());
163 std::istringstream iss(s);
165 std::regex e1(
"^\\s*#define\\s+([^\\s]+)\\s+([^\\s]+)");
166 std::regex e2(
"^\\s*#define\\s+([^\\s]+)\\s*$");
167 std::string identifier;
168 std::string replacement;
169 for (std::string line; std::getline(iss, line); )
175 if (std::regex_search(line, match, e1))
177 identifier += match.str(1);
178 replacement += match.str(2);
180 else if (std::regex_search(line, match, e2)) {
181 identifier += match.str(1);
184 if (identifier.empty()) {
185 result += line +
"\n";
188 auto it = addedDefines.find(identifier);
189 if (it != addedDefines.end()) {
190 if (replacement != (*it).second) {
191 LOG_WARNING(logger,
"Shader generation with inconsistent preprosessor define %s set to %s conflicts with previous define %s.", identifier.c_str(), replacement.c_str(), (*it).second.c_str());
195 result +=
"const " + identifier +
" = " + replacement +
";\n";
196 addedDefines.try_emplace(identifier, replacement);
201 void addInclude(std::string& content, std::string_view prefix, std::string_view path)
203 content.append(
"#include \"");
204 content.append(prefix);
205 content.append(path);
206 content.append(
"\"\n");
209 void changeSuffix(std::string& dst, std::string_view from, std::string_view to)
211 if (dst.ends_with(from)) {
212 dst.replace(dst.size() - from.length(), from.length(), to);
220 case MaterialDataType::Float:
return "f32 ";
break;
221 case MaterialDataType::Float2:
return "vec2f ";
break;
222 case MaterialDataType::Float3:
return "vec3f ";
break;
223 case MaterialDataType::Float4:
return "vec4f ";
break;
224 case MaterialDataType::Float4x4:
return "mat4x4f ";
break;
225 case MaterialDataType::Int:
return "i32 ";
break;
226 case MaterialDataType::Int2:
return "vec4i ";
break;
227 case MaterialDataType::Int3:
return "vec3i ";
break;
228 case MaterialDataType::Int4:
return "vec4i ";
break;
229 case MaterialDataType::UInt:
return "u32 ";
break;
230 case MaterialDataType::UInt2:
return "vec4u ";
break;
231 case MaterialDataType::UInt3:
return "vec3u ";
break;
232 case MaterialDataType::UInt4:
return "vec4u ";
break;
233 case MaterialDataType::Bool:
return "bool ";
break;
234 case MaterialDataType::SV_IsFrontFace:
return "bool ";
break;
235 case MaterialDataType::VFACE:
return "f32 ";
break;
236 case MaterialDataType::Position:
return "vec4f ";
break;
238 LOG_ERROR(logger,
"Unsupported attribute type %d",
int(type));
244 void createTextureBindings(WebGPUBindingGroupVector& bindingGroups,
const MaterialDefinition& materialDefinition) {
245 if (bindingGroups.empty()) {
246 bindingGroups.emplace_back();
248 WebGPUBindingGroup& locations = bindingGroups[0];
250 for (
auto& texture : materialDefinition.properties.textures) {
251 if (!hasBinding(bindingGroups, texture.name)) {
252 std::string name = texture.name;
253 locations.emplace_back(locations.size(), name, texture.dimensions);
254 locations.emplace_back(locations.size(), name +
"Sampler", texture.dimensions);
259 void createEngineTextureBindings(WebGPUBindingGroupVector& bindingGroups) {
260 if (bindingGroups.empty()) {
261 bindingGroups.emplace_back();
263 WebGPUBindingGroup& locations = bindingGroups[0];
265 for (
auto& tex : engineTextures) {
266 if (!hasBinding(bindingGroups, tex.name)) {
267 std::string name = tex.name;
268 locations.emplace_back(locations.size(), name, tex.dimensions, tex.isDepthTexture);
269 locations.emplace_back(locations.size(), name +
"Sampler", tex.dimensions, tex.isDepthTexture);
274 void addEffectDefinesAndStuff(std::string& output,
const std::vector<std::pair<std::string, std::string>>& definitions, uint32_t multiViewCount) {
275 if (multiViewCount) {
276 std::string multiViewCountString = std::to_string(multiViewCount);
277 output.append(
"#extension GL_OVR_multiview : require\nlayout(num_views=");
278 output.append(multiViewCountString);
279 output.append(
") in;\n");
280 output.append(
"#define COGS_MULTIVIEW ");
281 output.append(multiViewCountString);
285 std::unordered_set<std::string> addedDefines;
287 for (
const std::pair<std::string, std::string>& define : definitions) {
288 if (addedDefines.contains(define.first)) {
291 output.append(
"#define ");
292 output.append(define.first);
294 output.append(define.second);
296 addedDefines.insert(define.first);
302 BuiltinAttributeDescription desc;
303 desc.stage = ShaderInterface::None;
304 for (
const auto& builtin : builtinDataTypes)
306 if (builtin.type == attribute.type) {
310 for (
const auto& attr : builtinAttributes) {
311 if (attr.semanticName == attribute.semantic.name) {
318 void addInterfaceStruct(std::string& defines, std::string& source, std::string_view name,
const ShaderInterfaceDefinition& iface, ShaderInterface shaderInterface)
321 source.append(
"struct ");
323 source.append(
" {\n");
325 if (shaderInterface & ShaderInterface::VertexOut) {
326 source.append(
" @builtin(position) Position: vec4f,\n");
328 for (
const auto& attribute : iface.members) {
329 BuiltinAttributeDescription builtinAttributeDescription = getBuiltinAttributeDescription(attribute);
330 if (shaderInterface & ShaderInterface::VertexOut &&
331 (builtinAttributeDescription.stage & ShaderInterface::FragmentIn) != 0) {
334 if (shaderInterface & ShaderInterface::FragmentIn && attribute.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::None && attribute.type == MaterialDataType::Position) {
338 if ((builtinAttributeDescription.stage & shaderInterface) != 0) {
339 source.append(
" @builtin(" + builtinAttributeDescription.builtinName +
") ");
340 source.append(attribute.name);
341 source.append(
" : ");
342 source.append(attributeVaryingType(builtinAttributeDescription.type));
343 source.append(
",\n");
346 if (shaderInterface & ShaderInterface::VertexIn) {
347 defines.append(
"#define ");
348 size_t nameInd = size_t (attribute.semantic.name) - 1;
349 std::string_view semanticName = getSemanticName(nameInd);
350 if (!semanticName.empty()) {
351 std::string defineName;
352 defineName.append(semanticName);
353 defineName.append(std::to_string(attribute.semantic.slot) +
"_LOC");
354 defines.append(defineName +
" " + std::to_string(next_loc++) +
"\n");
355 source.append(
" @location(" + defineName +
") ");
359 source.append(
" @location(" + std::to_string(next_loc++) +
") ");
361 source.append(attribute.name);
362 source.append(
" : ");
363 if (attribute.type == MaterialDataType::UInt4) {
364 source.append(
"vec4u");
367 source.append(attributeVaryingType(attribute.type));
369 source.append(
",\n");
372 source.append(
"};\n\n");
377 shaderSource.append(
"fn create");
378 shaderSource.append(name);
379 shaderSource.append(
"() -> ");
380 shaderSource.append(name);
381 shaderSource.append(
" {\n");
382 shaderSource.append(
" var t : ");
383 shaderSource.append(name);
384 shaderSource.append(
";\n");
385 for (
const auto& attribute : iface.members) {
386 const char* initializer =
nullptr;
387 switch (attribute.type) {
388 case MaterialDataType::Float: initializer =
"0.0;\n";
break;
389 case MaterialDataType::Float2: initializer =
"vec2f(0);\n";
break;
390 case MaterialDataType::Float3: initializer =
"vec3f(0);\n";
break;
391 case MaterialDataType::Float4: initializer =
"vec4f(0);\n";
break;
392 case MaterialDataType::Float4x4: initializer =
"mat4x4f(0);\n";
break;
397 shaderSource.append(
" t.");
398 shaderSource.append(attribute.name);
399 shaderSource.append(
" = ");
400 shaderSource.append(initializer);
403 shaderSource.append(
" return t;\n}\n\n");
406 void addUniform(std::string& shaderSource, WebGPUBindingGroupVector& bindingGroups, std::string_view name, std::string_view type,
bool useTemplate =
false) {
407 WebGPUBindingGroup& bindings = bindingGroups[0];
408 WebGPULocation location;
409 for (
const WebGPULocation& curr_location : bindings) {
410 if (curr_location.name == name) {
411 location = curr_location;
415 if (location.name != name) {
416 LOG_ERROR(logger,
"Texture not in bindgroup %s", std::string(name).c_str());
419 shaderSource.append(
"@group(");
420 shaderSource.append(std::to_string(0));
421 shaderSource.append(
") @binding(");
422 shaderSource.append(std::to_string(location.location));
423 shaderSource.append(
") var");
425 shaderSource.append(
"<uniform>");
427 shaderSource.append(
" ");
428 shaderSource.append(name);
429 shaderSource.append(
" : ");
430 shaderSource.append(type);
431 shaderSource.append(
";\n");
434 void addUniformBuffer(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen,
const ConstantBufferDefinition& definition, WebGPUBindingGroupVector& bindingGroups)
436 if (!identifiersSeen.contains(Strings::add(definition.name))) {
439 if (definition.values.empty())
return;
440 shaderSource.append(
"struct ");
441 shaderSource.append(definition.name);
442 shaderSource.append(
"_t {\n");
444 shaderSource.append(member.name);
445 shaderSource.append(
" : ");
447 switch (member.type) {
448 case MaterialDataType::Float: shaderSource.append(
"f32");
break;
449 case MaterialDataType::Float2: shaderSource.append(
"vec2f");
break;
450 case MaterialDataType::Float3: shaderSource.append(
"vec3f");
break;
451 case MaterialDataType::Float4: shaderSource.append(
"vec4f");
break;
452 case MaterialDataType::Float4x4: shaderSource.append(
"mat4x4f");
break;
453 case MaterialDataType::Int: shaderSource.append(
"i32");
break;
454 case MaterialDataType::Int2: shaderSource.append(
"vec2i");
break;
455 case MaterialDataType::Int3: shaderSource.append(
"vec3i");
break;
456 case MaterialDataType::Int4: shaderSource.append(
"vec4i");
break;
457 case MaterialDataType::UInt: shaderSource.append(
"u32");
break;
458 case MaterialDataType::UInt2: shaderSource.append(
"vec2u");
break;
459 case MaterialDataType::UInt3: shaderSource.append(
"vec3u");
break;
460 case MaterialDataType::UInt4: shaderSource.append(
"vec4u");
break;
461 case MaterialDataType::Bool: shaderSource.append(
"u32");
break;
463 shaderSource.append(
"<invalid type>");
466 if (member.type == MaterialDataType::Float4Array || member.type == MaterialDataType::Float4x4Array) {
467 assert(member.dimension !=
static_cast<size_t>(-1));
468 shaderSource.append(
"[");
469 shaderSource.append(std::to_string(member.dimension));
470 shaderSource.append(
"]");
472 shaderSource.append(
",\n");
474 shaderSource.append(
"};\n");
476 addUniform(shaderSource, bindingGroups, definition.name, definition.name +
"_t",
true);
479 void addEngineBuffers(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen, WebGPUBindingGroupVector& bindingGroups) {
480 for (
const std::string& name : requiredEngineBuffers) {
481 addUniform(shaderSource, bindingGroups, name, name +
"_t",
true);
483 for (
const std::string& name : optionalEngineBuffers) {
485 if (identifiersSeen.contains(Strings::add(name))) {
486 addUniform(shaderSource, bindingGroups, name, name +
"_t",
true);
493 shaderSource.append(
"fn transferAttributes(vertexIn : VertexIn, vertexOut : ptr<function, VertexOut>) {\n");
495 if (member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::SV_VertexID)
continue;
497 if (dMember.name == member.name) {
498 shaderSource.append(
" (*vertexOut).");
499 shaderSource.append(member.name);
500 shaderSource.append(
" = ");
501 if (dMember.type == MaterialDataType::Float3 && member.type == MaterialDataType::Float2 && member.semantic.name == ShaderInterfaceMemberDefinition::SemanticName::Normal) {
502 shaderSource.append(
"octDecode(vertexIn.");
503 shaderSource.append(member.name);
504 shaderSource.append(
"); \n");
507 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float3) {
508 shaderSource.append(
"vec4f(vertexIn.");
509 shaderSource.append(member.name);
510 shaderSource.append(
", 1.0);\n");
513 if (dMember.type == MaterialDataType::Float4 && member.type == MaterialDataType::Float2) {
514 shaderSource.append(
"vec4f(vertexIn.");
515 shaderSource.append(member.name);
516 shaderSource.append(
", 0.0, 1.0);\n");
520 if (dMember.type != member.type) {
521 switch (dMember.type) {
522 case MaterialDataType::Float: shaderSource.append(
"f32("); close =
true;
break;
523 case MaterialDataType::Float2: shaderSource.append(
"vec2f("); close =
true;
break;
524 case MaterialDataType::Float3: shaderSource.append(
"vec3f("); close =
true;
break;
525 case MaterialDataType::Float4: shaderSource.append(
"vec4f("); close =
true;
break;
526 case MaterialDataType::Float4x4: shaderSource.append(
"mat4x4f("); close =
true;
break;
527 case MaterialDataType::Int: shaderSource.append(
"i32("); close =
true;
break;
528 case MaterialDataType::Int2: shaderSource.append(
"vec2i("); close =
true;
break;
529 case MaterialDataType::Int3: shaderSource.append(
"vec3i("); close =
true;
break;
530 case MaterialDataType::Int4: shaderSource.append(
"vec4i("); close =
true;
break;
531 case MaterialDataType::UInt: shaderSource.append(
"u32("); close =
true;
break;
532 case MaterialDataType::UInt2: shaderSource.append(
"vec2u("); close =
true;
break;
533 case MaterialDataType::UInt3: shaderSource.append(
"vec3u("); close =
true;
break;
534 case MaterialDataType::UInt4: shaderSource.append(
"vec4u("); close =
true;
break;
539 shaderSource.append(
"vertexIn.");
540 shaderSource.append(member.name);
541 if (close) shaderSource.append(1,
')');
542 shaderSource.append(
";\n");
547 shaderSource.append(
"}\n");
550 void addCallFunction(std::string& source, std::string_view name, std::string_view functionName, std::string_view inType, std::string_view outType) {
551 source.append(
"fn ");
553 source.append(
"(In : ");
554 source.append(inType);
555 source.append(
") ->");
556 source.append(outType);
557 source.append(
" { \n");
558 source.append(
" return ");
559 source.append(functionName);
560 source.append(
"(In);\n");
561 source.append(
"}\n\n");
564 void addTextures(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen, WebGPUBindingGroupVector& bindingGroups,
const std::vector<MaterialTextureDefinition>& definition,
bool ignoreIdentifiersSeen =
false)
566 for (
auto& texture : definition) {
567 if (!identifiersSeen.contains(Strings::add(texture.name)) && !ignoreIdentifiersSeen) {
572 switch (texture.dimensions) {
573 case TextureDimensions::Texture2D:
576 case TextureDimensions::TexureCube:
577 type +=
"_cube<f32>";
579 case TextureDimensions::Texture2DArray:
580 type +=
"_2d_array<f32>";
582 case TextureDimensions::Texture3D:
586 LOG_ERROR(logger,
"Unsupported texture type %d",
int(texture.dimensions));
589 addUniform(shaderSource, bindingGroups, texture.name, type);
590 addUniform(shaderSource, bindingGroups, texture.name +
"Sampler",
"sampler");
594 void addEngineTextures(std::string& shaderSource,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen, WebGPUBindingGroupVector& bindingGroups)
596 for (
auto& texture : engineTextures) {
597 if (!identifiersSeen.contains(Strings::add(texture.name))) {
602 std::string samplerType =
"sampler";
605 if (texture.isDepthTexture) {
607 samplerType +=
"_comparison";
610 switch (texture.dimensions) {
611 case TextureDimensions::Texture2D:
614 case TextureDimensions::TexureCube:
617 case TextureDimensions::Texture2DArray:
620 case TextureDimensions::Texture3D:
624 LOG_ERROR(logger,
"Unsupported texture type %d",
int(texture.dimensions));
627 if (!texture.isDepthTexture) {
630 addUniform(shaderSource, bindingGroups, texture.name, type);
631 addUniform(shaderSource, bindingGroups, texture.name +
"Sampler", samplerType);
637bool Cogs::Core::buildEffectWebGPU(
Context* context,
638 std::vector<std::pair<std::string, std::string>>& definitions,
641 const uint32_t multiViewCount)
643 if (!materialDefinition.effect.geometryShader.entryPoint.empty()) {
644 LOG_ERROR(logger,
"%s: Geometry shader not allowed in WebGPU.", materialDefinition.name.c_str());
647 if (!materialDefinition.effect.hullShader.entryPoint.empty()) {
648 LOG_ERROR(logger,
"%s: Hull shader not allowed in WebGPU.", materialDefinition.name.c_str());
651 if (!materialDefinition.effect.domainShader.entryPoint.empty()) {
652 LOG_ERROR(logger,
"%s: Domain shader not allowed in WebGPU.", materialDefinition.name.c_str());
655 if (!materialDefinition.effect.computeShader.entryPoint.empty()) {
656 LOG_ERROR(logger,
"%s: Compute shader not allowed in WebGPU.", materialDefinition.name.c_str());
660 changeSuffix(materialDefinition.effect.vertexShader.customSourcePath,
".hlsl",
".wgsl");
661 changeSuffix(materialDefinition.effect.pixelShader.customSourcePath,
".hlsl",
".wgsl");
662 std::string prefix =
"" + materialDefinition.name;
664 WebGPUBindingGroupVector bindings;
665 createBufferBinding(bindings, materialDefinition);
666 createTextureBindings(bindings, materialDefinition);
667 createEngineTextureBindings(bindings);
671 std::string vs_header;
672 const std::string shaderName = prefix +
"VertexShader" + permutation.getDefinition()->name +
".wgsl";
673 addEffectDefinesAndStuff(vs_header, definitions, multiViewCount);
674 if (!pp.
process(context, vs_header))
return false;
679 addInterfaceStruct(vs_header, vs_body,
"VertexIn", materialDefinition.effect.vertexShader.shaderInterface, ShaderInterface::VertexIn);
680 addInterfaceStruct(vs_header, vs_body,
"VertexOut", materialDefinition.effect.pixelShader.shaderInterface, ShaderInterface::VertexOut);
681 addInterfaceConstructor(vs_body,
"VertexOut", materialDefinition.effect.pixelShader.shaderInterface);
682 addTransferFunc(vs_body, materialDefinition.effect.vertexShader, materialDefinition.effect.pixelShader);
683 addInclude(vs_body, std::string_view(), materialDefinition.effect.vertexShader.customSourcePath);
684 std::string permutationVS = permutation.getDefinition()->vertexShader;
685 changeSuffix(permutationVS,
".hlsl",
".wgsl");
687 addCallFunction(vs_body,
"callMaterialVertexFunction",
688 materialDefinition.effect.vertexShader.entryPoint.empty() ?
"vertexFunction" : materialDefinition.effect.vertexShader.entryPoint,
689 "VertexIn",
"VertexOut");
690 addInclude(vs_body, std::string_view(),
"Engine/EngineVS.wgsl");
691 addCallFunction(vs_body,
"callVertexFunction",
693 "VertexIn",
"VertexOut");
694 addInclude(vs_body, std::string_view(), permutationVS);
695 if (!pp.
process(context, vs_body))
return false;
699 std::string vs_uniforms;
708 addInclude(vs_uniforms, std::string_view(),
"Engine/Common.wgsl");
710 if (!pp.
process(context, vs_uniforms))
return false;
714 std::string all = vs_header + vs_uniforms + vs_body;
715 all = convertDefinesToConstExpressions(all);
717 std::string vspath =
"Shaders/" + shaderName;
722 std::string fs_header;
723 const std::string shaderName = prefix +
"PixelShader" + permutation.getDefinition()->name +
".wgsl";
724 addEffectDefinesAndStuff(fs_header, definitions, 0 );
728 addInterfaceStruct(fs_header, fs_body,
"VertexIn", materialDefinition.effect.pixelShader.shaderInterface, ShaderInterface::FragmentIn);
729 addInclude(fs_header, std::string_view(), materialDefinition.effect.pixelShader.customSourcePath);
730 std::string permutationFS = permutation.getDefinition()->pixelShader;
731 changeSuffix(permutationFS,
".hlsl",
".wgsl");
733 addCallFunction(fs_header,
"callMaterialSurfaceFunction",
734 materialDefinition.effect.pixelShader.entryPoint.empty() ?
"surfaceFunction" : materialDefinition.effect.pixelShader.entryPoint,
735 "VertexIn",
"SurfaceOut");
736 addInclude(fs_header, std::string_view(),
"Engine/EnginePS.wgsl");
737 addCallFunction(fs_header,
"callSurfaceFunction",
739 "VertexIn",
"SurfaceOut");
740 addInclude(fs_header, std::string_view(), permutationFS);
741 if (!pp.
process(context, fs_header))
return false;
745 std::string fs_uniforms;
746 fs_uniforms.reserve(InitialBufferCapasity);
747 addTextures(fs_uniforms, pp.
identifiersSeen, bindings, materialDefinition.properties.textures,
true);
756 addInclude(fs_uniforms, std::string_view(),
"Engine/Common.wgsl");
757 if (!pp.
process(context, fs_uniforms))
return false;
761 std::string all = fs_header + fs_uniforms + fs_body;
762 all = convertDefinesToConstExpressions(all);
764 std::string fspath =
"Shaders/" + shaderName;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class ResourceStore > resourceStore
ResourceStore service instance.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
TextureDimensions
Texture dimensions.
MaterialDataType
Defines available data types for material properties.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
bool process(Context *context, const StringView input)
Run a text block through the preprocessor.
std::unordered_set< StringRef > identifiersSeen
Set of identifiers encountered in active text.
std::string processed
Resulting processed text.