1#include "RenderPipelineReader.h"
5#include "Foundation/Logging/Logger.h"
10#include "Bridge/Bridge.h"
12#include "Resources/ResourceStore.h"
14#include "Utilities/Parsing.h"
25 RenderResourceType parseResourceType(
const std::string & str)
27 if (str ==
"RenderList") {
28 return RenderResourceType::RenderList;
29 }
else if (str ==
"Texture2D") {
30 return RenderResourceType::RenderTexture;
31 }
else if (str ==
"RenderTarget") {
32 return RenderResourceType::RenderTarget;
33 }
else if (str ==
"RenderBuffer") {
34 return RenderResourceType::RenderBuffer;
37 return RenderResourceType::Unknown;
40 void parseOptions(
const Value & jsonOptions, RenderPipelineDefinition & definition)
42 for (
auto & o : jsonOptions.GetObject()) {
43 auto name = toKey(o.name);
46 option.key = name.to_string();
48 if (!o.value.IsObject()) {
49 LOG_ERROR(logger,
"Option %.*s must be object type.", StringViewFormat(name));
53 for (
auto & v : o.value.GetObject()) {
54 auto key = toKey(v.name);
56 if (key ==
"values" && v.value.IsArray()) {
57 for (
auto & vv : v.value.GetArray()) {
58 option.values.push_back(vv.GetString());
60 }
else if (key ==
"setting") {
61 option.setting = v.value.GetString();
65 definition.options.push_back(option);
69 void parseValue(
const StringView & key,
const Value & value, ParsedValue & v)
71 v.key = key.to_string();
73 switch (value.GetType())
77 parseStringValue(toKey(value), v);
82 v.type = ParsedDataType::Object;
84 for (
auto & m : value.GetObject()) {
85 v.values.emplace_back();
86 parseValue(toKey(m.name), m.value, v.values.back());
92 v.type = ParsedDataType::Int;
93 v.intValue =
static_cast<int>(value.GetInt());
95 v.type = ParsedDataType::Float;
96 v.floatValue =
static_cast<float>(value.GetFloat());
101 auto arr = value.GetArray();
103 if (arr.Size() < 1) {
104 LOG_ERROR(logger,
"Cannot deduce type from empty array.");
108 auto arrayType = arr[0].GetType();
110 if (arr.Size() > 4) {
111 LOG_ERROR(logger,
"Too many array members.");
115 if (arrayType == kStringType) {
116 v.type = ParsedDataType::String;
117 v.dimension = arr.Size();
119 for (
auto & a : arr) {
121 p.value = a.GetString();
122 v.values.push_back(p);
125 v.type = (ParsedDataType)((
size_t)ParsedDataType::Float + arr.Size() - 1);
126 for (uint32_t i = 0; i < arr.Size(); ++i) {
127 switch (arr[i].GetType())
130 v.float4Value[
static_cast<glm::length_t
>(i)] = arr[i].GetFloat();
133 LOG_ERROR(logger,
"Unknown vector type.");
141 v.type = ParsedDataType::Bool;
145 v.type = ParsedDataType::Bool;
153 void parseResource(
const Value & value, RenderResourceDefinition & resource,
const std::string & )
155 if (value.IsString()) {
156 std::string str = value.GetString();
158 auto space = str.find(
' ');
159 if (space != std::string::npos) {
160 resource.type = parseResourceType(str.substr(0, space));
161 resource.alias = str.substr(space + 1);
163 resource.type = parseResourceType(str);
165 }
else if (value.IsObject()) {
166 for (
auto & m : value.GetObject()) {
167 auto key = toKey(m.name);
170 resource.type = parseResourceType(m.value.GetString());
171 }
else if (key ==
"textures") {
172 for (
auto & t : m.value.GetArray()) {
173 resource.textures.push_back(t.GetString());
177 parseValue(key, m.value, p);
178 resource.parameters.push_back(p);
184 bool parseResources(
const Value & jsonResources, RenderPipelineDefinition & definition,
const std::string & condition =
"")
186 for (
auto & m : jsonResources.GetObject()) {
187 auto key = toString(m.name);
190 parseResources(m.value, definition, condition.size() ? condition + key : key);
194 RenderResourceDefinition resource;
196 resource.condition = condition;
198 parseResource(m.value, resource, condition);
200 definition.resources.push_back(resource);
206 void parseSlots(
const Value & value, std::vector<RenderTaskSlot> & slots)
208 if (value.IsArray()) {
209 for (
auto & v : value.GetArray()) {
210 slots.push_back(toString(v));
212 }
else if (value.IsString()) {
213 slots.push_back(toString(value));
214 }
else if (value.IsObject()) {
215 for (
auto & m : value.GetObject()) {
216 slots.push_back({ toString(m.name), toString(m.value) });
221 void parseTask(
const Value & jsonTask, RenderTaskDefinition & task,
const std::string & )
223 for (
auto & m : jsonTask.GetObject()) {
224 auto key = toString(m.name);
225 auto & value = m.value;
227 if (key ==
"type" && value.IsString()) {
228 task.type = toString(value);
229 }
else if (key ==
"dependencies" || key ==
"depends") {
230 if (value.IsArray()) {
231 for (
auto & a : value.GetArray()) {
232 task.dependencies.push_back(toString(a));
234 }
else if (value.IsString()) {
235 task.dependencies.push_back(toString(value));
237 }
else if (key ==
"options") {
238 for (
auto & m_ : value.GetObject()) {
239 task.options.push_back({ toString(m_.name), toString(m_.value), {} });
241 }
else if (key ==
"inputs" || key ==
"input") {
242 parseSlots(value, task.inputs);
243 }
else if (key ==
"outputs" || key ==
"output") {
244 parseSlots(value, task.outputs);
247 parseValue(key, value, p);
248 task.parameters.push_back(p);
253 bool parseTasks(
const Value & jsonTasks, RenderPipelineDefinition & definition,
const std::string & condition =
"")
255 for (
auto & m : jsonTasks.GetObject()) {
256 auto key = toString(m.name);
257 auto & value = m.value;
260 parseTasks(value, definition, condition.size() ? condition + key : key);
264 RenderTaskDefinition task;
266 task.condition = condition;
268 parseTask(value, task, condition);
270 definition.tasks.push_back(task);
276 bool parseDefinition(Context * context,
const Value & jsonDefinition, RenderPipelineDefinition & definition)
278 for (
auto & m : jsonDefinition.GetObject()) {
279 auto key = toString(m.name);
280 auto & value = m.value;
283 definition.name = toString(value);
284 }
else if (key ==
"permutations") {
285 auto val = toString(value);
286 loadPermutations(context, val.c_str());
287 }
else if (key ==
"options") {
288 parseOptions(value, definition);
289 }
if (key ==
"resources") {
290 parseResources(value, definition);
291 }
else if (key ==
"tasks") {
292 parseTasks(value, definition);
293 }
else if (key ==
"generators") {
294 for (
auto & g : value.GetObject()) {
295 RenderPipelineDefinition generator;
296 generator.name = toString(g.name);
297 parseDefinition(context, g.value, generator);
298 definition.generators.push_back(generator);
300 }
else if (key ==
"imports" || key ==
"import") {
301 for (
auto &
import : value.GetObject()) {
302 definition.imports.push_back({ toString(
import.name), toString(
import.value), {} });
304 }
else if (key ==
"input" || key ==
"inputs") {
305 parseSlots(value, definition.inputs);
306 }
else if (key ==
"outputs" || key ==
"output") {
307 parseSlots(value, definition.outputs);
308 }
else if (key ==
"useVariables") {
309 if (value.IsObject()) {
310 for (
auto & m_ : value.GetObject()) {
312 auto key_ = toKey(m_.name);
313 parseValue(key_, m_.value, p);
314 definition.useVariables.push_back(p);
317 }
else if (key ==
"setVariables") {
318 if (value.IsObject()) {
319 for (
auto & m_ : value.GetObject()) {
321 auto key_ = toKey(m_.name);
322 parseValue(key_, m_.value, p);
323 definition.setVariables.push_back(p);
326 }
else if (key ==
"useComponentFields") {
327 if (value.IsObject()) {
328 for (
auto & m_ : value.GetObject()) {
330 auto key_ = toKey(m_.name);
331 parseValue(key_, m_.value, p);
332 definition.useComponentFields.push_back(p);
346 auto document = isContent ? parseJson(resource, JsonParseFlags::None) : parseJson(context, resource);
348 if (!document.IsObject()) {
349 LOG_ERROR(logger,
"Cannot read pipeline from non-object JSON.");
350 return RenderPipelineDefinition{};
353 for (
auto & m : document.GetObject()) {
354 auto key = toKey(m.name);
356 if (key ==
"Pipeline") {
357 RenderPipelineDefinition definition;
358 parseDefinition(context, m.value, definition);
363 return RenderPipelineDefinition{};
Log implementation class.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.