summaryrefslogtreecommitdiff
path: root/drivers/gles3/rasterizer_canvas_gles3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/rasterizer_canvas_gles3.cpp')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp239
1 files changed, 91 insertions, 148 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 441b049b50..e14018c562 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -117,6 +117,7 @@ void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_trans
void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
texture_storage->frame.current_rt = nullptr;
@@ -155,7 +156,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
- state_buffer.time = texture_storage->frame.time;
+ state_buffer.time = state.time;
state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel;
state_buffer.directional_light_count = 0; //directional_light_count;
@@ -178,8 +179,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
//print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_state_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_BUFFER_OBJECT, state.canvas_state_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
+
+ GLuint global_buffer = material_storage->global_variables_get_uniform_buffer();
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_BUFFER_OBJECT, global_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
@@ -197,8 +202,6 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
r_sdf_used = false;
int item_count = 0;
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
Item *ci = p_item_list;
while (ci) {
// just add all items for now
@@ -215,7 +218,6 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
- GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
Item *current_clip = nullptr;
@@ -229,88 +231,31 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
RID prev_material;
uint32_t index = 0;
+ state.current_shader_version = state.canvas_shader_default_version;
+
for (int i = 0; i < p_item_count; i++) {
Item *ci = items[i];
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
- GLES3::Material *material_ptr = material_storage->get_material(material);
if (material.is_null() && ci->canvas_group != nullptr) {
material = default_canvas_group_material;
}
if (material != prev_material) {
- GLES3::Shader *shader_ptr = nullptr;
-
- if (material_ptr) {
- shader_ptr = material_ptr->shader;
-
- if (shader_ptr && shader_ptr->mode != RS::SHADER_CANVAS_ITEM) {
- shader_ptr = nullptr; // not a canvas item shader, don't use.
- }
+ GLES3::CanvasMaterialData *material_data = nullptr;
+ if (material.is_valid()) {
+ material_data = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM));
}
-
- if (shader_ptr) {
- if (true) { //check that shader has changed
- if (shader_ptr->canvas_item.uses_time) {
- RenderingServerDefault::redraw_request();
- }
- //state.canvas_shader.version_bind_shader(shader_ptr->version, CanvasShaderGLES3::MODE_QUAD);
- state.current_shader_version = shader_ptr->version;
- }
-
- int tc = material_ptr->textures.size();
- Pair<StringName, RID> *textures = material_ptr->textures.ptrw();
-
- ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_ptr->texture_uniforms.ptrw();
-
- for (int ti = 0; ti < tc; i++) {
- glActiveTexture(GL_TEXTURE0 + ti);
-
- GLES3::Texture *t = texture_storage->get_texture(textures[ti].second);
-
- if (!t) {
- switch (texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
- } break;
- default: {
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- } break;
- }
-
- continue;
- }
-
- //Set texture filter and repeat texture_uniforms[i].filter texture_uniforms[i].repeat
-
- if (t->redraw_if_visible) {
- RenderingServerDefault::redraw_request();
- }
-
- t = t->get_ptr();
-
-#ifdef TOOLS_ENABLED
- if (t->detect_normal && texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
- t->detect_normal(t->detect_normal_ud);
- }
-#endif
- if (t->render_target) {
- t->render_target->used_in_frame = true;
- }
-
- glBindTexture(t->target, t->tex_id);
+ if (material_data) {
+ if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
+ // Bind uniform buffer and textures
+ material_data->bind_uniforms();
+ state.current_shader_version = material_data->shader_data->version;
+ } else {
+ state.current_shader_version = state.canvas_shader_default_version;
}
-
} else {
- //state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
state.current_shader_version = state.canvas_shader_default_version;
}
prev_material = material;
@@ -389,7 +334,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.current_command = Item::Command::TYPE_RECT;
}
_bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size);
- state.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_QUAD);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_QUAD);
Rect2 src_rect;
Rect2 dst_rect;
@@ -552,7 +497,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.current_command = Item::Command::TYPE_POLYGON;
}
_bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index, last_texture, texpixel_size);
- state.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
state.current_primitive = polygon->primitive;
state.instance_data_array[r_index].modulation[0] = base_color.r;
@@ -566,16 +511,18 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
}
- // If the previous operation is not done yet, allocated a new buffer
- GLint syncStatus;
- glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
- if (syncStatus == GL_UNSIGNALED) {
- _allocate_instance_data_buffer();
- } else {
- glDeleteSync(state.fences[state.current_buffer]);
+ // If the previous operation is not done yet, allocate a new buffer
+ if (state.fences[state.current_buffer] != GLsync()) {
+ GLint syncStatus;
+ glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
+ if (syncStatus == GL_UNSIGNALED) {
+ _allocate_instance_data_buffer();
+ } else {
+ glDeleteSync(state.fences[state.current_buffer]);
+ }
}
- glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.canvas_instance_data_buffers[state.current_buffer]);
+ glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
#ifdef JAVASCRIPT_ENABLED
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData), &state.instance_data_array[0], GL_DYNAMIC_DRAW);
@@ -609,7 +556,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.current_command = Item::Command::TYPE_PRIMITIVE;
}
_bind_canvas_texture(RID(), current_filter, current_repeat, r_index, last_texture, texpixel_size);
- state.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE);
for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) {
state.instance_data_array[r_index].points[j * 2 + 0] = primitive->points[j].x;
@@ -771,15 +718,17 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
if (state.end_batch && r_index > 0) {
// If the previous operation is not done yet, allocate a new buffer
- GLint syncStatus;
- glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
- if (syncStatus == GL_UNSIGNALED) {
- _allocate_instance_data_buffer();
- } else {
- glDeleteSync(state.fences[state.current_buffer]);
+ if (state.fences[state.current_buffer] != GLsync()) {
+ GLint syncStatus;
+ glGetSynciv(state.fences[state.current_buffer], GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
+ if (syncStatus == GL_UNSIGNALED) {
+ _allocate_instance_data_buffer();
+ } else {
+ glDeleteSync(state.fences[state.current_buffer]);
+ }
}
- glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.canvas_instance_data_buffers[state.current_buffer]);
+ glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
#ifdef JAVASCRIPT_ENABLED
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * r_index, state.instance_data_array, GL_DYNAMIC_DRAW);
@@ -823,24 +772,24 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
}
// TODO maybe dont use
-void RasterizerCanvasGLES3::_end_batch(uint32_t &r_index) {
+void RasterizerCanvasGLES3::_end_batch(const uint32_t p_index) {
for (int i = 0; i < 4; i++) {
- state.instance_data_array[r_index].modulation[i] = 0.0;
- state.instance_data_array[r_index].ninepatch_margins[i] = 0.0;
- state.instance_data_array[r_index].src_rect[i] = 0.0;
- state.instance_data_array[r_index].dst_rect[i] = 0.0;
+ state.instance_data_array[p_index].modulation[i] = 0.0;
+ state.instance_data_array[p_index].ninepatch_margins[i] = 0.0;
+ state.instance_data_array[p_index].src_rect[i] = 0.0;
+ state.instance_data_array[p_index].dst_rect[i] = 0.0;
}
- state.instance_data_array[r_index].flags = uint32_t(0);
- state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0;
- state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0;
+ state.instance_data_array[p_index].flags = uint32_t(0);
+ state.instance_data_array[p_index].color_texture_pixel_size[0] = 0.0;
+ state.instance_data_array[p_index].color_texture_pixel_size[1] = 0.0;
- state.instance_data_array[r_index].pad[0] = 0.0;
- state.instance_data_array[r_index].pad[1] = 0.0;
+ state.instance_data_array[p_index].pad[0] = 0.0;
+ state.instance_data_array[p_index].pad[1] = 0.0;
- state.instance_data_array[r_index].lights[0] = uint32_t(0);
- state.instance_data_array[r_index].lights[1] = uint32_t(0);
- state.instance_data_array[r_index].lights[2] = uint32_t(0);
- state.instance_data_array[r_index].lights[3] = uint32_t(0);
+ state.instance_data_array[p_index].lights[0] = uint32_t(0);
+ state.instance_data_array[p_index].lights[1] = uint32_t(0);
+ state.instance_data_array[p_index].lights[2] = uint32_t(0);
+ state.instance_data_array[p_index].lights[3] = uint32_t(0);
}
RID RasterizerCanvasGLES3::light_create() {
@@ -903,7 +852,8 @@ void RasterizerCanvasGLES3::canvas_begin() {
reset_canvas();
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE));
+ glBindTexture(GL_TEXTURE_2D, tex->tex_id);
}
void RasterizerCanvasGLES3::canvas_end() {
@@ -961,11 +911,9 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
ct->size_cache = Size2i(1, 1);
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE));
+ glBindTexture(GL_TEXTURE_2D, tex->tex_id);
} else {
- texture = texture->get_ptr();
-
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->tex_id);
@@ -973,8 +921,8 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.current_tex_ptr = texture;
ct->size_cache = Size2i(texture->width, texture->height);
- texture->GLSetFilter(GL_TEXTURE_2D, filter);
- texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
}
GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
@@ -983,17 +931,16 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.current_normal = RID();
ct->use_normal_cache = false;
glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6);
- glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_NORMAL));
+ glBindTexture(GL_TEXTURE_2D, tex->tex_id);
} else {
- normal_map = normal_map->get_ptr();
-
glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
state.current_normal = ct->normal_map;
ct->use_normal_cache = true;
- texture->GLSetFilter(GL_TEXTURE_2D, filter);
- texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
}
GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular);
@@ -1002,17 +949,15 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.current_specular = RID();
ct->use_specular_cache = false;
glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
- glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE));
+ glBindTexture(GL_TEXTURE_2D, tex->tex_id);
} else {
- specular_map = specular_map->get_ptr();
-
glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
glBindTexture(GL_TEXTURE_2D, specular_map->tex_id);
state.current_specular = ct->specular;
ct->use_specular_cache = true;
- texture->GLSetFilter(GL_TEXTURE_2D, filter);
- texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
}
if (ct->use_specular_cache) {
@@ -1102,8 +1047,8 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
{
glBindBuffer(GL_ARRAY_BUFFER, pb.vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, stride * vertex_count * sizeof(float), nullptr, GL_STATIC_DRAW); // TODO may not be necessary
- const uint8_t *r = polygon_buffer.ptr();
- float *fptr = (float *)r;
+ uint8_t *r = polygon_buffer.ptrw();
+ float *fptr = reinterpret_cast<float *>(r);
uint32_t *uptr = (uint32_t *)r;
uint32_t base_offset = 0;
{
@@ -1260,7 +1205,19 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-void RasterizerCanvasGLES3::initialize() {
+void RasterizerCanvasGLES3::set_time(double p_time) {
+ state.time = p_time;
+}
+
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::singleton = nullptr;
+
+RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
+ return singleton;
+}
+
+RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) {
+ singleton = this;
+ storage = p_storage;
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
@@ -1386,9 +1343,7 @@ void RasterizerCanvasGLES3::initialize() {
}
//state.canvas_shadow_shader.init();
-
- int uniform_max_size;
- glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &uniform_max_size);
+ int uniform_max_size = storage->config->max_uniform_buffer_size;
if (uniform_max_size < 65536) {
state.max_lights_per_render = 64;
state.max_instances_per_batch = 128;
@@ -1402,6 +1357,7 @@ void RasterizerCanvasGLES3::initialize() {
state.fences.resize(64);
glGenBuffers(64, state.canvas_instance_data_buffers.ptr());
for (int i = 0; i < 64; i++) {
+ state.fences[i] = GLsync();
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_instance_data_buffers[i]);
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * state.max_instances_per_batch, nullptr, GL_DYNAMIC_DRAW);
}
@@ -1419,9 +1375,9 @@ void RasterizerCanvasGLES3::initialize() {
global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n";
global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n";
- state.canvas_shader.initialize(global_defines);
- state.canvas_shader_default_version = state.canvas_shader.version_create();
- state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines);
+ state.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create();
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
//state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows);
@@ -1463,32 +1419,19 @@ void fragment() {
state.using_transparent_rt = false;
state.using_skeleton = false;
state.current_shader_version = state.canvas_shader_default_version;
-}
-
-RasterizerCanvasGLES3 *RasterizerCanvasGLES3::singleton = nullptr;
-
-RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
- return singleton;
-}
-
-RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) {
- singleton = this;
- storage = p_storage;
- initialize();
+ state.time = 0.0;
}
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- state.canvas_shader.version_free(state.canvas_shader_default_version);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
texture_storage->canvas_texture_free(default_canvas_texture);
singleton = nullptr;
-}
-void RasterizerCanvasGLES3::finalize() {
glDeleteBuffers(1, &data.canvas_quad_vertices);
glDeleteVertexArrays(1, &data.canvas_quad_array);