sculpto
shaders_preprocessor.cpp
Go to the documentation of this file.
1/*!****************************************************************//*!*
2 * \file shader_preprocessor.cpp
3 * \brief Assets manager shaders preprocessor class implementation module.
4 *
5 * \author Sabitov Kirill
6 * \date 07 July 2022
7 *********************************************************************/
8
9#include "sclpch.h"
11#include "files_load.h"
12
13std::string scl::assets_manager::shader_preprocessor::ReadWord(std::string::const_iterator Begin,
14 std::string::const_iterator End,
15 int *SpacesCount)
16{
17 // skip spaces
18 if (SpacesCount) *SpacesCount = 0;
19 while (Begin != End && ((*Begin) == ' ' || (*Begin) == '\n'))
20 {
21 ++Begin;
22 if (SpacesCount) ++(*SpacesCount);
23 }
24
25 // return sequence of letters from start to neares space or end of string
26 return std::string(Begin, Begin + std::min(std::string(Begin, End).find(' '), std::string(Begin, End).find('\n')));
27}
28
29scl::shader_type scl::assets_manager::shader_preprocessor::ShaderTypeFromString(const std::string &ShaderTypeString)
30{
31 std::string shader_string_prepared(ShaderTypeString);
32 std::transform(shader_string_prepared.begin(), shader_string_prepared.end(), shader_string_prepared.begin(),
33 [](unsigned char c) { return std::tolower(c); });
34
35 switch (StringId(shader_string_prepared.c_str()))
36 {
37 case "compute"_id: return shader_type::COMPUTE;
38 case "vertex"_id: return shader_type::VERTEX;
39 case "geometry"_id: return shader_type::GEOMETRY;
40 case "pixel"_id:
41 case "fragment"_id: return shader_type::PIXEL;
42 }
43
44 SCL_CORE_ASSERT(0, "Unknown shader type!");
45 return shader_type();
46}
47
48void scl::assets_manager::shader_preprocessor::SeparateShaders(const std::string &ShaderDebugName,
49 const std::string &ShaderText,
50 std::vector<shader_props> &Out)
51{
52 size_t offset = ShaderText.find(shader_preprocessor::LexemBlockStart, 0);
53 if (offset == std::string::npos)
54 {
55 SCL_CORE_ERROR("Error while preprocessing shader \"{}\".\nNo shader blcoks was found in text.", ShaderDebugName);
56 return;
57 }
58 std::string global_block(ShaderText.begin(), ShaderText.begin() + offset);
59
60 while (offset != std::string::npos)
61 {
62 size_t block_start_offset = ShaderText.find(' ', offset);
63 if (block_start_offset == std::string::npos)
64 SCL_CORE_ERROR("Error while preprocessing shader \"{}\".\nNo block text found, block skiped.", ShaderDebugName);
65
66 size_t block_end_offset = ShaderText.find(shader_preprocessor::LexemBlockEnd, offset);
67 if (block_end_offset == std::string::npos)
68 SCL_CORE_ERROR("Error while preprocessing shader \"{}\".\nNo block end lexem found. Block skiped.", ShaderDebugName);
69
70 if (block_end_offset != std::string::npos && block_start_offset != std::string::npos)
71 {
72 int spaces_count;
73 std::string block_text(ShaderText.begin() + block_start_offset, ShaderText.begin() + block_end_offset);
74 std::string block_shader_type_string = ReadWord(block_text.begin(), block_text.end(), &spaces_count);
75
76 shader_type block_shader_type;
77 bool block_shader_type_ok = true;
78 std::transform(block_shader_type_string.begin(), block_shader_type_string.end(), block_shader_type_string.begin(),
79 [](unsigned char c) { return std::tolower(c); });
80
81 switch (StringId(block_shader_type_string.c_str()))
82 {
83 case "compute"_id: block_shader_type = shader_type::COMPUTE; break;
84 case "vert"_id:
85 case "vertex"_id: block_shader_type = shader_type::VERTEX; break;
86 case "geom"_id:
87 case "geometry"_id: block_shader_type = shader_type::GEOMETRY; break;
88 case "pixel"_id:
89 case "frag"_id:
90 case "fragment"_id: block_shader_type = shader_type::PIXEL; break;
91 default:
92 SCL_CORE_ERROR("Error while preprocessing shader \"{}\".\nShader type \"{}\" is unknown. Block skipped.", ShaderDebugName, block_shader_type_string);
93 block_shader_type_ok = false;
94 }
95
96 if (block_shader_type_ok)
97 Out.push_back({
98 block_shader_type,
99 global_block + std::string(block_text.begin() + spaces_count + block_shader_type_string.size(), block_text.end())
100 });
101 }
102 offset = ShaderText.find(shader_preprocessor::LexemBlockStart, block_end_offset);
103 }
104}
105
106void scl::assets_manager::shader_preprocessor::ProcessIncludes(const std::string &ShaderDebugName,
107 const std::string &ShaderFolderPath,
108 std::string &ShaderText)
109{
110 size_t offset;
111 while ((offset = ShaderText.find(shader_preprocessor::LexemInclude, 0)) != std::string::npos)
112 {
113 ShaderText.erase(offset, strlen(shader_preprocessor::LexemInclude));
114
115 int spaces_count = 0;
116 std::string include_path = ReadWord(ShaderText.begin() + offset, ShaderText.end(), &spaces_count);
117 ShaderText.erase(offset, spaces_count + include_path.size());
118
119 std::string file_name = std::string(include_path.begin() + 1, include_path.end() - 1);
120 std::filesystem::path file_path = ShaderFolderPath / std::filesystem::path(file_name);
121 ShaderText.insert(offset, LoadFile(file_path));
122 }
123}
#define SCL_CORE_ASSERT(expr,...)
Definition: assert.h:69
static void ProcessIncludes(const std::string &ShaderDebugName, const std::string &ShaderFolderPath, std::string &ShaderText)
static void SeparateShaders(const std::string &ShaderDebugName, const std::string &ShaderText, std::vector< shader_props > &Out)
#define SCL_CORE_ERROR(...)
Definition: log.h:44
std::string LoadFile(const std::filesystem::path &FilePath)
Definition: files_load.cpp:12
shader_type
Definition: shader.h:17
constexpr string_id StringId(const char *Str)
Definition: string_id.h:87
Sculpto library prehompiled header. Defines common definitions, includes commonly used modules.
Assets manager shaders preprocessor class definition module.