Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/dummy/storage/material_storage.cpp
20959 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 if (mode_string == "texture_blit") {
182
new_mode = RS::SHADER_TEXTURE_BLIT;
183
} else {
184
new_mode = RS::SHADER_MAX;
185
ERR_FAIL_MSG("Shader type " + mode_string + " not supported in Dummy renderer.");
186
}
187
ShaderCompiler::IdentifierActions actions;
188
actions.uniforms = &shader->uniforms;
189
ShaderCompiler::GeneratedCode gen_code;
190
191
Error err = MaterialStorage::get_singleton()->dummy_compiler.compile(new_mode, p_code, &actions, "", gen_code);
192
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
193
}
194
195
void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
196
DummyShader *shader = shader_owner.get_or_null(p_shader);
197
ERR_FAIL_NULL(shader);
198
199
SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter;
200
LocalVector<Pair<StringName, int>> filtered_uniforms;
201
202
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : shader->uniforms) {
203
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
204
continue;
205
}
206
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.prop_order));
207
}
208
int uniform_count = filtered_uniforms.size();
209
sorter.sort(filtered_uniforms.ptr(), uniform_count);
210
211
String last_group;
212
for (int i = 0; i < uniform_count; i++) {
213
const StringName &uniform_name = filtered_uniforms[i].first;
214
const ShaderLanguage::ShaderNode::Uniform &uniform = shader->uniforms[uniform_name];
215
216
String group = uniform.group;
217
if (!uniform.subgroup.is_empty()) {
218
group += "::" + uniform.subgroup;
219
}
220
221
if (group != last_group) {
222
PropertyInfo pi;
223
pi.usage = PROPERTY_USAGE_GROUP;
224
pi.name = group;
225
p_param_list->push_back(pi);
226
227
last_group = group;
228
}
229
230
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniform);
231
pi.name = uniform_name;
232
p_param_list->push_back(pi);
233
}
234
}
235
236
RID MaterialStorage::material_allocate() {
237
return material_owner.allocate_rid();
238
}
239
240
void MaterialStorage::material_initialize(RID p_rid) {
241
material_owner.initialize_rid(p_rid, DummyMaterial());
242
}
243
244
void MaterialStorage::material_free(RID p_rid) {
245
DummyMaterial *material = material_owner.get_or_null(p_rid);
246
ERR_FAIL_NULL(material);
247
248
material_owner.free(p_rid);
249
}
250
251
void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
252
DummyMaterial *material = material_owner.get_or_null(p_material);
253
ERR_FAIL_NULL(material);
254
255
material->shader = p_shader;
256
}
257
258
void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
259
DummyMaterial *material = material_owner.get_or_null(p_material);
260
ERR_FAIL_NULL(material);
261
262
material->next_pass = p_next_material;
263
}
264
265
void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
266
DummyMaterial *material = material_owner.get_or_null(p_material);
267
ERR_FAIL_NULL(material);
268
DummyShader *shader = shader_owner.get_or_null(material->shader);
269
270
if (shader) {
271
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : shader->uniforms) {
272
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
273
continue;
274
}
275
276
RendererMaterialStorage::InstanceShaderParam p;
277
p.info = ShaderLanguage::uniform_to_property_info(E.value);
278
p.info.name = E.key; //supply name
279
p.index = E.value.instance_index;
280
p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
281
r_parameters->push_back(p);
282
}
283
}
284
if (material->next_pass.is_valid()) {
285
material_get_instance_shader_parameters(material->next_pass, r_parameters);
286
}
287
}
288
289