1#include "ShaderBuilderHelpersWebGPU.h"
2#include "Rendering/IBindGroups.h"
4#include "Utilities/Strings.h"
5#include "Utilities/Preprocessor.h"
6#include "ResourceStore.h"
7#include "Renderer/EnginePermutations.h"
8#include "Rendering/IGraphicsDevice.h"
10#include "Foundation/Logging/Logger.h"
18 using Cogs::Core::BindGroup;
21 std::vector<std::string> sceneGetters = {
22 "getClipFromViewMatrix",
23 "getClipFromWorldMatrix",
24 "getViewFromWorldMatrix",
25 "getViewFromClipMatrix",
26 "getWorldFromViewMatrix",
27 "getInverseViewMatrix",
28 "getViewFromViewportMatrix",
29 "getViewportFromViewMatrix",
30 "getPeriodicWorldPosAndCell",
34 std::vector<std::string> objectGetters = {
35 "getWorldFromLocalMatrix",
39 struct EngineBufferDesc {
42 std::vector<std::string> getters;
46 const std::array engineBuffers = {
47 EngineBufferDesc{
"SceneBuffer", BindGroup::Scene, sceneGetters},
48 EngineBufferDesc{
"ObjectBuffer", BindGroup::Object, objectGetters},
51 struct EngineTexture {
53 Cogs::ResourceDimensions dimensions;
54 bool isDepthTexture =
false;
55 BindGroup group = BindGroup::Default;
58 const std::array engineTextures = {
59 EngineTexture{.name =
"environmentSky", .dimensions = Cogs::ResourceDimensions::TextureCube, .group = BindGroup::LightTextures},
60 EngineTexture{.name =
"environmentRadiance", .dimensions = Cogs::ResourceDimensions::TextureCube, .group = BindGroup::LightTextures},
61 EngineTexture{.name =
"environmentIrradiance", .dimensions = Cogs::ResourceDimensions::TextureCube, .group = BindGroup::LightTextures},
62 EngineTexture{.name =
"ambientIrradiance", .dimensions = Cogs::ResourceDimensions::TextureCube, .group = BindGroup::LightTextures},
63 EngineTexture{.name =
"brdfLUT", .dimensions = Cogs::ResourceDimensions::Texture2D, .group = BindGroup::LightTextures},
64 EngineTexture{.name =
"cascadedShadowMap", .dimensions = Cogs::ResourceDimensions::Texture2DArray, .isDepthTexture =
true, .group = BindGroup::LightTextures},
65 EngineTexture{.name =
"cubeShadowMap", .dimensions = Cogs::ResourceDimensions::TextureCube, .isDepthTexture =
true, .group = BindGroup::LightTextures},
68 struct EngineSampler {
70 BindGroup group = BindGroup::Default;
71 bool isDepthTexture =
false;
74 const std::array engineSamplers = {
75 EngineSampler{.name =
"linearSampler", .group = BindGroup::LightTextures},
76 EngineSampler{.name =
"linearClampSampler", .group = BindGroup::LightTextures},
77 EngineSampler{.name =
"pointSampler", .group = BindGroup::LightTextures},
78 EngineSampler{.name =
"pointClampSampler", .group = BindGroup::LightTextures},
79 EngineSampler{.name =
"shadowSampler", .group = BindGroup::LightTextures, .isDepthTexture =
true},
83 const uint32_t SceneGlobalVisibility = (Cogs::BindingVisibilityVertex | Cogs::BindingVisibilityFragment | Cogs::BindingVisibilityCompute);
88 entry.binding = binding;
90 entry.resourceType = Cogs::BindingResourceType::UniformBuffer;
91 entry.visibility = SceneGlobalVisibility;
96 const uint32_t binding,
98 const Cogs::ResourceDimensions dimension,
99 const bool isDepthTexture)
102 entry.binding = binding;
104 entry.resourceType = Cogs::BindingResourceType::Texture;
105 entry.visibility = SceneGlobalVisibility;
106 entry.textureDimension = dimension;
107 entry.isDepthTexture = isDepthTexture;
114 entry.binding = binding;
116 entry.resourceType = Cogs::BindingResourceType::Sampler;
117 entry.samplerBindingType = isDepthTexture ? Cogs::BindingSamplerBindingType::Comparison : Cogs::BindingSamplerBindingType::Filtering;
118 entry.visibility = SceneGlobalVisibility;
123 std::string textureDataType(Cogs::BindingTextureSampleType type)
126 case Cogs::BindingTextureSampleType::Unknown:
127 case Cogs::BindingTextureSampleType::Float:
128 case Cogs::BindingTextureSampleType::UnfilterableFloat:
129 case Cogs::BindingTextureSampleType::Depth:
131 case Cogs::BindingTextureSampleType::Sint:
133 case Cogs::BindingTextureSampleType::Uint:
136 LOG_ERROR(logger,
"Unsupported texture datatype %d",
int(type));
149 for (uint16_t i = 0; i < group.numEntries; ++i) {
151 if (entry.nameHash == nameHash) {
160 source.append(
"#include \"Engine/");
162 source.append(
".wgsl\"\n");
163 source.append(
"@group(");
164 source.append(std::to_string(
static_cast<size_t>(group)));
165 source.append(
") @binding(");
166 source.append(std::to_string(entry.binding));
167 source.append(
") var<uniform> ");
169 source.append(
" : ");
171 source.append(
"_t;\n");
176 source.append(
"@group(");
177 source.append(std::to_string(
static_cast<size_t>(group)));
178 source.append(
") @binding(");
179 source.append(std::to_string(entry.binding));
180 source.append(
") var ");
182 source.append(
" : ");
183 source.append(entry.samplerBindingType == Cogs::BindingSamplerBindingType::Comparison ?
"sampler_comparison" :
"sampler");
184 source.append(
";\n");
193 if (entry.isDepthTexture) {
197 switch (entry.textureDimension) {
198 case Cogs::ResourceDimensions::Texture2D:
201 case Cogs::ResourceDimensions::TextureCube:
204 case Cogs::ResourceDimensions::Texture2DArray:
207 case Cogs::ResourceDimensions::Texture3D:
211 LOG_ERROR(logger,
"Unsupported texture dimension %d",
int(entry.textureDimension));
215 if (!entry.isDepthTexture) {
216 std::string dataType = textureDataType(entry.textureSampleType);
217 type +=
"<" + dataType +
">";
220 source.append(
"@group(");
221 source.append(std::to_string(
static_cast<size_t>(group)));
222 source.append(
") @binding(");
223 source.append(std::to_string(entry.binding));
224 source.append(
") var");
227 source.append(
" : ");
229 source.append(
";\n");
237 if (staticDesc.numGroups == 0) {
239 groups.numGroups =
static_cast<uint16_t
>(BindGroup::Count);
240 for (
const auto& buffer : engineBuffers) {
242 uint16_t binding = g.numEntries;
243 g.entries[g.numEntries++] = makeBufferEntry(binding, buffer.name.c_str());
247 for (
const auto& texture : engineTextures) {
249 uint16_t binding = g.numEntries;
250 g.entries[g.numEntries++] = makeTextureEntry(binding, texture.name.c_str(), texture.dimensions, texture.isDepthTexture);
253 for (
const auto& sampler : engineSamplers) {
255 uint16_t binding = g.numEntries;
256 g.entries[g.numEntries++] = makeSamplerEntry(binding, sampler.name.c_str(), sampler.isDepthTexture);
263 void addEngineUniformsToSourceWebGPU(std::string& source,
const std::unordered_set<Cogs::Core::StringRef>& identifiersSeen, std::vector<bool>& bindGroupUsed) {
264 bindGroupUsed.resize(
static_cast<size_t>(BindGroup::Count),
false);
267 for (
const auto& buffer : engineBuffers) {
269 for (
auto& get : buffer.getters) {
270 if (identifiersSeen.contains(Strings::add(get))) {
275 if (identifiersSeen.contains(Cogs::Core::Strings::add(buffer.name))) {
279 bindGroupUsed[
static_cast<size_t>(buffer.group)] =
true;
286 for (
const auto& texture : engineTextures) {
287 if (!identifiersSeen.contains(Cogs::Core::Strings::add(texture.name))) {
294 bindGroupUsed[
static_cast<size_t>(texture.group)] =
true;
298 for (
const auto& sampler : engineSamplers) {
299 if (!identifiersSeen.contains(Cogs::Core::Strings::add(sampler.name))) {
304 bindGroupUsed[
static_cast<size_t>(sampler.group)] =
true;
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
void addBufferToSource(std::string &source, const std::string &name, BindGroup group, const Cogs::BindGroupEntryDescription &entry)
Emits a valid WGSL uniform buffer declaration ("#include" + "@group()@binding() var<uniform>") for an...
const Cogs::BindGroupEntryDescription * findEntryByName(const Cogs::BindGroupDescription &group, std::string_view name)
Finds an entry by name within a single bind group's already-populated entries (bound by numEntries).
void addSamplerToSource(std::string &source, const std::string &name, BindGroup group, const Cogs::BindGroupEntryDescription &entry)
Emits a valid WGSL sampler declaration ("@group()@binding() var") for an engine-provided sampler entr...
void addTextureToSource(std::string &source, const std::string &name, BindGroup group, const Cogs::BindGroupEntryDescription &entry)
Emits a valid WGSL texture declaration ("@group()@binding() var") for an engine-provided texture entr...
constexpr Log getLogger(const char(&name)[LEN]) noexcept
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.