Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/dummy/storage/material_storage.cpp
10279 views
1
/**************************************************************************/
2
/* material_storage.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "material_storage.h"
32
33
#include "core/config/project_settings.h"
34
35
using namespace RendererDummy;
36
37
MaterialStorage *MaterialStorage::singleton = nullptr;
38
39
MaterialStorage::MaterialStorage() {
40
singleton = this;
41
ShaderCompiler::DefaultIdentifierActions actions;
42
dummy_compiler.initialize(actions);
43
}
44
45
MaterialStorage::~MaterialStorage() {
46
singleton = nullptr;
47
global_shader_variables.clear();
48
}
49
50
void MaterialStorage::global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) {
51
ERR_FAIL_COND(global_shader_variables.has(p_name));
52
53
global_shader_variables[p_name] = p_type;
54
}
55
56
void MaterialStorage::global_shader_parameter_remove(const StringName &p_name) {
57
if (!global_shader_variables.has(p_name)) {
58
return;
59
}
60
61
global_shader_variables.erase(p_name);
62
}
63
64
Vector<StringName> MaterialStorage::global_shader_parameter_get_list() const {
65
Vector<StringName> names;
66
for (const KeyValue<StringName, RS::GlobalShaderParameterType> &E : global_shader_variables) {
67
names.push_back(E.key);
68
}
69
names.sort_custom<StringName::AlphCompare>();
70
return names;
71
}
72
73
RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type(const StringName &p_name) const {
74
if (!global_shader_variables.has(p_name)) {
75
print_line("don't have name, sorry");
76
return RS::GLOBAL_VAR_TYPE_MAX;
77
}
78
79
return global_shader_variables[p_name];
80
}
81
82
void MaterialStorage::global_shader_parameters_load_settings(bool p_load_textures) {
83
List<PropertyInfo> settings;
84
ProjectSettings::get_singleton()->get_property_list(&settings);
85
86
for (const PropertyInfo &E : settings) {
87
if (E.name.begins_with("shader_globals/")) {
88
StringName name = E.name.get_slicec('/', 1);
89
Dictionary d = GLOBAL_GET(E.name);
90
91
ERR_CONTINUE(!d.has("type"));
92
ERR_CONTINUE(!d.has("value"));
93
94
String type = d["type"];
95
96
static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
97
"bool",
98
"bvec2",
99
"bvec3",
100
"bvec4",
101
"int",
102
"ivec2",
103
"ivec3",
104
"ivec4",
105
"rect2i",
106
"uint",
107
"uvec2",
108
"uvec3",
109
"uvec4",
110
"float",
111
"vec2",
112
"vec3",
113
"vec4",
114
"color",
115
"rect2",
116
"mat2",
117
"mat3",
118
"mat4",
119
"transform_2d",
120
"transform",
121
"sampler2D",
122
"sampler2DArray",
123
"sampler3D",
124
"samplerCube",
125
"samplerExternalOES"
126
};
127
128
RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
129
130
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
131
if (global_var_type_names[i] == type) {
132
gvtype = RS::GlobalShaderParameterType(i);
133
break;
134
}
135
}
136
137
ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
138
139
if (!global_shader_variables.has(name)) {
140
global_shader_parameter_add(name, gvtype, Variant());
141
}
142
}
143
}
144
}
145
146
RID MaterialStorage::shader_allocate() {
147
return shader_owner.allocate_rid();
148
}
149
150
void MaterialStorage::shader_initialize(RID p_rid, bool p_embedded) {
151
shader_owner.initialize_rid(p_rid, DummyShader());
152
}
153
154
void MaterialStorage::shader_free(RID p_rid) {
155
DummyShader *shader = shader_owner.get_or_null(p_rid);
156
ERR_FAIL_NULL(shader);
157
158
shader_owner.free(p_rid);
159
}
160
161
void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
162
DummyShader *shader = shader_owner.get_or_null(p_shader);
163
ERR_FAIL_NULL(shader);
164
if (p_code.is_empty()) {
165
return;
166
}
167
168
String mode_string = ShaderLanguage::get_shader_type(p_code);
169
170
RS::ShaderMode new_mode;
171
if (mode_string == "canvas_item") {
172
new_mode = RS::SHADER_CANVAS_ITEM;
173
} else if (mode_string == "particles") {
174
new_mode = RS::SHADER_PARTICLES;
175
} else if (mode_string == "spatial") {
176
new_mode = RS::SHADER_SPATIAL;
177
} else if (mode_string == "sky") {
178
new_mode = RS::SHADER_SKY;
179
} else if (mode_string == "fog") {
180
new_mode = RS::SHADER_FOG;
181
} else {
182
new_mode = RS::SHADER_MAX;
183
ERR_FAIL_MSG("Shader type " + mode_string + " not supported in Dummy renderer.");
184
}
185
ShaderCompiler::IdentifierActions actions;
186
actions.uniforms = &shader->uniforms;
187
ShaderCompiler::GeneratedCode gen_code;
188
189
Error err = MaterialStorage::get_singleton()->dummy_compiler.compile(new_mode, p_code, &actions, "", gen_code);
190
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
191
}
192
193
void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
194
DummyShader *shader = shader_owner.get_or_null(p_shader);
195
ERR_FAIL_NULL(shader);
196
197
SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter;
198
LocalVector<Pair<StringName, int>> filtered_uniforms;
199
200
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : shader->uniforms) {
201
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
202
continue;
203
}
204
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.prop_order));
205
}
206
int uniform_count = filtered_uniforms.size();
207
sorter.sort(filtered_uniforms.ptr(), uniform_count);
208
209
String last_group;
210
for (int i = 0; i < uniform_count; i++) {
211
const StringName &uniform_name = filtered_uniforms[i].first;
212
const ShaderLanguage::ShaderNode::Uniform &uniform = shader->uniforms[uniform_name];
213
214
String group = uniform.group;
215
if (!uniform.subgroup.is_empty()) {
216
group += "::" + uniform.subgroup;
217
}
218
219
if (group != last_group) {
220
PropertyInfo pi;
221
pi.usage = PROPERTY_USAGE_GROUP;
222
pi.name = group;
223
p_param_list->push_back(pi);
224
225
last_group = group;
226
}
227
228
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniform);
229
pi.name = uniform_name;
230
p_param_list->push_back(pi);
231
}
232
}
233
234
RID MaterialStorage::material_allocate() {
235
return material_owner.allocate_rid();
236
}
237
238
void MaterialStorage::material_initialize(RID p_rid) {
239
material_owner.initialize_rid(p_rid, DummyMaterial());
240
}
241
242
void MaterialStorage::material_free(RID p_rid) {
243
DummyMaterial *material = material_owner.get_or_null(p_rid);
244
ERR_FAIL_NULL(material);
245
246
material_owner.free(p_rid);
247
}
248
249
void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
250
DummyMaterial *material = material_owner.get_or_null(p_material);
251
ERR_FAIL_NULL(material);
252
253
material->shader = p_shader;
254
}
255
256
void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
257
DummyMaterial *material = material_owner.get_or_null(p_material);
258
ERR_FAIL_NULL(material);
259
260
material->next_pass = p_next_material;
261
}
262
263
void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
264
DummyMaterial *material = material_owner.get_or_null(p_material);
265
ERR_FAIL_NULL(material);
266
DummyShader *shader = shader_owner.get_or_null(material->shader);
267
268
if (shader) {
269
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : shader->uniforms) {
270
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
271
continue;
272
}
273
274
RendererMaterialStorage::InstanceShaderParam p;
275
p.info = ShaderLanguage::uniform_to_property_info(E.value);
276
p.info.name = E.key; //supply name
277
p.index = E.value.instance_index;
278
p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
279
r_parameters->push_back(p);
280
}
281
}
282
if (material->next_pass.is_valid()) {
283
material_get_instance_shader_parameters(material->next_pass, r_parameters);
284
}
285
}
286
287