1#include "ShaderBuilderPostProcess.h"
4#include "Utilities/Strings.h"
5#include "Utilities/Parsing.h"
6#include "Utilities/Preprocessor.h"
7#include "ResourceStore.h"
8#include "Renderer/EnginePermutations.h"
9#include "Rendering/IGraphicsDevice.h"
10#include "Renderer/RenderPipelineDefinition.h"
11#include "Renderer/Tasks/PostProcessTask.h"
12#include "Renderer/Tasks/ComputeTask.h"
13#include "Foundation/Logging/Logger.h"
14#include "Rendering/IContext.h"
15#include "Rendering/IBuffers.h"
16#include "Renderer/IRenderer.h"
17#include "Renderer/RenderTarget.h"
19#include <glm/gtc/type_ptr.hpp>
28 constexpr size_t InitialBufferCapasity = 4096u;
32 void removeSuffix(std::string& dst,
const std::string_view& suffix)
34 auto pos = dst.find(suffix);
35 if (pos == std::string::npos)
return;
40 [[nodiscard]] std::string_view parameterType(
const ParsedDataType type)
43 case ParsedDataType::Float:
return "float";
break;
44 case ParsedDataType::Float2:
return "float2";
break;
45 case ParsedDataType::Float3:
return "float3";
break;
46 case ParsedDataType::Float4:
return "float4";
break;
47 case ParsedDataType::Float4x4:
return "float4x4";
break;
48 case ParsedDataType::Int:
return "int";
break;
49 case ParsedDataType::Int2:
return "int2";
break;
50 case ParsedDataType::Int3:
return "int3";
break;
51 case ParsedDataType::Int4:
return "int4";
break;
52 case ParsedDataType::UInt:
return "uint";
break;
53 case ParsedDataType::UInt2:
return "uint2";
break;
54 case ParsedDataType::UInt3:
return "uint3";
break;
55 case ParsedDataType::UInt4:
return "uint4";
break;
57 LOG_ERROR(logger,
"Unsupported attribute type %d",
int(type));
63 void addUniforms(std::string& src,
const std::vector<ProcessTaskProperty>& properties,
const std::unordered_set<Cogs::Core::StringRef>&) {
64 std::string parameterUBOsrc;
66 bool hasParameters =
false;
67 parameterUBOsrc.append(
"");
68 parameterUBOsrc.append(
"cbuffer EffectParameters {\n");
71 switch (p.definition->type) {
72 case ParsedDataType::Float:
73 case ParsedDataType::Float2:
74 case ParsedDataType::Float3:
75 case ParsedDataType::Float4:
76 case ParsedDataType::Float4x4:
77 case ParsedDataType::Int:
78 case ParsedDataType::Int2:
79 case ParsedDataType::Int3:
80 case ParsedDataType::Int4:
81 case ParsedDataType::UInt:
82 case ParsedDataType::UInt2:
83 case ParsedDataType::UInt3:
84 case ParsedDataType::UInt4:
85 parameterUBOsrc.append(
" ");
86 parameterUBOsrc.append(parameterType(p.definition->type));
87 parameterUBOsrc.append(
" " + p.definition->key +
";\n");
91 case ParsedDataType::Texture2D:
93 std::string_view type_str =
"float4";
94 if (p.definition->texture.dataType != ParsedDataType::Unknown) {
95 type_str = parameterType(p.definition->texture.dataType);
98 if (p.definition->texture.samples <= 1) {
99 src.append(
"uniform Texture2D<");
100 src.append(type_str);
101 src.append(
"> " + p.definition->key +
";\n");
104 src.append(
"uniform Texture2DMS<");
105 src.append(type_str);
106 src.append(
", " + std::to_string(p.definition->texture.samples) +
"> " + p.definition->key +
";\n");
109 src.append(
"uniform SamplerState " + p.definition->key +
"Sampler;\n");;
113 case ParsedDataType::Buffer:
115 auto type_str = parameterType(p.definition->buffer.dataType);
116 if ((p.definition->buffer.flags & ParsedValueBufferFlags::Structured) == ParsedValueBufferFlags::None) {
117 src.append(
"RWBuffer ");
120 src.append(
"RWStructuredBuffer<");
121 src.append(type_str);
124 src.append(p.definition->key +
";\n");
127 case ParsedDataType::ConstantBuffer:
128 if (p.definition->key ==
"SceneBuffer") {
129 src.append(
"#define COGS_SCENEBUFFER_REFERENCED 1\n");
130 src.append(
"#include \"Engine/Common.hlsl\"\n\n");
131 }
else if (p.definition->value.starts_with(
"Cogs.")) {
132 std::string bufferName = p.definition->value.substr(5);
133 src.append(
"#include \"Engine/" + bufferName +
".hlsl\"\n");
140 parameterUBOsrc.append(
"};\n");
142 src.append(parameterUBOsrc);
146 void addEngineSampleStates(std::string& src) {
148SamplerState linearSampler;
149SamplerState linearClampSampler;
150SamplerState pointSampler;
151SamplerState pointClampSampler;
156 void addInterface(std::string& src) {
161 float4 Position : SV_Position;
162 float4 ScreenPosition : TEXCOORD0;
163 float2 TexCoords : TEXCOORD1;
170 void addOutputStruct(std::string& src,
const PipelineOptions& options,
bool writeDepth) {
171 bool hasCustomTargets =
false;
172 std::string prefix =
"target_";
173 src.append(
"struct PixelOut {\n");
175 src.append(
" float fragDepth : SV_Depth;\n");
177 for (
auto o : options) {
180 for (
auto& c : key) {
181 c =
static_cast<decltype(key)::value_type
>(std::tolower(c));
183 if (key.substr(0, prefix.size()) == prefix) {
184 if (!hasCustomTargets) {
185 hasCustomTargets =
true;
187 int location = std::stoi(key.substr(prefix.size()));
189 Cogs::Core::split(o.second,
" ", tokens);
190 if (tokens.size() != 2) {
191 LOG_ERROR(logger,
"Unable to parse pipeline output option %s", o.second.c_str());
194 std::string_view datatype =
"Undefined";
197 datatype = parameterType(ParsedDataType::Float);
200 datatype = parameterType(ParsedDataType::Float2);
203 datatype = parameterType(ParsedDataType::Float3);
206 datatype = parameterType(ParsedDataType::Float4);
209 datatype = parameterType(ParsedDataType::UInt);
212 datatype = parameterType(ParsedDataType::UInt2);
215 datatype = parameterType(ParsedDataType::UInt3);
218 datatype = parameterType(ParsedDataType::UInt4);
221 datatype = parameterType(ParsedDataType::Int);
224 datatype = parameterType(ParsedDataType::Int2);
227 datatype = parameterType(ParsedDataType::Int3);
230 datatype = parameterType(ParsedDataType::Int4);
234 src.append(datatype);
236 src.append(tokens[0]);
237 src.append(
" : SV_Target" + std::to_string(location) +
";\n");
240 if (!hasCustomTargets) {
241 src.append(
" float4 fragColor : SV_Target0;\n");
243 src.append(
"};\n\n");
254 std::string prefix_ps = desc.ps;
255 removeSuffix(prefix_ps,
".hlsl");
256 src.append(
"#include \"" + prefix_ps +
".hlsl\"\n");
257 auto code =
hash(src);
258 std::string file_prefix = prefix_ps +
"_" + std::to_string(code);
261 pp.
processed.reserve(::InitialBufferCapasity);
263 if (!pp.
process(context->context, src))
return false;
265 std::string uniform_src;
267 addEngineSampleStates(uniform_src);
268 addOutputStruct(uniform_src, task->options, task->writeDepth);
269 uniform_src.append(src);
270 src = std::move(uniform_src);
273 context->context->
resourceStore->addResource(file_prefix +
".hlsl", src);
274 desc.ps = file_prefix +
".hlsl";
282 addEngineSampleStates(src);
283 std::string prefix_cs = desc.cs;
284 removeSuffix(prefix_cs,
".hlsl");
285 src.append(
"#include \"" + prefix_cs +
".hlsl\"\n");
286 auto code =
hash(src);
287 std::string file_prefix = prefix_cs +
"_" + std::to_string(code);
290 pp.
processed.reserve(::InitialBufferCapasity);
292 if (!pp.
process(context->context, src))
return false;
294 std::string uniform_src;
296 uniform_src.append(src);
297 src = std::move(uniform_src);
300 context->context->
resourceStore->addResource(file_prefix +
".hlsl", src);
301 desc.cs = file_prefix +
".hlsl";
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....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
COGSFOUNDATION_API size_t hashLowercase(std::string_view str, size_t hashValue=Cogs::hash()) noexcept
Get the hash code of the string converted to lowercase.
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.