summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub2
-rw-r--r--drivers/gles3/environment/fog.cpp2
-rw-r--r--drivers/gles3/environment/fog.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp1044
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h111
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp16
-rw-r--r--drivers/gles3/rasterizer_gles3.h5
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp155
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h77
-rw-r--r--drivers/gles3/shaders/canvas.glsl21
-rw-r--r--drivers/gles3/storage/config.cpp2
-rw-r--r--drivers/gles3/storage/config.h2
-rw-r--r--drivers/gles3/storage/light_storage.cpp131
-rw-r--r--drivers/gles3/storage/light_storage.h90
-rw-r--r--drivers/gles3/storage/material_storage.cpp8
-rw-r--r--drivers/gles3/storage/material_storage.h2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp168
-rw-r--r--drivers/gles3/storage/texture_storage.h49
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h4
-rw-r--r--drivers/unix/dir_access_unix.cpp24
-rw-r--r--drivers/unix/dir_access_unix.h4
-rw-r--r--drivers/unix/file_access_unix.cpp31
-rw-r--r--drivers/unix/file_access_unix.h4
-rw-r--r--drivers/unix/net_socket_posix.cpp32
-rw-r--r--drivers/unix/os_unix.cpp13
-rw-r--r--drivers/unix/os_unix.h6
-rw-r--r--drivers/unix/thread_posix.cpp6
-rw-r--r--drivers/unix/thread_posix.h2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp36
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h2
-rw-r--r--drivers/vulkan/vulkan_context.cpp43
-rw-r--r--drivers/vulkan/vulkan_context.h2
-rw-r--r--drivers/windows/dir_access_windows.cpp36
-rw-r--r--drivers/windows/file_access_windows.cpp6
34 files changed, 1137 insertions, 1001 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index dd81fc645c..6cfcb1d18c 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -24,6 +24,7 @@ SConscript("winmidi/SCsub")
# Graphics drivers
if env["vulkan"]:
+ SConscript("spirv-reflect/SCsub")
SConscript("vulkan/SCsub")
if env["opengl3"]:
SConscript("gl_context/SCsub")
@@ -31,7 +32,6 @@ if env["opengl3"]:
# Core dependencies
SConscript("png/SCsub")
-SConscript("spirv-reflect/SCsub")
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp
index 02d88f6871..8587c5f9f7 100644
--- a/drivers/gles3/environment/fog.cpp
+++ b/drivers/gles3/environment/fog.cpp
@@ -43,7 +43,7 @@ RID Fog::fog_volume_allocate() {
void Fog::fog_volume_initialize(RID p_rid) {
}
-void Fog::fog_free(RID p_rid) {
+void Fog::fog_volume_free(RID p_rid) {
}
void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h
index 350eb459cf..fcde7399dd 100644
--- a/drivers/gles3/environment/fog.h
+++ b/drivers/gles3/environment/fog.h
@@ -46,7 +46,7 @@ public:
virtual RID fog_volume_allocate() override;
virtual void fog_volume_initialize(RID p_rid) override;
- virtual void fog_free(RID p_rid) override;
+ virtual void fog_volume_free(RID p_rid) override;
virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 0ffede0992..c635e18132 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -124,6 +124,26 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
// Clear out any state that may have been left from the 3D pass.
reset_canvas();
+ if (state.canvas_instance_data_buffers[state.current_buffer].fence != GLsync()) {
+ GLint syncStatus;
+ glGetSynciv(state.canvas_instance_data_buffers[state.current_buffer].fence, GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus);
+ if (syncStatus == GL_UNSIGNALED) {
+ // If older than 2 frames, wait for sync OpenGL can have up to 3 frames in flight, any more and we need to sync anyway.
+ if (state.canvas_instance_data_buffers[state.current_buffer].last_frame_used < RSG::rasterizer->get_frame_number() - 2) {
+ glClientWaitSync(state.canvas_instance_data_buffers[state.current_buffer].fence, 0, 100000000); // wait for up to 100ms
+ } else {
+ // Used in last frame or frame before that. OpenGL can get up to two frames behind, so these buffers may still be in use
+ // Allocate a new buffer and use that.
+ _allocate_instance_data_buffer();
+ }
+ } else {
+ // Already finished all rendering commands, we can use it.
+ state.canvas_instance_data_buffers[state.current_buffer].last_frame_used = RSG::rasterizer->get_frame_number();
+ glDeleteSync(state.canvas_instance_data_buffers[state.current_buffer].fence);
+ state.canvas_instance_data_buffers[state.current_buffer].fence = GLsync();
+ }
+ }
+
// TODO: Setup Directional Lights
// TODO: Setup lights
@@ -207,6 +227,8 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Item *ci = p_item_list;
Item *canvas_group_owner = nullptr;
+ uint32_t starting_index = 0;
+
while (ci) {
if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
backbuffer_copy = true;
@@ -245,8 +267,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
if (ci->canvas_group_owner != nullptr) {
if (canvas_group_owner == nullptr) {
// Canvas group begins here, render until before this item
-
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
item_count = 0;
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
@@ -271,7 +292,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
if (ci == canvas_group_owner) {
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, true);
item_count = 0;
if (ci->canvas_group->blur_mipmaps) {
@@ -279,12 +300,14 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
canvas_group_owner = nullptr;
+ // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it.
+ backbuffer_cleared = false;
}
if (backbuffer_copy) {
//render anything pending, including clearing if no items
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
item_count = 0;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
@@ -306,7 +329,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
items[item_count++] = ci;
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
- _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
//then reset
item_count = 0;
}
@@ -318,46 +341,43 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
RenderingServerDefault::redraw_request();
}
+ state.canvas_instance_data_buffers[state.current_buffer].fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
// Clear out state used in 2D pass
reset_canvas();
+ state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
}
-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();
+void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- Item *current_clip = nullptr;
-
- Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
canvas_begin(p_to_render_target, p_to_backbuffer);
- RID prev_material;
+ if (p_item_count <= 0) {
+ // Nothing to draw, just call canvas_begin() to clear the render target and return.
+ return;
+ }
+
uint32_t index = 0;
- GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX;
- Color last_blend_color;
- GLES3::CanvasShaderData *shader_data_cache = nullptr;
+ Item *current_clip = nullptr;
+
+ // Record Batches.
+ // First item always forms its own batch.
+ bool batch_broken = false;
+ _new_batch(batch_broken, index);
- state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
- state.current_tex_ptr = nullptr;
- state.current_normal = RID();
- state.current_specular = RID();
- state.canvas_texscreen_used = false;
- state.current_shader_version = state.canvas_shader_default_version;
+ // Override the start position and index as we want to start from where we finished off last time.
+ state.canvas_instance_batches[state.current_batch_index].start = r_last_index * sizeof(InstanceData);
+ index = 0;
+ _align_instance_data_buffer(index);
for (int i = 0; i < p_item_count; i++) {
Item *ci = items[i];
- if (current_clip != ci->final_clip_owner) {
- _render_batch(index);
-
+ if (ci->final_clip_owner != state.canvas_instance_batches[state.current_batch_index].clip) {
+ _new_batch(batch_broken, index);
+ state.canvas_instance_batches[state.current_batch_index].clip = ci->final_clip_owner;
current_clip = ci->final_clip_owner;
- //setup clip
- if (current_clip) {
- glEnable(GL_SCISSOR_TEST);
- glScissor(current_clip->final_clip_rect.position.x, current_clip->final_clip_rect.position.y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
- } else {
- glDisable(GL_SCISSOR_TEST);
- }
}
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
@@ -366,105 +386,68 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
material = default_canvas_group_material;
}
- if (material != prev_material) {
- _render_batch(index);
+ GLES3::CanvasShaderData *shader_data_cache = nullptr;
+ if (material != state.canvas_instance_batches[state.current_batch_index].material) {
+ _new_batch(batch_broken, index);
+
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));
}
+ shader_data_cache = nullptr;
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;
shader_data_cache = material_data->shader_data;
- } else {
- state.current_shader_version = state.canvas_shader_default_version;
- shader_data_cache = nullptr;
}
- } else {
- state.current_shader_version = state.canvas_shader_default_version;
- shader_data_cache = nullptr;
}
- prev_material = material;
+
+ state.canvas_instance_batches[state.current_batch_index].material = material;
+ state.canvas_instance_batches[state.current_batch_index].material_data = material_data;
}
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
- _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index, blend_mode, last_blend_mode, last_blend_color);
+ _record_item_commands(ci, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
}
- // Render last command
- _render_batch(index);
-}
-
-void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color) {
- // Used by Polygon and Mesh.
- static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
-
- RS::CanvasItemTextureFilter current_filter = state.default_filter;
- RS::CanvasItemTextureRepeat current_repeat = state.default_repeat;
-
- if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) {
- current_filter = p_item->texture_filter;
- }
-
- if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) {
- current_repeat = p_item->texture_repeat;
- }
-
- Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform;
- Transform2D draw_transform; // Used by transform command
-
- Color base_color = p_item->final_modulate;
-
- uint32_t base_flags = 0;
-
- bool reclip = false;
-
- bool skipping = false;
-
- const Item::Command *c = p_item->commands;
- while (c) {
- if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
- c = c->next;
- continue;
- }
- if (c->type != Item::Command::TYPE_MESH) {
- // For Meshes, this gets updated below.
- _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
- }
-
- 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[r_index].lights[i] = 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;
+ // Copy over all data needed for rendering.
+ glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].ubo);
+#ifdef WEB_ENABLED
+ glBufferSubData(GL_UNIFORM_BUFFER, r_last_index * sizeof(InstanceData), sizeof(InstanceData) * index, state.instance_data_array);
+#else
+ // On Desktop and mobile we map the memory without synchronizing for maximum speed.
+ void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, r_last_index * sizeof(InstanceData), index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
+ memcpy(ubo, state.instance_data_array, index * sizeof(InstanceData));
+ glUnmapBuffer(GL_UNIFORM_BUFFER);
+#endif
- state.instance_data_array[r_index].pad[0] = 0.0;
- state.instance_data_array[r_index].pad[1] = 0.0;
+ glDisable(GL_SCISSOR_TEST);
+ current_clip = nullptr;
- state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
+ GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX;
- GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode;
- Color blend_color;
+ state.current_tex = RID();
- if (c->type == Item::Command::TYPE_RECT) {
- const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
- if (rect->flags & CANVAS_RECT_LCD) {
- blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD;
- blend_color = rect->modulate;
+ for (uint32_t i = 0; i <= state.current_batch_index; i++) {
+ //setup clip
+ if (current_clip != state.canvas_instance_batches[i].clip) {
+ current_clip = state.canvas_instance_batches[i].clip;
+ if (current_clip) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(current_clip->final_clip_rect.position.x, current_clip->final_clip_rect.position.y, current_clip->final_clip_rect.size.x, current_clip->final_clip_rect.size.y);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
}
}
- if (r_last_blend_mode != blend_mode || r_last_blend_color != blend_color) {
- _render_batch(r_index);
+ GLES3::CanvasMaterialData *material_data = state.canvas_instance_batches[i].material_data;
+ CanvasShaderGLES3::ShaderVariant variant = state.canvas_instance_batches[i].shader_variant;
+ _bind_material(material_data, variant);
- if (r_last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
+ GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
+
+ if (last_blend_mode != blend_mode) {
+ if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
// re-enable it
glEnable(GL_BLEND);
} else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
@@ -475,7 +458,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
switch (blend_mode) {
case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: {
// Nothing to do here.
-
} break;
case GLES3::CanvasShaderData::BLEND_MODE_LCD: {
glBlendEquation(GL_FUNC_ADD);
@@ -484,6 +466,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
} else {
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE);
}
+ Color blend_color = state.canvas_instance_batches[state.current_batch_index].blend_color;
glBlendColor(blend_color.r, blend_color.g, blend_color.b, blend_color.a);
} break;
@@ -532,32 +515,112 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
} break;
}
- r_last_blend_mode = blend_mode;
- r_last_blend_color = blend_color;
+ last_blend_mode = blend_mode;
+ }
+
+ _render_batch(p_lights, i);
+ }
+
+ state.current_batch_index = 0;
+ state.canvas_instance_batches.clear();
+ r_last_index += index;
+}
+
+void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
+ RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
+
+ if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
+ _new_batch(r_batch_broken, r_index);
+
+ state.canvas_instance_batches[state.current_batch_index].filter = texture_filter;
+ }
+
+ RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? state.default_repeat : p_item->texture_repeat;
+
+ if (texture_repeat != state.canvas_instance_batches[state.current_batch_index].repeat) {
+ _new_batch(r_batch_broken, r_index);
+
+ state.canvas_instance_batches[state.current_batch_index].repeat = texture_repeat;
+ }
+
+ Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform;
+ Transform2D draw_transform; // Used by transform command
+
+ Color base_color = p_item->final_modulate;
+ uint32_t base_flags = 0;
+ Size2 texpixel_size;
+
+ bool reclip = false;
+
+ bool skipping = false;
+
+ const Item::Command *c = p_item->commands;
+ while (c) {
+ if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
+ c = c->next;
+ continue;
+ }
+
+ if (c->type != Item::Command::TYPE_MESH) {
+ // For Meshes, this gets updated below.
+ _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
+ }
+
+ // Zero out most fields.
+ 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[r_index].lights[i] = 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[r_index].pad[0] = 0.0;
+ state.instance_data_array[r_index].pad[1] = 0.0;
+
+ state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
+
+ Color blend_color;
+ if (c->type == Item::Command::TYPE_RECT) {
+ const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
+ if (rect->flags & CANVAS_RECT_LCD) {
+ p_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD;
+ blend_color = rect->modulate * base_color;
+ }
+ }
+
+ if (p_blend_mode != state.canvas_instance_batches[state.current_batch_index].blend_mode || blend_color != state.canvas_instance_batches[state.current_batch_index].blend_color) {
+ _new_batch(r_batch_broken, r_index);
+ state.canvas_instance_batches[state.current_batch_index].blend_mode = p_blend_mode;
+ state.canvas_instance_batches[state.current_batch_index].blend_color = blend_color;
}
switch (c->type) {
case Item::Command::TYPE_RECT: {
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
- if (rect->flags & CANVAS_RECT_TILE) {
- current_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
+ if (rect->flags & CANVAS_RECT_TILE && state.canvas_instance_batches[state.current_batch_index].repeat != RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED) {
+ _new_batch(r_batch_broken, r_index);
+ state.canvas_instance_batches[state.current_batch_index].repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
}
- if (rect->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_RECT) {
- _render_batch(r_index);
-
- state.current_primitive_points = 0;
- state.current_command = Item::Command::TYPE_RECT;
+ if (rect->texture != state.canvas_instance_batches[state.current_batch_index].tex || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_RECT) {
+ _new_batch(r_batch_broken, r_index);
+ state.canvas_instance_batches[state.current_batch_index].tex = rect->texture;
+ state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT;
+ state.canvas_instance_batches[state.current_batch_index].command = c;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_QUAD;
}
- _bind_canvas_texture(rect->texture, current_filter, current_repeat, r_index);
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_QUAD);
+
+ _prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
Rect2 src_rect;
Rect2 dst_rect;
if (rect->texture != RID()) {
- src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * state.current_pixel_size, rect->source.size * state.current_pixel_size) : Rect2(0, 0, 1, 1);
+ src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
dst_rect = Rect2(rect->rect.position, rect->rect.size);
if (dst_rect.size.width < 0) {
@@ -625,36 +688,32 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width;
state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height;
- r_index++;
- if (r_index >= state.max_instances_per_batch - 1) {
- _render_batch(r_index);
- }
+ _add_to_batch(r_index, r_batch_broken);
} break;
case Item::Command::TYPE_NINEPATCH: {
const Item::CommandNinePatch *np = static_cast<const Item::CommandNinePatch *>(c);
- if (np->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_NINEPATCH) {
- _render_batch(r_index);
-
- state.current_primitive_points = 0;
- state.current_command = Item::Command::TYPE_NINEPATCH;
+ if (np->texture != state.canvas_instance_batches[state.current_batch_index].tex || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_NINEPATCH) {
+ _new_batch(r_batch_broken, r_index);
+ state.canvas_instance_batches[state.current_batch_index].tex = np->texture;
+ state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_NINEPATCH;
+ state.canvas_instance_batches[state.current_batch_index].command = c;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_NINEPATCH;
}
- //bind textures
- _bind_canvas_texture(np->texture, current_filter, current_repeat, r_index);
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_NINEPATCH);
+ _prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
Rect2 src_rect;
Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y);
if (np->texture == RID()) {
- state.current_pixel_size = Size2(1, 1);
+ texpixel_size = Size2(1, 1);
src_rect = Rect2(0, 0, 1, 1);
} else {
if (np->source != Rect2()) {
- src_rect = Rect2(np->source.position.x * state.current_pixel_size.width, np->source.position.y * state.current_pixel_size.height, np->source.size.x * state.current_pixel_size.width, np->source.size.y * state.current_pixel_size.height);
+ src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height);
state.instance_data_array[r_index].color_texture_pixel_size[0] = 1.0 / np->source.size.width;
state.instance_data_array[r_index].color_texture_pixel_size[1] = 1.0 / np->source.size.height;
@@ -690,32 +749,26 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].ninepatch_margins[2] = np->margin[SIDE_RIGHT];
state.instance_data_array[r_index].ninepatch_margins[3] = np->margin[SIDE_BOTTOM];
- r_index++;
- if (r_index >= state.max_instances_per_batch - 1) {
- _render_batch(r_index);
- }
+ _add_to_batch(r_index, r_batch_broken);
// Restore if overridden.
- state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x;
- state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y;
+ state.instance_data_array[r_index].color_texture_pixel_size[0] = texpixel_size.x;
+ state.instance_data_array[r_index].color_texture_pixel_size[1] = texpixel_size.y;
} break;
case Item::Command::TYPE_POLYGON: {
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
- PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
- ERR_CONTINUE(!pb);
+ // Polygon's can't be batched, so always create a new batch
+ _new_batch(r_batch_broken, r_index);
- if (polygon->texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_POLYGON) {
- _render_batch(r_index);
+ state.canvas_instance_batches[state.current_batch_index].tex = polygon->texture;
+ state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_POLYGON;
+ state.canvas_instance_batches[state.current_batch_index].command = c;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
- state.current_primitive_points = 0;
- state.current_command = Item::Command::TYPE_POLYGON;
- }
- _bind_canvas_texture(polygon->texture, current_filter, current_repeat, r_index);
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
+ _prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
- state.current_primitive = polygon->primitive;
state.instance_data_array[r_index].modulation[0] = base_color.r;
state.instance_data_array[r_index].modulation[1] = base_color.g;
state.instance_data_array[r_index].modulation[2] = base_color.b;
@@ -727,39 +780,20 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
}
- _bind_instance_data_buffer(1);
- glBindVertexArray(pb->vertex_array);
-
- if (pb->color_disabled) {
- glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
- }
-
- if (pb->index_buffer != 0) {
- glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
- } else {
- glDrawArrays(prim[polygon->primitive], 0, pb->count);
- }
- glBindVertexArray(0);
- state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-
- state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
-
- if (pb->color_disabled) {
- // Reset so this doesn't pollute other draw calls.
- glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
- }
+ _add_to_batch(r_index, r_batch_broken);
} break;
case Item::Command::TYPE_PRIMITIVE: {
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
- if (state.current_primitive_points != primitive->point_count || state.current_command != Item::Command::TYPE_PRIMITIVE) {
- _render_batch(r_index);
- state.current_primitive_points = primitive->point_count;
- state.current_command = Item::Command::TYPE_PRIMITIVE;
+ if (primitive->point_count != state.canvas_instance_batches[state.current_batch_index].primitive_points || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_PRIMITIVE) {
+ _new_batch(r_batch_broken, r_index);
+ state.canvas_instance_batches[state.current_batch_index].tex = RID();
+ state.canvas_instance_batches[state.current_batch_index].primitive_points = primitive->point_count;
+ state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_PRIMITIVE;
+ state.canvas_instance_batches[state.current_batch_index].command = c;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_PRIMITIVE;
}
- _bind_canvas_texture(RID(), current_filter, current_repeat, r_index);
- 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;
@@ -770,14 +804,16 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
state.instance_data_array[r_index].colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
}
- r_index++;
+
+ _add_to_batch(r_index, r_batch_broken);
+
if (primitive->point_count == 4) {
// Reset base data
_update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world);
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[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
+ state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
for (uint32_t j = 0; j < 3; j++) {
//second half of triangle
@@ -789,78 +825,39 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
state.instance_data_array[r_index].colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
}
- r_index++;
- }
- if (r_index >= state.max_instances_per_batch - 1) {
- _render_batch(r_index);
+
+ _add_to_batch(r_index, r_batch_broken);
}
} break;
case Item::Command::TYPE_MESH:
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
- GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
- RID mesh;
- RID mesh_instance;
- RID texture;
- Color modulate(1, 1, 1, 1);
- uint32_t instance_count = 1;
- GLuint multimesh_buffer = 0;
- uint32_t multimesh_stride = 0;
- uint32_t multimesh_color_offset = 0;
- bool multimesh_uses_color = false;
- bool multimesh_uses_custom_data = false;
+ // Mesh's can't be batched, so always create a new batch
+ _new_batch(r_batch_broken, r_index);
+ Color modulate(1, 1, 1, 1);
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
- mesh = m->mesh;
- mesh_instance = m->mesh_instance;
- texture = m->texture;
- modulate = m->modulate;
+ state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
_update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, state.instance_data_array[r_index].world);
+ modulate = m->modulate;
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
- RID multimesh = mm->multimesh;
- mesh = mesh_storage->multimesh_get_mesh(multimesh);
- texture = mm->texture;
-
- if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
- break;
- }
-
- instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
-
- if (instance_count == 0) {
- break;
+ state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
+ uint32_t instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(mm->multimesh);
+ if (instance_count > 1) {
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
}
-
- multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
- multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
- multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
- multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
- multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+ } else if (c->type == Item::Command::TYPE_PARTICLES) {
+ WARN_PRINT_ONCE("Particles not supported yet, sorry :(");
}
- // TODO: implement particles here
+ state.canvas_instance_batches[state.current_batch_index].command = c;
+ state.canvas_instance_batches[state.current_batch_index].command_type = c->type;
- if (mesh.is_null()) {
- break;
- }
-
- if (texture != state.current_tex || state.current_primitive_points != 0 || state.current_command != Item::Command::TYPE_PRIMITIVE) {
- _render_batch(r_index);
- state.current_primitive_points = 0;
- state.current_command = c->type;
- }
-
- _bind_canvas_texture(texture, current_filter, current_repeat, r_index);
- if (instance_count == 1) {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES);
- } else {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED);
- }
-
- uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
+ _prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
state.instance_data_array[r_index].modulation[0] = base_color.r * modulate.r;
state.instance_data_array[r_index].modulation[1] = base_color.g * modulate.g;
@@ -872,75 +869,9 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].dst_rect[j] = 0;
state.instance_data_array[r_index].ninepatch_margins[j] = 0;
}
- _bind_instance_data_buffer(1);
- for (uint32_t j = 0; j < surf_count; j++) {
- void *surface = mesh_storage->mesh_get_surface(mesh, j);
-
- RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
- ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
-
- GLuint vertex_array_gl = 0;
- GLuint index_array_gl = 0;
-
- uint32_t input_mask = 0; // 2D meshes always use the same vertex format
- if (mesh_instance.is_valid()) {
- mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl);
- } else {
- mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array_gl);
- }
-
- index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0);
- bool use_index_buffer = false;
- glBindVertexArray(vertex_array_gl);
- if (index_array_gl != 0) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
- use_index_buffer = true;
- }
-
- if (instance_count > 1) {
- // Bind instance buffers.
- glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
- glVertexAttribDivisor(1, 1);
- glEnableVertexAttribArray(2);
- glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
- glVertexAttribDivisor(2, 1);
-
- if (multimesh_uses_color || multimesh_uses_custom_data) {
- glEnableVertexAttribArray(5);
- glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
- glVertexAttribDivisor(5, 1);
- }
- }
-
- GLenum primitive_gl = prim[int(primitive)];
- if (instance_count == 1) {
- if (use_index_buffer) {
- glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0);
- } else {
- glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
- }
- } else {
- if (use_index_buffer) {
- glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count);
- } else {
- glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
- }
- }
-
- state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-
- state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- if (instance_count > 1) {
- glDisableVertexAttribArray(5);
- glDisableVertexAttribArray(6);
- glDisableVertexAttribArray(7);
- glDisableVertexAttribArray(8);
- }
- }
+ _add_to_batch(r_index, r_batch_broken);
} break;
+
case Item::Command::TYPE_TRANSFORM: {
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
draw_transform = transform->xform;
@@ -950,30 +881,30 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
const Item::CommandClipIgnore *ci = static_cast<const Item::CommandClipIgnore *>(c);
if (current_clip) {
if (ci->ignore != reclip) {
+ _new_batch(r_batch_broken, r_index);
if (ci->ignore) {
- glDisable(GL_SCISSOR_TEST);
+ state.canvas_instance_batches[state.current_batch_index].clip = nullptr;
reclip = true;
} else {
- // Scissor area is already set
- glEnable(GL_SCISSOR_TEST);
+ state.canvas_instance_batches[state.current_batch_index].clip = current_clip;
reclip = false;
}
}
}
} break;
+
case Item::Command::TYPE_ANIMATION_SLICE: {
- /*
const Item::CommandAnimationSlice *as = static_cast<const Item::CommandAnimationSlice *>(c);
- double current_time = RendererCompositorRD::singleton->get_total_time();
+ double current_time = RSG::rasterizer->get_total_time();
double local_time = Math::fposmod(current_time - as->offset, as->animation_length);
skipping = !(local_time >= as->slice_begin && local_time < as->slice_end);
RenderingServerDefault::redraw_request(); // animation visible means redraw request
- */
} break;
}
c = c->next;
+ r_batch_broken = false;
}
if (current_clip && reclip) {
@@ -982,66 +913,245 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
}
}
-void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
- if (r_index > 0) {
- _bind_instance_data_buffer(r_index);
- glBindVertexArray(data.canvas_quad_array);
- if (state.current_primitive_points == 0) {
- glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, r_index);
- } else {
- static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLES };
- glDrawArraysInstanced(prim[state.current_primitive_points], 0, state.current_primitive_points, r_index);
- }
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
+void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
+ ERR_FAIL_COND(!state.canvas_instance_batches[state.current_batch_index].command);
- state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
- //copy the new data into the base of the batch
- for (int i = 0; i < 4; i++) {
- state.instance_data_array[0].modulation[i] = state.instance_data_array[r_index].modulation[i];
- state.instance_data_array[0].ninepatch_margins[i] = state.instance_data_array[r_index].ninepatch_margins[i];
- state.instance_data_array[0].src_rect[i] = state.instance_data_array[r_index].src_rect[i];
- state.instance_data_array[0].dst_rect[i] = state.instance_data_array[r_index].dst_rect[i];
- state.instance_data_array[0].lights[i] = state.instance_data_array[r_index].lights[i];
- }
- state.instance_data_array[0].flags = state.instance_data_array[r_index].flags;
- state.instance_data_array[0].color_texture_pixel_size[0] = state.instance_data_array[r_index].color_texture_pixel_size[0];
- state.instance_data_array[0].color_texture_pixel_size[1] = state.instance_data_array[r_index].color_texture_pixel_size[1];
-
- state.instance_data_array[0].pad[0] = state.instance_data_array[r_index].pad[0];
- state.instance_data_array[0].pad[1] = state.instance_data_array[r_index].pad[1];
- for (int i = 0; i < 6; i++) {
- state.instance_data_array[0].world[i] = state.instance_data_array[r_index].world[i];
- }
+ // Used by Polygon and Mesh.
+ static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
- r_index = 0;
+ _bind_canvas_texture(state.canvas_instance_batches[p_index].tex, state.canvas_instance_batches[p_index].filter, state.canvas_instance_batches[p_index].repeat);
+
+ // Bind the region of the UBO used by this batch.
+ // If region exceeds the boundary of the UBO, just ignore.
+ uint32_t range_bytes = data.max_instances_per_batch * sizeof(InstanceData);
+ if (state.canvas_instance_batches[p_index].start >= (data.max_instances_per_ubo - 1) * sizeof(InstanceData)) {
+ return;
+ } else if (state.canvas_instance_batches[p_index].start >= (data.max_instances_per_ubo - data.max_instances_per_batch) * sizeof(InstanceData)) {
+ // If we have less than a full batch at the end, we can just draw it anyway.
+ // OpenGL will complain about the UBO being smaller than expected, but it should render fine.
+ range_bytes = (data.max_instances_per_ubo - 1) * sizeof(InstanceData) - state.canvas_instance_batches[p_index].start;
+ }
+
+ uint32_t range_start = state.canvas_instance_batches[p_index].start;
+ glBindBufferRange(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer].ubo, range_start, range_bytes);
+
+ switch (state.canvas_instance_batches[p_index].command_type) {
+ case Item::Command::TYPE_RECT:
+ case Item::Command::TYPE_NINEPATCH: {
+ glBindVertexArray(data.indexed_quad_array);
+ glDrawElements(GL_TRIANGLES, state.canvas_instance_batches[p_index].instance_count * 6, GL_UNSIGNED_INT, 0);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ glBindVertexArray(0);
+
+ } break;
+
+ case Item::Command::TYPE_POLYGON: {
+ const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(state.canvas_instance_batches[p_index].command);
+
+ PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
+ ERR_FAIL_COND(!pb);
+
+ glBindVertexArray(pb->vertex_array);
+
+ if (pb->color_disabled && pb->color != Color(1.0, 1.0, 1.0, 1.0)) {
+ glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
+ }
+
+ if (pb->index_buffer != 0) {
+ glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
+ } else {
+ glDrawArrays(prim[polygon->primitive], 0, pb->count);
+ }
+ glBindVertexArray(0);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ if (pb->color_disabled && pb->color != Color(1.0, 1.0, 1.0, 1.0)) {
+ // Reset so this doesn't pollute other draw calls.
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ }
+ } break;
+
+ case Item::Command::TYPE_PRIMITIVE: {
+ glBindVertexArray(data.canvas_quad_array);
+ const GLenum primitive[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLES };
+ int instance_count = state.canvas_instance_batches[p_index].instance_count;
+ if (instance_count > 1) {
+ glDrawArraysInstanced(primitive[state.canvas_instance_batches[p_index].primitive_points], 0, state.canvas_instance_batches[p_index].primitive_points, instance_count);
+ } else {
+ glDrawArrays(primitive[state.canvas_instance_batches[p_index].primitive_points], 0, state.canvas_instance_batches[p_index].primitive_points);
+ }
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ } break;
+
+ case Item::Command::TYPE_MESH:
+ case Item::Command::TYPE_MULTIMESH:
+ case Item::Command::TYPE_PARTICLES: {
+ GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ RID mesh;
+ RID mesh_instance;
+ RID texture;
+ uint32_t instance_count = 1;
+ GLuint multimesh_buffer = 0;
+ uint32_t multimesh_stride = 0;
+ uint32_t multimesh_color_offset = 0;
+ bool multimesh_uses_color = false;
+ bool multimesh_uses_custom_data = false;
+
+ if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MESH) {
+ const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(state.canvas_instance_batches[p_index].command);
+ mesh = m->mesh;
+ mesh_instance = m->mesh_instance;
+ } else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MULTIMESH) {
+ const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(state.canvas_instance_batches[p_index].command);
+ RID multimesh = mm->multimesh;
+ mesh = mesh_storage->multimesh_get_mesh(multimesh);
+
+ if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
+ break;
+ }
+
+ instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
+
+ if (instance_count == 0) {
+ break;
+ }
+
+ multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
+ multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
+ multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
+ multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
+ multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+ } else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_PARTICLES) {
+ // Do nothing for now.
+ }
+
+ ERR_FAIL_COND(mesh.is_null());
+
+ uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
+
+ for (uint32_t j = 0; j < surf_count; j++) {
+ void *surface = mesh_storage->mesh_get_surface(mesh, j);
+
+ RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
+ ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
+
+ GLuint vertex_array_gl = 0;
+ GLuint index_array_gl = 0;
+
+ uint32_t input_mask = 0; // 2D meshes always use the same vertex format
+ if (mesh_instance.is_valid()) {
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl);
+ } else {
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array_gl);
+ }
+
+ index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0);
+ bool use_index_buffer = false;
+ glBindVertexArray(vertex_array_gl);
+ if (index_array_gl != 0) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
+ use_index_buffer = true;
+ }
+
+ if (instance_count > 1) {
+ // Bind instance buffers.
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(1, 1);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(2, 1);
+
+ if (multimesh_uses_color || multimesh_uses_custom_data) {
+ glEnableVertexAttribArray(5);
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribDivisor(5, 1);
+ }
+ }
+
+ GLenum primitive_gl = prim[int(primitive)];
+ if (instance_count == 1) {
+ if (use_index_buffer) {
+ glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0);
+ } else {
+ glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface));
+ }
+ } else if (instance_count > 1) {
+ if (use_index_buffer) {
+ glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count);
+ } else {
+ glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), instance_count);
+ }
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ if (instance_count > 1) {
+ glDisableVertexAttribArray(5);
+ glDisableVertexAttribArray(6);
+ glDisableVertexAttribArray(7);
+ glDisableVertexAttribArray(8);
+ }
+ }
+
+ } break;
+ case Item::Command::TYPE_TRANSFORM:
+ case Item::Command::TYPE_CLIP_IGNORE:
+ case Item::Command::TYPE_ANIMATION_SLICE: {
+ // Can ignore these as they only impact batch creation.
+ } break;
}
}
-void RasterizerCanvasGLES3::_bind_instance_data_buffer(uint32_t p_max_index) {
- if (p_max_index == 0) {
+void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broken) {
+ if (r_index >= data.max_instances_per_ubo - 1) {
+ WARN_PRINT_ONCE("Trying to draw too many items. Please increase maximum number of items in the project settings 'rendering/gl_compatibility/item_buffer_size'");
return;
}
- // 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();
+
+ if (state.canvas_instance_batches[state.current_batch_index].instance_count >= data.max_instances_per_batch) {
+ _new_batch(r_batch_broken, r_index);
+ }
+
+ state.canvas_instance_batches[state.current_batch_index].instance_count++;
+ r_index++;
+}
+
+void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index) {
+ if (state.canvas_instance_batches.size() == 0) {
+ state.canvas_instance_batches.push_back(Batch());
+ return;
+ }
+
+ if (r_batch_broken || state.canvas_instance_batches[state.current_batch_index].instance_count == 0) {
+ return;
+ }
+
+ r_batch_broken = true;
+
+ // Copy the properties of the current batch, we will manually update the things that changed.
+ Batch new_batch = state.canvas_instance_batches[state.current_batch_index];
+ new_batch.instance_count = 0;
+ new_batch.start = state.canvas_instance_batches[state.current_batch_index].start + state.canvas_instance_batches[state.current_batch_index].instance_count * sizeof(InstanceData);
+
+ state.current_batch_index++;
+ state.canvas_instance_batches.push_back(new_batch);
+ _align_instance_data_buffer(r_index);
+}
+
+void RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant) {
+ if (p_material_data) {
+ if (p_material_data->shader_data->version.is_valid() && p_material_data->shader_data->valid) {
+ // Bind uniform buffer and textures
+ p_material_data->bind_uniforms();
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant);
} else {
- glDeleteSync(state.fences[state.current_buffer]);
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant);
}
+ } else {
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant);
}
-
- glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
-#ifdef WEB_ENABLED
- //WebGL 2.0 does not support mapping buffers, so use slow glBufferSubData instead
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * p_max_index, state.instance_data_array);
-#else
- void *ubo = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(InstanceData) * p_max_index, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
- memcpy(ubo, state.instance_data_array, sizeof(InstanceData) * p_max_index);
- glUnmapBuffer(GL_UNIFORM_BUFFER);
-#endif
}
RID RasterizerCanvasGLES3::light_create() {
@@ -1100,12 +1210,12 @@ void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backb
glBindTexture(GL_TEXTURE_2D, render_target->backbuffer);
}
- if (render_target->is_transparent) {
+ if (render_target->is_transparent || p_to_backbuffer) {
state.transparent_render_target = true;
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
state.transparent_render_target = false;
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
if (render_target && render_target->clear_requested) {
@@ -1121,30 +1231,28 @@ void RasterizerCanvasGLES3::canvas_begin(RID p_to_render_target, bool p_to_backb
glBindTexture(GL_TEXTURE_2D, tex->tex_id);
}
-void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index) {
+void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
if (p_texture == RID()) {
- p_texture = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
+ p_texture = default_canvas_texture;
}
- if (state.current_tex == p_texture) {
- return; //nothing to do, its the same
+ if (state.current_tex == p_texture && state.current_filter_mode == p_base_filter && state.current_repeat_mode == p_base_repeat) {
+ return;
}
+
state.current_tex = p_texture;
+ state.current_filter_mode = p_base_filter;
+ state.current_repeat_mode = p_base_repeat;
GLES3::CanvasTexture *ct = nullptr;
GLES3::Texture *t = texture_storage->get_texture(p_texture);
if (t) {
- //regular texture
- if (!t->canvas_texture) {
- t->canvas_texture = memnew(GLES3::CanvasTexture);
- t->canvas_texture->diffuse = p_texture;
- }
-
+ ERR_FAIL_COND(!t->canvas_texture);
ct = t->canvas_texture;
} else {
ct = texture_storage->get_canvas_texture(p_texture);
@@ -1152,7 +1260,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
if (!ct) {
// Invalid Texture RID.
- _bind_canvas_texture(default_canvas_texture, p_base_filter, p_base_repeat, r_index);
+ _bind_canvas_texture(default_canvas_texture, p_base_filter, p_base_repeat);
return;
}
@@ -1165,20 +1273,12 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse);
if (!texture) {
- state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
- GLES3::Texture *tex = texture_storage->get_texture(state.current_tex);
- state.current_tex_ptr = tex;
- ct->size_cache = Size2i(tex->width, tex->height);
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex->tex_id);
} else {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->tex_id);
-
- state.current_tex = p_texture;
- state.current_tex_ptr = texture;
- ct->size_cache = Size2i(texture->width, texture->height);
-
texture->gl_set_filter(filter);
texture->gl_set_repeat(repeat);
}
@@ -1186,45 +1286,78 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
if (!normal_map) {
- state.current_normal = RID();
- ct->use_normal_cache = false;
- glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6);
+ glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6);
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 {
glActiveTexture(GL_TEXTURE0 + 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->gl_set_filter(filter);
- texture->gl_set_repeat(repeat);
+ normal_map->gl_set_filter(filter);
+ normal_map->gl_set_repeat(repeat);
}
GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular);
if (!specular_map) {
- state.current_specular = RID();
- ct->use_specular_cache = false;
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 7);
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 {
glActiveTexture(GL_TEXTURE0 + 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->gl_set_filter(filter);
- texture->gl_set_repeat(repeat);
+ specular_map->gl_set_filter(filter);
+ specular_map->gl_set_repeat(repeat);
}
+}
- if (ct->use_specular_cache) {
+void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
+ if (p_texture == RID()) {
+ p_texture = default_canvas_texture;
+ }
+
+ GLES3::CanvasTexture *ct = nullptr;
+
+ GLES3::Texture *t = texture_storage->get_texture(p_texture);
+
+ if (t) {
+ //regular texture
+ if (!t->canvas_texture) {
+ t->canvas_texture = memnew(GLES3::CanvasTexture);
+ t->canvas_texture->diffuse = p_texture;
+ }
+
+ ct = t->canvas_texture;
+ } else {
+ ct = texture_storage->get_canvas_texture(p_texture);
+ }
+
+ if (!ct) {
+ // Invalid Texture RID.
+ _prepare_canvas_texture(default_canvas_texture, p_base_filter, p_base_repeat, r_index, r_texpixel_size);
+ return;
+ }
+
+ GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse);
+ Size2i size_cache;
+ if (!texture) {
+ ct->diffuse = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
+ GLES3::Texture *tex = texture_storage->get_texture(ct->diffuse);
+ size_cache = Size2i(tex->width, tex->height);
+ } else {
+ size_cache = Size2i(texture->width, texture->height);
+ }
+
+ GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
+
+ if (ct->specular_color.a < 0.999) {
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
} else {
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED;
}
- if (ct->use_normal_cache) {
+ if (!normal_map) {
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
} else {
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED;
@@ -1235,11 +1368,11 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.g * 255.0, 0, 255)) << 8;
state.instance_data_array[r_index].specular_shininess |= uint32_t(CLAMP(ct->specular_color.r * 255.0, 0, 255));
- state.current_pixel_size.x = 1.0 / float(ct->size_cache.x);
- state.current_pixel_size.y = 1.0 / float(ct->size_cache.y);
+ r_texpixel_size.x = 1.0 / float(size_cache.x);
+ r_texpixel_size.y = 1.0 / float(size_cache.y);
- state.instance_data_array[r_index].color_texture_pixel_size[0] = state.current_pixel_size.x;
- state.instance_data_array[r_index].color_texture_pixel_size[1] = state.current_pixel_size.y;
+ state.instance_data_array[r_index].color_texture_pixel_size[0] = r_texpixel_size.x;
+ state.instance_data_array[r_index].color_texture_pixel_size[1] = r_texpixel_size.y;
}
void RasterizerCanvasGLES3::reset_canvas() {
@@ -1431,20 +1564,43 @@ void RasterizerCanvasGLES3::free_polygon(PolygonID p_polygon) {
// Creates a new uniform buffer and uses it right away
// This expands the instance buffer continually
-// In theory allocations can reach as high as number_of_draw_calls * 3 frames
+// In theory allocations can reach as high as number of windows * 3 frames
// because OpenGL can start rendering subsequent frames before finishing the current one
void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
GLuint new_buffer;
glGenBuffers(1, &new_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, new_buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * state.max_instances_per_batch, nullptr, GL_DYNAMIC_DRAW);
+ glBufferData(GL_UNIFORM_BUFFER, data.max_instance_buffer_size, nullptr, GL_DYNAMIC_DRAW);
state.current_buffer = (state.current_buffer + 1);
- state.canvas_instance_data_buffers.insert(state.current_buffer, new_buffer);
- state.fences.insert(state.current_buffer, GLsync());
+ DataBuffer db;
+ db.ubo = new_buffer;
+ db.last_frame_used = RSG::rasterizer->get_frame_number();
+ state.canvas_instance_data_buffers.insert(state.current_buffer, db);
state.current_buffer = state.current_buffer % state.canvas_instance_data_buffers.size();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
+// Batch start positions need to be aligned to the device's GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT.
+// This needs to be called anytime a new batch is created.
+void RasterizerCanvasGLES3::_align_instance_data_buffer(uint32_t &r_index) {
+ if (GLES3::Config::get_singleton()->uniform_buffer_offset_alignment > int(sizeof(InstanceData))) {
+ uint32_t offset = state.canvas_instance_batches[state.current_batch_index].start % GLES3::Config::get_singleton()->uniform_buffer_offset_alignment;
+ if (offset > 0) {
+ // uniform_buffer_offset_alignment can be 4, 16, 32, or 256. Our instance batches are 128 bytes.
+ // Accordingly, this branch is only triggered if we are 128 bytes off.
+ uint32_t offset_bytes = GLES3::Config::get_singleton()->uniform_buffer_offset_alignment - offset;
+ state.canvas_instance_batches[state.current_batch_index].start += offset_bytes;
+ // Offset the instance array so it stays in sync with batch start points.
+ // This creates gaps in the instance buffer with wasted space, but we can't help it.
+ r_index += offset_bytes / sizeof(InstanceData);
+ if (r_index > 0) {
+ // In this case we need to copy over the basic data.
+ state.instance_data_array[r_index] = state.instance_data_array[r_index - 1];
+ }
+ }
+ }
+}
+
void RasterizerCanvasGLES3::set_time(double p_time) {
state.time = p_time;
}
@@ -1457,9 +1613,11 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
singleton = this;
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
+ polygon_buffers.last_id = 1;
// quad buffer
{
glGenBuffers(1, &data.canvas_quad_vertices);
@@ -1583,25 +1741,58 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
int uniform_max_size = config->max_uniform_buffer_size;
if (uniform_max_size < 65536) {
- state.max_lights_per_render = 64;
- state.max_instances_per_batch = 128;
+ data.max_lights_per_render = 64;
+ data.max_instances_per_batch = 128;
} else {
- state.max_lights_per_render = 256;
- state.max_instances_per_batch = 512;
+ data.max_lights_per_render = 256;
+ data.max_instances_per_batch = 512;
}
- // Reserve 64 Uniform Buffers for instance data
- state.canvas_instance_data_buffers.resize(64);
- 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);
+ // Reserve 3 Uniform Buffers for instance data Frame N, N+1 and N+2
+ data.max_instances_per_ubo = MAX(data.max_instances_per_batch, uint32_t(GLOBAL_GET("rendering/gl_compatibility/item_buffer_size")));
+ data.max_instance_buffer_size = data.max_instances_per_ubo * sizeof(InstanceData); // 16,384 instances * 128 bytes = 2,097,152 bytes = 2,048 kb
+ state.canvas_instance_data_buffers.resize(3);
+ state.canvas_instance_batches.reserve(200);
+
+ for (int i = 0; i < 3; i++) {
+ GLuint new_buffer;
+ glGenBuffers(1, &new_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, new_buffer);
+ glBufferData(GL_UNIFORM_BUFFER, data.max_instance_buffer_size, nullptr, GL_DYNAMIC_DRAW);
+ DataBuffer db;
+ db.ubo = new_buffer;
+ db.last_frame_used = 0;
+ db.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ state.canvas_instance_data_buffers[i] = db;
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- state.instance_data_array = memnew_arr(InstanceData, state.max_instances_per_batch);
+ state.instance_data_array = memnew_arr(InstanceData, data.max_instances_per_ubo);
+
+ {
+ const uint32_t no_of_instances = data.max_instances_per_batch;
+
+ glGenVertexArrays(1, &data.indexed_quad_array);
+ glBindVertexArray(data.indexed_quad_array);
+ glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
+
+ const uint32_t num_indices = 6;
+ const uint32_t quad_indices[num_indices] = { 0, 2, 1, 3, 2, 0 };
+
+ const uint32_t total_indices = no_of_instances * num_indices;
+ uint32_t *indices = new uint32_t[total_indices];
+ for (uint32_t i = 0; i < total_indices; i++) {
+ uint32_t quad = i / num_indices;
+ uint32_t quad_local = i % num_indices;
+ indices[i] = quad_indices[quad_local] + quad * num_indices;
+ }
+
+ glGenBuffers(1, &data.indexed_quad_buffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.indexed_quad_buffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * total_indices, indices, GL_STATIC_DRAW);
+ glBindVertexArray(0);
+ delete[] indices;
+ }
glGenBuffers(1, &state.canvas_state_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_state_buffer);
@@ -1610,12 +1801,12 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
String global_defines;
global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
- 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";
+ global_defines += "#define MAX_LIGHTS " + itos(data.max_instances_per_batch) + "\n";
+ global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(data.max_instances_per_batch) + "\n";
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);
+ data.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create();
+ GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
{
default_canvas_group_shader = material_storage->shader_allocate();
@@ -1642,16 +1833,16 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
- state.current_shader_version = state.canvas_shader_default_version;
+ default_canvas_texture = texture_storage->canvas_texture_allocate();
+ texture_storage->canvas_texture_initialize(default_canvas_texture);
+
state.time = 0.0;
}
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- memdelete_arr(state.instance_data_array);
-
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version);
+ material_storage->shaders.canvas_shader.version_free(data.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
singleton = nullptr;
@@ -1661,6 +1852,9 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
glDeleteBuffers(1, &data.canvas_quad_vertices);
glDeleteVertexArrays(1, &data.canvas_quad_array);
+
+ GLES3::TextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
+ memfree(state.instance_data_array);
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 372ac00493..15c2ca5710 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -125,6 +125,23 @@ public:
uint32_t pad2;
};
+ struct PolygonBuffers {
+ GLuint vertex_buffer;
+ GLuint vertex_array;
+ GLuint index_buffer;
+ int count = 0;
+ bool color_disabled = false;
+ Color color;
+ };
+
+ struct {
+ HashMap<PolygonID, PolygonBuffers> polygons;
+ PolygonID last_id = 0;
+ } polygon_buffers;
+
+ RendererCanvasRender::PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override;
+ void free_polygon(PolygonID p_polygon) override;
+
struct InstanceData {
float world[6];
float color_texture_pixel_size[2];
@@ -156,42 +173,71 @@ public:
GLuint canvas_quad_vertices;
GLuint canvas_quad_array;
+ GLuint indexed_quad_buffer;
+ GLuint indexed_quad_array;
+
GLuint particle_quad_vertices;
GLuint particle_quad_array;
GLuint ninepatch_vertices;
GLuint ninepatch_elements;
+
+ RID canvas_shader_default_version;
+
+ uint32_t max_lights_per_render;
+ uint32_t max_lights_per_item;
+ uint32_t max_instances_per_batch = 512;
+ uint32_t max_instances_per_ubo = 16384;
+ uint32_t max_instance_buffer_size = 16384 * 128;
} data;
+ struct Batch {
+ // Position in the UBO measured in bytes
+ uint32_t start = 0;
+ uint32_t instance_count = 0;
+
+ RID tex = RID();
+ RS::CanvasItemTextureFilter filter = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
+ RS::CanvasItemTextureRepeat repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
+
+ GLES3::CanvasShaderData::BlendMode blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX;
+ Color blend_color = Color(1.0, 1.0, 1.0, 1.0);
+
+ Item *clip = nullptr;
+
+ RID material = RID();
+ GLES3::CanvasMaterialData *material_data = nullptr;
+ CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD;
+
+ const Item::Command *command = nullptr;
+ Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch.
+ uint32_t primitive_points = 0;
+ };
+
+ struct DataBuffer {
+ GLuint ubo = 0;
+ uint64_t last_frame_used = -3;
+ GLsync fence = GLsync();
+ };
+
struct State {
GLuint canvas_state_buffer;
- LocalVector<GLuint> canvas_instance_data_buffers;
- LocalVector<GLsync> fences;
+ LocalVector<DataBuffer> canvas_instance_data_buffers;
+ LocalVector<Batch> canvas_instance_batches;
uint32_t current_buffer = 0;
+ uint32_t current_buffer_index = 0;
+ uint32_t current_batch_index = 0;
InstanceData *instance_data_array = nullptr;
- bool canvas_texscreen_used;
- RID canvas_shader_current_version;
- RID canvas_shader_default_version;
RID current_tex = RID();
- Size2 current_pixel_size = Size2();
- RID current_normal = RID();
- RID current_specular = RID();
- GLES3::Texture *current_tex_ptr;
- RID current_shader_version = RID();
- RS::PrimitiveType current_primitive = RS::PRIMITIVE_MAX;
- uint32_t current_primitive_points = 0;
- Item::Command::Type current_command = Item::Command::TYPE_RECT;
+ RS::CanvasItemTextureFilter current_filter_mode = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
+ RS::CanvasItemTextureRepeat current_repeat_mode = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
bool transparent_render_target = false;
double time = 0.0;
- uint32_t max_lights_per_render;
- uint32_t max_lights_per_item;
- uint32_t max_instances_per_batch;
-
RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
} state;
@@ -229,31 +275,18 @@ public:
bool free(RID p_rid) override;
void update() override;
- void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index);
-
- struct PolygonBuffers {
- GLuint vertex_buffer;
- GLuint vertex_array;
- GLuint index_buffer;
- int count;
- bool color_disabled = false;
- Color color;
- };
-
- struct {
- HashMap<PolygonID, PolygonBuffers> polygons;
- PolygonID last_id;
- } polygon_buffers;
-
- RendererCanvasRender::PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override;
- void free_polygon(PolygonID p_polygon) override;
+ void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat);
+ void _prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size);
void 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) override;
- void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
- void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color);
- void _render_batch(uint32_t &p_max_index);
- void _bind_instance_data_buffer(uint32_t p_max_index);
+ void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer = false);
+ void _record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
+ void _render_batch(Light *p_lights, uint32_t p_index);
+ void _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant);
+ void _new_batch(bool &r_batch_broken, uint32_t &r_index);
+ void _add_to_batch(uint32_t &r_index, bool &r_batch_broken);
void _allocate_instance_data_buffer();
+ void _align_instance_data_buffer(uint32_t &r_index);
void set_time(double p_time);
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 3575837794..0836a21254 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -100,9 +100,9 @@ void RasterizerGLES3::begin_frame(double frame_step) {
canvas->set_time(time_total);
scene->set_time(time_total, frame_step);
- GLES3::Utilities *utilities = GLES3::Utilities::get_singleton();
- utilities->info.render_final = utilities->info.render;
- utilities->info.render.reset();
+ GLES3::Utilities *utils = GLES3::Utilities::get_singleton();
+ utils->info.render_final = utils->info.render;
+ utils->info.render.reset();
//scene->iteration();
}
@@ -275,16 +275,10 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() {
}
void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) {
- GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
-
- GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
+ GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton()->get_render_target(p_render_target);
ERR_FAIL_COND(!rt);
- if (rt->external.fbo != 0) {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
- } else {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
- }
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
// Flip content upside down to correct for coordinates.
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 97543af0d5..431515fd0d 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -103,8 +103,9 @@ public:
low_end = true;
}
- uint64_t get_frame_number() const { return frame; }
- double get_frame_delta_time() const { return delta; }
+ _ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
+ _ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
+ _ALWAYS_INLINE_ double get_total_time() const { return time_total; }
RasterizerGLES3();
~RasterizerGLES3();
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 85b35639ec..4c71edc24c 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -34,7 +34,6 @@
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
#include "storage/config.h"
-#include "storage/light_storage.h"
#include "storage/mesh_storage.h"
#include "storage/texture_storage.h"
@@ -70,7 +69,7 @@ void RasterizerSceneGLES3::GeometryInstanceGLES3::pair_light_instances(const RID
spot_lights.clear();
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = RasterizerSceneGLES3::get_singleton()->light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = GLES3::LightStorage::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
if (omni_light_count < (uint32_t)config->max_lights_per_object) {
@@ -399,32 +398,6 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
ginstance->dirty_list_element.remove_from_list();
}
-/* SHADOW ATLAS API */
-
-RID RasterizerSceneGLES3::shadow_atlas_create() {
- return RID();
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
-}
-
-void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
-}
-
-bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
- return false;
-}
-
-void RasterizerSceneGLES3::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
-}
-
-int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) {
- return 0;
-}
-
-void RasterizerSceneGLES3::set_directional_shadow_count(int p_count) {
-}
-
/* SKY API */
void RasterizerSceneGLES3::_free_sky_data(Sky *p_sky) {
@@ -625,7 +598,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons
if (shader_data->uses_light) {
sky_globals.directional_light_count = 0;
for (int i = 0; i < (int)p_lights.size(); i++) {
- LightInstance *li = light_instance_owner.get_or_null(p_lights[i]);
+ GLES3::LightInstance *li = GLES3::LightStorage::get_singleton()->get_light_instance(p_lights[i]);
if (!li) {
continue;
}
@@ -737,7 +710,6 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
RS::EnvironmentBG background = environment_get_background(p_env);
if (sky) {
- ERR_FAIL_COND(!sky);
sky_material = sky->material;
if (sky_material.is_valid()) {
@@ -781,7 +753,7 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
@@ -882,7 +854,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.matrix[2][0], cm.matrix[0][0], cm.matrix[2][1], cm.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glBindVertexArray(sky_globals.screen_triangle_array);
@@ -1085,38 +1057,6 @@ void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQ
void RasterizerSceneGLES3::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
}
-RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
- RID li = light_instance_owner.make_rid(LightInstance());
-
- LightInstance *light_instance = light_instance_owner.get_or_null(li);
-
- light_instance->self = li;
- light_instance->light = p_light;
- light_instance->light_type = RSG::light_storage->light_get_type(p_light);
-
- return li;
-}
-
-void RasterizerSceneGLES3::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->transform = p_transform;
-}
-
-void RasterizerSceneGLES3::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->aabb = p_aabb;
-}
-
-void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
-}
-
-void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
-}
-
RID RasterizerSceneGLES3::fog_volume_instance_create(RID p_fog_volume) {
return RID();
}
@@ -1135,57 +1075,6 @@ Vector3 RasterizerSceneGLES3::fog_volume_instance_get_position(RID p_fog_volume_
return Vector3();
}
-RID RasterizerSceneGLES3::reflection_atlas_create() {
- return RID();
-}
-
-int RasterizerSceneGLES3::reflection_atlas_get_size(RID p_ref_atlas) const {
- return 0;
-}
-
-void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
-}
-
-RID RasterizerSceneGLES3::reflection_probe_instance_create(RID p_probe) {
- return RID();
-}
-
-void RasterizerSceneGLES3::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
-}
-
-void RasterizerSceneGLES3::reflection_probe_release_atlas_index(RID p_instance) {
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_needs_redraw(RID p_instance) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_has_reflection(RID p_instance) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- return false;
-}
-
-bool RasterizerSceneGLES3::reflection_probe_instance_postprocess_step(RID p_instance) {
- return true;
-}
-
-RID RasterizerSceneGLES3::decal_instance_create(RID p_decal) {
- return RID();
-}
-
-void RasterizerSceneGLES3::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
-}
-
-RID RasterizerSceneGLES3::lightmap_instance_create(RID p_lightmap) {
- return RID();
-}
-
-void RasterizerSceneGLES3::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
-}
-
RID RasterizerSceneGLES3::voxel_gi_instance_create(RID p_voxel_gi) {
return RID();
}
@@ -1258,13 +1147,13 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
if (inst->omni_light_count) {
inst->omni_light_gl_cache.resize(inst->omni_light_count);
for (uint32_t j = 0; j < inst->omni_light_count; j++) {
- inst->omni_light_gl_cache[j] = light_instance_get_gl_id(inst->omni_lights[j]);
+ inst->omni_light_gl_cache[j] = GLES3::LightStorage::get_singleton()->light_instance_get_gl_id(inst->omni_lights[j]);
}
}
if (inst->spot_light_count) {
inst->spot_light_gl_cache.resize(inst->spot_light_count);
for (uint32_t j = 0; j < inst->spot_light_count; j++) {
- inst->spot_light_gl_cache[j] = light_instance_get_gl_id(inst->spot_lights[j]);
+ inst->spot_light_gl_cache[j] = GLES3::LightStorage::get_singleton()->light_instance_get_gl_id(inst->spot_lights[j]);
}
}
}
@@ -1502,7 +1391,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
int num_lights = lights.size();
for (int i = 0; i < num_lights; i++) {
- LightInstance *li = light_instance_owner.get_or_null(lights[i]);
+ GLES3::LightInstance *li = GLES3::LightStorage::get_singleton()->get_light_instance(lights[i]);
if (!li) {
continue;
}
@@ -1607,12 +1496,12 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
}
if (r_omni_light_count) {
- SortArray<InstanceSort<LightInstance>> sorter;
+ SortArray<InstanceSort<GLES3::LightInstance>> sorter;
sorter.sort(scene_state.omni_light_sort, r_omni_light_count);
}
if (r_spot_light_count) {
- SortArray<InstanceSort<LightInstance>> sorter;
+ SortArray<InstanceSort<GLES3::LightInstance>> sorter;
sorter.sort(scene_state.spot_light_sort, r_spot_light_count);
}
@@ -1620,7 +1509,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
uint32_t index = (i < r_omni_light_count) ? i : i - (r_omni_light_count);
LightData &light_data = (i < r_omni_light_count) ? scene_state.omni_lights[index] : scene_state.spot_lights[index];
RS::LightType type = (i < r_omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
- LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
+ GLES3::LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
RID base = li->light;
Transform3D light_transform = li->transform;
@@ -2043,7 +1932,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
} break;
}
- if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
+ if constexpr (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 2);
GLuint texture_to_bind = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_CUBEMAP_BLACK))->tex_id;
if (p_render_data->environment.is_valid()) {
@@ -2074,7 +1963,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
GLES3::SceneMaterialData *material_data;
void *mesh_surface;
- if (p_pass_mode == PASS_MODE_SHADOW) {
+ if constexpr (p_pass_mode == PASS_MODE_SHADOW) {
shader = surf->shader_shadow;
material_data = surf->material_shadow;
mesh_surface = surf->surface_shadow;
@@ -2088,7 +1977,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
continue;
}
- if (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
+ if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
if (scene_state.current_depth_test != shader->depth_test) {
if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) {
glDisable(GL_DEPTH_TEST);
@@ -2115,9 +2004,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
scene_state.current_depth_draw = shader->depth_draw;
}
- if (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_ADDITIVE) {
+ if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_ADDITIVE) {
GLES3::SceneShaderData::BlendMode desired_blend_mode;
- if (p_pass_mode == PASS_MODE_COLOR_ADDITIVE) {
+ if constexpr (p_pass_mode == PASS_MODE_COLOR_ADDITIVE) {
desired_blend_mode = GLES3::SceneShaderData::BLEND_MODE_ADD;
} else {
desired_blend_mode = shader->blend_mode;
@@ -2241,9 +2130,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
if (prev_shader != shader || prev_variant != instance_variant) {
material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant);
float opaque_prepass_threshold = 0.0;
- if (p_pass_mode == PASS_MODE_DEPTH) {
+ if constexpr (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
- } else if (p_pass_mode == PASS_MODE_SHADOW) {
+ } else if constexpr (p_pass_mode == PASS_MODE_SHADOW) {
opaque_prepass_threshold = 0.1;
}
@@ -2391,10 +2280,8 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
ERR_FAIL_COND_V(!sky, false);
_free_sky_data(sky);
sky_owner.free(p_rid);
- } else if (light_instance_owner.owns(p_rid)) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
- ERR_FAIL_COND_V(!light_instance, false);
- light_instance_owner.free(p_rid);
+ } else if (GLES3::LightStorage::get_singleton()->owns_light_instance(p_rid)) {
+ GLES3::LightStorage::get_singleton()->light_instance_free(p_rid);
} else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
//not much to delete, just free it
RSG::camera_attributes->camera_attributes_free(p_rid);
@@ -2434,13 +2321,13 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
uint32_t light_buffer_size = config->max_renderable_lights * sizeof(LightData);
scene_state.omni_lights = memnew_arr(LightData, config->max_renderable_lights);
- scene_state.omni_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights);
+ scene_state.omni_light_sort = memnew_arr(InstanceSort<GLES3::LightInstance>, config->max_renderable_lights);
glGenBuffers(1, &scene_state.omni_light_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, scene_state.omni_light_buffer);
glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW);
scene_state.spot_lights = memnew_arr(LightData, config->max_renderable_lights);
- scene_state.spot_light_sort = memnew_arr(InstanceSort<LightInstance>, config->max_renderable_lights);
+ scene_state.spot_light_sort = memnew_arr(InstanceSort<GLES3::LightInstance>, config->max_renderable_lights);
glGenBuffers(1, &scene_state.spot_light_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, scene_state.spot_light_buffer);
glBufferData(GL_UNIFORM_BUFFER, light_buffer_size, nullptr, GL_STREAM_DRAW);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index f0dc972678..d11dc14080 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -44,6 +44,7 @@
#include "shader_gles3.h"
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/sky.glsl.gen.h"
+#include "storage/light_storage.h"
#include "storage/material_storage.h"
#include "storage/render_scene_buffers_gles3.h"
#include "storage/utilities.h"
@@ -183,34 +184,6 @@ private:
};
static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes");
- struct LightInstance {
- RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
-
- AABB aabb;
- RID self;
- RID light;
- Transform3D transform;
-
- Vector3 light_vector;
- Vector3 spot_vector;
- float linear_att = 0.0;
-
- uint64_t shadow_pass = 0;
- uint64_t last_scene_pass = 0;
- uint64_t last_scene_shadow_pass = 0;
- uint64_t last_pass = 0;
- uint32_t cull_mask = 0;
- uint32_t light_directional_index = 0;
-
- Rect2 directional_rect;
-
- uint32_t gl_id = -1;
-
- LightInstance() {}
- };
-
- mutable RID_Owner<LightInstance> light_instance_owner;
-
class GeometryInstanceGLES3;
// Cached data for drawing surfaces
@@ -398,8 +371,8 @@ private:
LightData *omni_lights = nullptr;
LightData *spot_lights = nullptr;
- InstanceSort<LightInstance> *omni_light_sort;
- InstanceSort<LightInstance> *spot_light_sort;
+ InstanceSort<GLES3::LightInstance> *omni_light_sort;
+ InstanceSort<GLES3::LightInstance> *spot_light_sort;
GLuint omni_light_buffer = 0;
GLuint spot_light_buffer = 0;
uint32_t omni_light_count = 0;
@@ -605,17 +578,6 @@ public:
uint32_t geometry_instance_get_pair_mask() override;
- /* SHADOW ATLAS API */
-
- RID shadow_atlas_create() override;
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
-
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
- int get_directional_light_shadow_size(RID p_light_intance) override;
- void set_directional_shadow_count(int p_count) override;
-
/* SDFGI UPDATE */
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
@@ -666,45 +628,12 @@ public:
void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
- RID light_instance_create(RID p_light) override;
- void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
- void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
- void light_instance_mark_visible(RID p_light_instance) override;
-
- _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->light_type;
- }
- _FORCE_INLINE_ uint32_t light_instance_get_gl_id(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->gl_id;
- }
-
RID fog_volume_instance_create(RID p_fog_volume) override;
void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override;
void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override;
RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override;
Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override;
- RID reflection_atlas_create() override;
- int reflection_atlas_get_size(RID p_ref_atlas) const override;
- void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
-
- RID reflection_probe_instance_create(RID p_probe) override;
- void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
- void reflection_probe_release_atlas_index(RID p_instance) override;
- bool reflection_probe_instance_needs_redraw(RID p_instance) override;
- bool reflection_probe_instance_has_reflection(RID p_instance) override;
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
- bool reflection_probe_instance_postprocess_step(RID p_instance) override;
-
- RID decal_instance_create(RID p_decal) override;
- void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
-
- RID lightmap_instance_create(RID p_lightmap) override;
- void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
-
RID voxel_gi_instance_create(RID p_voxel_gi) override;
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
bool voxel_gi_needs_update(RID p_probe) const override;
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 7334100575..a177112476 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -60,20 +60,18 @@ out vec2 pixel_size_interp;
void main() {
vec4 instance_custom = vec4(0.0);
- draw_data_instance = gl_InstanceID;
-#ifdef USE_PRIMITIVE
- //weird bug,
- //this works
+#ifdef USE_PRIMITIVE
+ draw_data_instance = gl_InstanceID;
vec2 vertex;
vec2 uv;
vec4 color;
- if (gl_VertexID == 0) {
+ if (gl_VertexID % 3 == 0) {
vertex = draw_data[draw_data_instance].point_a;
uv = draw_data[draw_data_instance].uv_a;
color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_a_rg), unpackHalf2x16(draw_data[draw_data_instance].color_a_ba));
- } else if (gl_VertexID == 1) {
+ } else if (gl_VertexID % 3 == 1) {
vertex = draw_data[draw_data_instance].point_b;
uv = draw_data[draw_data_instance].uv_b;
color = vec4(unpackHalf2x16(draw_data[draw_data_instance].color_b_rg), unpackHalf2x16(draw_data[draw_data_instance].color_b_ba));
@@ -86,6 +84,7 @@ void main() {
vec4 bone_weights = vec4(0.0);
#elif defined(USE_ATTRIBUTES)
+ draw_data_instance = gl_InstanceID;
#ifdef USE_INSTANCING
draw_data_instance = 0;
#endif
@@ -103,9 +102,9 @@ void main() {
#endif
#else
-
- vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- vec2 vertex_base = vertex_base_arr[gl_VertexID];
+ draw_data_instance = gl_VertexID / 6;
+ vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
+ vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
vec2 uv = draw_data[draw_data_instance].src_rect.xy + abs(draw_data[draw_data_instance].src_rect.zw) * ((draw_data[draw_data_instance].flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
vec4 color = draw_data[draw_data_instance].modulation;
@@ -127,6 +126,8 @@ void main() {
}
#endif
+ vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+
#ifdef USE_POINT_SIZE
float point_size = 1.0;
#endif
@@ -393,6 +394,8 @@ void main() {
vec2 screen_uv = vec2(0.0);
#endif
+ vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+
vec3 light_vertex = vec3(vertex, 0.0);
vec2 shadow_vertex = vertex;
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 6cc65e7bb2..242c1ce0a9 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -86,6 +86,8 @@ Config::Config() {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
+ glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_offset_alignment);
+
// the use skeleton software path should be used if either float texture is not supported,
// OR max_vertex_texture_image_units is zero
use_skeleton_software = (float_texture_supported == false) || (max_vertex_texture_image_units == 0);
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index b83c83f425..fe18345775 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -64,6 +64,8 @@ public:
int max_renderable_lights = 0;
int max_lights_per_object = 0;
+ int uniform_buffer_offset_alignment = 0;
+
// TODO implement wireframe in OpenGL
// bool generate_wireframes;
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 6411590aee..b6bd4a2760 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -333,6 +333,46 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
ERR_FAIL_V(AABB());
}
+/* LIGHT INSTANCE API */
+
+RID LightStorage::light_instance_create(RID p_light) {
+ RID li = light_instance_owner.make_rid(LightInstance());
+
+ LightInstance *light_instance = light_instance_owner.get_or_null(li);
+
+ light_instance->self = li;
+ light_instance->light = p_light;
+ light_instance->light_type = light_get_type(p_light);
+
+ return li;
+}
+
+void LightStorage::light_instance_free(RID p_light_instance) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+ light_instance_owner.free(p_light_instance);
+}
+
+void LightStorage::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->transform = p_transform;
+}
+
+void LightStorage::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->aabb = p_aabb;
+}
+
+void LightStorage::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+}
+
+void LightStorage::light_instance_mark_visible(RID p_light_instance) {
+}
+
/* PROBE API */
RID LightStorage::reflection_probe_allocate() {
@@ -419,6 +459,53 @@ float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
return 0.0;
}
+/* REFLECTION ATLAS */
+
+RID LightStorage::reflection_atlas_create() {
+ return RID();
+}
+
+void LightStorage::reflection_atlas_free(RID p_ref_atlas) {
+}
+
+int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const {
+ return 0;
+}
+
+void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
+}
+
+/* REFLECTION PROBE INSTANCE */
+
+RID LightStorage::reflection_probe_instance_create(RID p_probe) {
+ return RID();
+}
+
+void LightStorage::reflection_probe_instance_free(RID p_instance) {
+}
+
+void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
+}
+
+void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
+}
+
+bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
+ return false;
+}
+
+bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
+ return true;
+}
+
/* LIGHTMAP CAPTURE */
RID LightStorage::lightmap_allocate() {
@@ -484,6 +571,18 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
return 0;
}
+/* LIGHTMAP INSTANCE */
+
+RID LightStorage::lightmap_instance_create(RID p_lightmap) {
+ return RID();
+}
+
+void LightStorage::lightmap_instance_free(RID p_lightmap) {
+}
+
+void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
+}
+
/* LIGHT SHADOW MAPPING */
/*
@@ -584,4 +683,36 @@ void LightStorage::canvas_light_occluder_set_polylines(RID p_occluder, const Poo
}
*/
+/* SHADOW ATLAS API */
+
+RID LightStorage::shadow_atlas_create() {
+ return RID();
+}
+
+void LightStorage::shadow_atlas_free(RID p_atlas) {
+}
+
+void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
+}
+
+void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
+}
+
+bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
+ return false;
+}
+
+void LightStorage::shadow_atlas_update(RID p_atlas) {
+}
+
+void LightStorage::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
+}
+
+int LightStorage::get_directional_light_shadow_size(RID p_light_intance) {
+ return 0;
+}
+
+void LightStorage::set_directional_shadow_count(int p_count) {
+}
+
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index 8b708116ac..12cb2c4393 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -76,6 +76,33 @@ struct Light {
Dependency dependency;
};
+/* Light instance */
+struct LightInstance {
+ RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
+
+ AABB aabb;
+ RID self;
+ RID light;
+ Transform3D transform;
+
+ Vector3 light_vector;
+ Vector3 spot_vector;
+ float linear_att = 0.0;
+
+ uint64_t shadow_pass = 0;
+ uint64_t last_scene_pass = 0;
+ uint64_t last_scene_shadow_pass = 0;
+ uint64_t last_pass = 0;
+ uint32_t cull_mask = 0;
+ uint32_t light_directional_index = 0;
+
+ Rect2 directional_rect;
+
+ uint32_t gl_id = -1;
+
+ LightInstance() {}
+};
+
/* REFLECTION PROBE */
struct ReflectionProbe {
@@ -128,6 +155,9 @@ private:
/* LIGHT */
mutable RID_Owner<Light, true> light_owner;
+ /* Light instance */
+ mutable RID_Owner<LightInstance> light_instance_owner;
+
/* REFLECTION PROBE */
mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
@@ -268,6 +298,28 @@ public:
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
virtual uint64_t light_get_version(RID p_light) const override;
+ /* LIGHT INSTANCE API */
+
+ LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); };
+ bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); };
+
+ virtual RID light_instance_create(RID p_light) override;
+ virtual void light_instance_free(RID p_light_instance) override;
+
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
+ virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_mark_visible(RID p_light_instance) override;
+
+ _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->light_type;
+ }
+ _FORCE_INLINE_ uint32_t light_instance_get_gl_id(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->gl_id;
+ }
+
/* PROBE API */
virtual RID reflection_probe_allocate() override;
@@ -298,6 +350,24 @@ public:
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+ /* REFLECTION ATLAS */
+
+ virtual RID reflection_atlas_create() override;
+ virtual void reflection_atlas_free(RID p_ref_atlas) override;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
+
+ /* REFLECTION PROBE INSTANCE */
+
+ virtual RID reflection_probe_instance_create(RID p_probe) override;
+ virtual void reflection_probe_instance_free(RID p_instance) override;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) override;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
+
/* LIGHTMAP CAPTURE */
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
@@ -338,6 +408,26 @@ public:
RID canvas_light_occluder_create();
void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines);
*/
+
+ /* LIGHTMAP INSTANCE */
+
+ virtual RID lightmap_instance_create(RID p_lightmap) override;
+ virtual void lightmap_instance_free(RID p_lightmap) override;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
+
+ /* SHADOW ATLAS API */
+
+ virtual RID shadow_atlas_create() override;
+ virtual void shadow_atlas_free(RID p_atlas) override;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
+
+ virtual void shadow_atlas_update(RID p_atlas) override;
+
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
+ virtual int get_directional_light_shadow_size(RID p_light_intance) override;
+ virtual void set_directional_shadow_count(int p_count) override;
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 687e98ba58..8e6009c943 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -714,7 +714,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
Projection v = value;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- gui[i * 4 + j] = v.matrix[i][j];
+ gui[i * 4 + j] = v.columns[i][j];
}
}
}
@@ -1393,7 +1393,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_MAP"] = "normal_map";
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["TEXTURE"] = "color_texture";
- actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size";
+ actions.renames["TEXTURE_PIXEL_SIZE"] = "color_texture_pixel_size";
actions.renames["NORMAL_TEXTURE"] = "normal_texture";
actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture";
actions.renames["SPECULAR_SHININESS"] = "specular_shininess";
@@ -1406,6 +1406,8 @@ MaterialStorage::MaterialStorage() {
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["LIGHT_POSITION"] = "light_position";
+ actions.renames["LIGHT_DIRECTION"] = "light_direction";
+ actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT_ENERGY"] = "light_energy";
actions.renames["LIGHT"] = "light";
@@ -1654,7 +1656,7 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
- actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
+ actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISION_SCALE\n";
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1;
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 65c46631ed..6504c7748c 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -494,7 +494,7 @@ public:
static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ p_array[i * 4 + j] = p_mtx.columns[i][j];
}
}
}
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index a801b3285a..442bd69b55 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -666,6 +666,8 @@ void TextureStorage::texture_free(RID p_texture) {
}
void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+ ERR_FAIL_COND(p_image.is_null());
+
Texture texture;
texture.width = p_image->get_width();
texture.height = p_image->get_height();
@@ -1181,6 +1183,18 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
return AABB();
}
+/* DECAL INSTANCE API */
+
+RID TextureStorage::decal_instance_create(RID p_decal) {
+ return RID();
+}
+
+void TextureStorage::decal_instance_free(RID p_decal_instance) {
+}
+
+void TextureStorage::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
+}
+
/* RENDER TARGET API */
GLuint TextureStorage::system_fbo = 0;
@@ -1329,24 +1343,6 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
rt->fbo = 0;
rt->color = 0;
}
- /*
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // clean up our texture
- Texture *t = get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- }
- */
Texture *tex = get_texture(rt->texture);
tex->alloc_height = 0;
@@ -1398,6 +1394,13 @@ void TextureStorage::render_target_set_position(RID p_render_target, int p_x, in
rt->position = Point2i(p_x, p_y);
}
+Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Point2i());
+
+ return rt->position;
+};
+
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -1414,9 +1417,9 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
}
// TODO: convert to Size2i internally
-Size2i TextureStorage::render_target_get_size(RID p_render_target) {
+Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
+ ERR_FAIL_COND_V(!rt, Size2i());
return rt->size;
}
@@ -1425,105 +1428,7 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- if (rt->external.fbo == 0) {
- return rt->texture;
- } else {
- return rt->external.texture;
- }
-}
-
-void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_texture_id == 0) {
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // and this
- if (rt->external.depth != 0) {
- glDeleteRenderbuffers(1, &rt->external.depth);
- }
-
- // clean up our texture
- Texture *t = get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_free(rt->external.texture);
- //memdelete(t);
-
- rt->external.fbo = 0;
- rt->external.color = 0;
- rt->external.depth = 0;
- }
- } else {
- Texture *t;
-
- if (rt->external.fbo == 0) {
- // create our fbo
- glGenFramebuffers(1, &rt->external.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // allocate a texture
- t = memnew(Texture);
-
- t->type = Texture::TYPE_2D;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_RGBA8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->total_data_size = 0;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
- t->is_render_target = true;
-
- //rt->external.texture = make_rid(t);
-
- } else {
- // bind our frame buffer
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // find our texture
- t = get_texture(rt->external.texture);
- }
-
- // set our texture
- t->tex_id = p_texture_id;
- rt->external.color = p_texture_id;
-
- // size shouldn't be different
- t->width = rt->size.x;
- t->height = rt->size.y;
- t->alloc_height = rt->size.x;
- t->alloc_width = rt->size.y;
-
- // Switch our texture on our frame buffer
- {
- // set our texture as the destination for our framebuffer
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
- }
-
- // check status and unbind
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- WARN_PRINT("framebuffer fail, status: " + get_framebuffer_error(status));
- }
-
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
+ return rt->texture;
}
void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_transparent) {
@@ -1536,6 +1441,13 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_t
_update_render_target(rt);
}
+bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->is_transparent;
+}
+
void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -1550,7 +1462,14 @@ void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, boo
_update_render_target(rt);
}
-bool TextureStorage::render_target_was_used(RID p_render_target) {
+bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->direct_to_screen;
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
@@ -1577,6 +1496,13 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA
_update_render_target(rt);
}
+RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED);
+
+ return rt->msaa;
+}
+
void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -1607,9 +1533,11 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) {
if (!rt->clear_requested) {
return;
}
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glClearBufferfv(GL_COLOR, 0, rt->clear_color.components);
rt->clear_requested = false;
+ glBindFramebuffer(GL_FRAMEBUFFER, system_fbo);
}
void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 4f4032723b..7e083e48e8 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -126,11 +126,6 @@ struct CanvasTexture {
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
};
/* CANVAS SHADOW */
@@ -327,16 +322,6 @@ private:
};
struct RenderTarget {
- struct External {
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
- RID texture;
-
- External() {
- }
- } external;
-
Point2i position = Point2i(0, 0);
Size2i size = Size2i(0, 0);
int mipmap_count = 1;
@@ -509,6 +494,12 @@ public:
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ /* DECAL INSTANCE */
+
+ virtual RID decal_instance_create(RID p_decal) override;
+ virtual void decal_instance_free(RID p_decal_instance) override;
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
+
/* RENDER TARGET API */
static GLuint system_fbo;
@@ -518,17 +509,19 @@ public:
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
+
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual Point2i render_target_get_position(RID p_render_target) const override;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
- Size2i render_target_get_size(RID p_render_target);
- virtual RID render_target_get_texture(RID p_render_target) override;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
-
+ virtual Size2i render_target_get_size(RID p_render_target) const override;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
+ virtual bool render_target_get_transparent(RID p_render_target) const override;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
- virtual bool render_target_was_used(RID p_render_target) override;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
+ virtual bool render_target_was_used(RID p_render_target) const override;
void render_target_clear_used(RID p_render_target);
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
// new
void render_target_set_as_unused(RID p_render_target) override {
@@ -548,8 +541,20 @@ public:
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
- virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
- virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
+
+ virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+
+ virtual RID render_target_get_texture(RID p_render_target) override;
void bind_framebuffer(GLuint framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index 85e328b49f..ae6e0acc97 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -48,8 +48,8 @@ class AudioDriverPulseAudio : public AudioDriver {
pa_context *pa_ctx = nullptr;
pa_stream *pa_str = nullptr;
pa_stream *pa_rec_str = nullptr;
- pa_channel_map pa_map;
- pa_channel_map pa_rec_map;
+ pa_channel_map pa_map = {};
+ pa_channel_map pa_rec_map = {};
String device_name = "Default";
String new_device = "Default";
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 55ea952696..d894ceba59 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -30,7 +30,7 @@
#include "dir_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/os/memory.h"
#include "core/os/os.h"
@@ -41,10 +41,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#ifndef ANDROID_ENABLED
#include <sys/statvfs.h>
-#endif
#ifdef HAVE_MNTENT
#include <mntent.h>
@@ -74,7 +71,7 @@ bool DirAccessUnix::file_exists(String p_file) {
p_file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success && S_ISDIR(flags.st_mode)) {
@@ -93,7 +90,7 @@ bool DirAccessUnix::dir_exists(String p_dir) {
p_dir = fix_path(p_dir);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_dir.utf8().get_data(), &flags) == 0);
return (success && S_ISDIR(flags.st_mode));
@@ -128,7 +125,7 @@ uint64_t DirAccessUnix::get_modified_time(String p_file) {
p_file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success) {
@@ -161,7 +158,7 @@ String DirAccessUnix::get_next() {
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) {
String f = current_dir.path_join(fname);
- struct stat flags;
+ struct stat flags = {};
if (stat(f.utf8().get_data(), &flags) == 0) {
_cisdir = S_ISDIR(flags.st_mode);
} else {
@@ -415,7 +412,7 @@ Error DirAccessUnix::remove(String p_path) {
p_path = fix_path(p_path);
- struct stat flags;
+ struct stat flags = {};
if ((stat(p_path.utf8().get_data(), &flags) != 0)) {
return FAILED;
}
@@ -434,7 +431,7 @@ bool DirAccessUnix::is_link(String p_file) {
p_file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
if ((lstat(p_file.utf8().get_data(), &flags) != 0)) {
return FAILED;
}
@@ -475,17 +472,12 @@ Error DirAccessUnix::create_link(String p_source, String p_target) {
}
uint64_t DirAccessUnix::get_space_left() {
-#ifndef NO_STATVFS
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
}
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
-#else
- // FIXME: Implement this.
- return 0;
-#endif
}
String DirAccessUnix::get_filesystem_type() const {
@@ -516,4 +508,4 @@ DirAccessUnix::~DirAccessUnix() {
list_dir_end();
}
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index f5dca7c282..4db24a27b9 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -31,7 +31,7 @@
#ifndef DIR_ACCESS_UNIX_H
#define DIR_ACCESS_UNIX_H
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/io/dir_access.h"
@@ -90,6 +90,6 @@ public:
~DirAccessUnix();
};
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
#endif // DIR_ACCESS_UNIX_H
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 300fbcdcfd..0b80fb1491 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -30,24 +30,20 @@
#include "file_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <errno.h>
-
#if defined(UNIX_ENABLED)
#include <unistd.h>
#endif
-#ifndef ANDROID_ENABLED
-#include <sys/statvfs.h>
-#endif
-
#ifdef MSVC
#define S_ISREG(m) ((m)&_S_IFREG)
#include <io.h>
@@ -56,12 +52,6 @@
#define S_ISREG(m) ((m)&S_IFREG)
#endif
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
void FileAccessUnix::check_errors() const {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
@@ -96,7 +86,7 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) {
backend (unix-compatible mostly) supports utf8 encoding */
//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
- struct stat st;
+ struct stat st = {};
int err = stat(path.utf8().get_data(), &st);
if (!err) {
switch (st.st_mode & S_IFMT) {
@@ -131,13 +121,8 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) {
int fd = fileno(f);
if (fd != -1) {
-#if defined(NO_FCNTL)
- unsigned long par = 0;
- ioctl(fd, FIOCLEX, &par);
-#else
int opts = fcntl(fd, F_GETFD);
fcntl(fd, F_SETFD, opts | FD_CLOEXEC);
-#endif
}
last_error = OK;
@@ -267,7 +252,7 @@ void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
bool FileAccessUnix::file_exists(const String &p_path) {
int err;
- struct stat st;
+ struct stat st = {};
String filename = fix_path(p_path);
// Does the name exist at all?
@@ -299,7 +284,7 @@ bool FileAccessUnix::file_exists(const String &p_path) {
uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
int err = stat(file.utf8().get_data(), &flags);
if (!err) {
@@ -312,7 +297,7 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
int err = stat(file.utf8().get_data(), &flags);
if (!err) {
@@ -339,4 +324,4 @@ FileAccessUnix::~FileAccessUnix() {
_close();
}
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index e1311a80f8..8c9afe75e7 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -36,7 +36,7 @@
#include <stdio.h>
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
typedef void (*CloseNotificationFunc)(const String &p_file, int p_flags);
@@ -86,6 +86,6 @@ public:
virtual ~FileAccessUnix();
};
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
#endif // FILE_ACCESS_UNIX_H
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 86adf33d62..c6b327eeee 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -30,32 +30,30 @@
#include "net_socket_posix.h"
+// Some proprietary Unix-derived platforms don't expose Unix sockets
+// so this allows skipping this file to reimplement this API differently.
#ifndef UNIX_SOCKET_UNAVAILABLE
+
#if defined(UNIX_ENABLED)
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-#include <netinet/in.h>
-#include <sys/socket.h>
#ifdef WEB_ENABLED
#include <arpa/inet.h>
#endif
-#include <netinet/tcp.h>
-
// BSD calls this flag IPV6_JOIN_GROUP
#if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP)
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -93,7 +91,7 @@
#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15)
#endif
-#endif
+#endif // UNIX_ENABLED
size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) {
memset(p_addr, 0, sizeof(struct sockaddr_storage));
@@ -181,8 +179,8 @@ NetSocketPosix::~NetSocketPosix() {
close();
}
-// Silent a warning reported in #27594
-
+// Silence a warning reported in GH-27594.
+// EAGAIN and EWOULDBLOCK have the same value on most platforms, but it's not guaranteed.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
@@ -309,14 +307,9 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_
void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) {
#ifndef WINDOWS_ENABLED
// Enable close on exec to avoid sharing with subprocesses. Off by default on Windows.
-#if defined(NO_FCNTL)
- unsigned long par = p_enabled ? 1 : 0;
- SOCK_IOCTL(_sock, FIOCLEX, &par);
-#else
int opts = fcntl(_sock, F_GETFD);
fcntl(_sock, F_SETFD, opts | FD_CLOEXEC);
#endif
-#endif
}
Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
@@ -658,7 +651,7 @@ void NetSocketPosix::set_blocking_enabled(bool p_enabled) {
ERR_FAIL_COND(!is_open());
int ret = 0;
-#if defined(WINDOWS_ENABLED) || defined(NO_FCNTL)
+#if defined(WINDOWS_ENABLED)
unsigned long par = p_enabled ? 0 : 1;
ret = SOCK_IOCTL(_sock, FIONBIO, &par);
#else
@@ -781,4 +774,5 @@ Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, Str
Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) {
return _change_multicast_group(p_multi_address, p_if_name, false);
}
-#endif
+
+#endif // UNIX_SOCKET_UNAVAILABLE
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index c8a42e925e..fc06291a3a 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -126,9 +126,7 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
}
void OS_Unix::initialize_core() {
-#if !defined(NO_THREADS)
init_thread_posix();
-#endif
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
@@ -137,10 +135,8 @@ void OS_Unix::initialize_core() {
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
-#ifndef NO_NETWORK
NetSocketPosix::make_default();
IPUnix::make_default();
-#endif
_setup_clock();
}
@@ -149,6 +145,10 @@ void OS_Unix::finalize_core() {
NetSocketPosix::cleanup();
}
+Vector<String> OS_Unix::get_video_adapter_driver_info() const {
+ return Vector<String>();
+}
+
String OS_Unix::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
@@ -170,6 +170,7 @@ Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
left -= chunk;
ofs += chunk;
} while (left > 0);
+// Define this yourself if you don't want to fall back to /dev/urandom.
#elif !defined(NO_URANDOM)
int r = open("/dev/urandom", O_RDONLY);
ERR_FAIL_COND_V(r < 0, FAILED);
@@ -503,10 +504,6 @@ bool OS_Unix::set_environment(const String &p_var, const String &p_value) const
return setenv(p_var.utf8().get_data(), p_value.utf8().get_data(), /* overwrite: */ true) == 0;
}
-int OS_Unix::get_processor_count() const {
- return sysconf(_SC_NPROCESSORS_CONF);
-}
-
String OS_Unix::get_user_data_dir() const {
String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
if (!appname.is_empty()) {
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index b35f161524..ce06a52a95 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -51,9 +51,11 @@ protected:
public:
OS_Unix();
+ virtual Vector<String> get_video_adapter_driver_info() const override;
+
virtual String get_stdin_string(bool p_block) override;
- virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
+ virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
@@ -84,8 +86,6 @@ public:
virtual bool set_environment(const String &p_var, const String &p_value) const override;
virtual String get_locale() const override;
- virtual int get_processor_count() const override;
-
virtual void initialize_debugging() override;
virtual String get_executable_path() const override;
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index cb5f261e6e..5154feb478 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
+#if defined(UNIX_ENABLED)
#include "thread_posix.h"
@@ -70,7 +70,7 @@ static Error set_name(const String &p_name) {
}
void init_thread_posix() {
- Thread::_set_platform_funcs(&set_name, nullptr);
+ Thread::_set_platform_functions({ .set_name = set_name });
}
-#endif
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index 672adcba72..87e42b3870 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -31,8 +31,6 @@
#ifndef THREAD_POSIX_H
#define THREAD_POSIX_H
-#if !defined(NO_THREADS)
void init_thread_posix();
-#endif
#endif // THREAD_POSIX_H
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 53e9146f85..036489a9bc 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -1655,9 +1655,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
image_create_info.pNext = nullptr;
image_create_info.flags = 0;
-#ifndef _MSC_VER
-#warning TODO check for support via RenderingDevice to enable on mobile when possible
-#endif
+ // TODO: Check for support via RenderingDevice to enable on mobile when possible.
#ifndef ANDROID_ENABLED
@@ -4152,8 +4150,8 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
size.height = texture->height;
size_set = true;
} else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
- // If this is not the first attachement we assume this is used as the VRS attachment.
- // In this case this texture will be 1/16th the size of the color attachement.
+ // If this is not the first attachment we assume this is used as the VRS attachment.
+ // In this case this texture will be 1/16th the size of the color attachment.
// So we skip the size check.
} else {
ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
@@ -4828,7 +4826,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
for (uint32_t j = 0; j < binding_count; j++) {
const SpvReflectDescriptorBinding &binding = *bindings[j];
- RenderingDeviceVulkanShaderBinaryDataBinding info;
+ RenderingDeviceVulkanShaderBinaryDataBinding info{};
bool need_array_dimensions = false;
bool need_block_size = false;
@@ -4979,7 +4977,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
for (uint32_t j = 0; j < sc_count; j++) {
int32_t existing = -1;
- RenderingDeviceVulkanShaderBinarySpecializationConstant sconst;
+ RenderingDeviceVulkanShaderBinarySpecializationConstant sconst{};
SpvReflectSpecializationConstant *spc = spec_constants[j];
sconst.constant_id = spc->constant_id;
@@ -5172,9 +5170,9 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
uint32_t offset = 0;
uint8_t *binptr = ret.ptrw();
binptr[0] = 'G';
- binptr[1] = 'V';
+ binptr[1] = 'S';
binptr[2] = 'B';
- binptr[3] = 'D'; // Godot vulkan binary data.
+ binptr[3] = 'D'; // Godot Shader Binary Data.
offset += 4;
encode_uint32(SHADER_BINARY_VERSION, binptr + offset);
offset += sizeof(uint32_t);
@@ -5235,7 +5233,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
uint32_t read_offset = 0;
// Consistency check.
ERR_FAIL_COND_V(binsize < sizeof(uint32_t) * 3 + sizeof(RenderingDeviceVulkanShaderBinaryData), RID());
- ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID());
+ ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'S' || binptr[2] != 'B' || binptr[3] != 'D', RID());
uint32_t bin_version = decode_uint32(binptr + 4);
ERR_FAIL_COND_V(bin_version != SHADER_BINARY_VERSION, RID());
@@ -7262,12 +7260,12 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
return OK;
}
-void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) {
+void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) {
Vector<VkClearAttachment> clear_attachments;
int color_index = 0;
int texture_index = 0;
- for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
- Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
+ for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) {
+ Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
if (!texture) {
texture_index++;
@@ -7300,12 +7298,12 @@ void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list,
VkClearRect cr;
cr.baseArrayLayer = 0;
cr.layerCount = 1;
- cr.rect.offset.x = viewport_offset.x;
- cr.rect.offset.y = viewport_offset.y;
- cr.rect.extent.width = viewport_size.width;
- cr.rect.extent.height = viewport_size.height;
+ cr.rect.offset.x = p_viewport_offset.x;
+ cr.rect.offset.y = p_viewport_offset.y;
+ cr.rect.extent.width = p_viewport_size.width;
+ cr.rect.extent.height = p_viewport_size.height;
- vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr);
+ vkCmdClearAttachments(p_draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr);
}
RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
@@ -9393,7 +9391,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
ERR_CONTINUE(err != OK);
}
- max_descriptors_per_pool = GLOBAL_DEF("rendering/rendering_device/descriptor_pools/max_descriptors_per_pool", 64);
+ max_descriptors_per_pool = GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64);
// Check to make sure DescriptorPoolKey is good.
static_assert(sizeof(uint64_t) * 3 >= UNIFORM_TYPE_MAX * sizeof(uint16_t));
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index abec1b0e1b..7c75e9bb2e 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -905,7 +905,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
bool draw_list_unbind_color_textures = false;
bool draw_list_unbind_depth_textures = false;
- void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
+ void _draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass, uint32_t *r_subpass_count);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 99ef57abae..1ab8914624 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -48,7 +48,7 @@
VulkanHooks *VulkanContext::vulkan_hooks = nullptr;
-VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
+VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass) {
if (fpCreateRenderPass2KHR == nullptr) {
fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetInstanceProcAddr(inst, "vkCreateRenderPass2KHR");
}
@@ -56,7 +56,7 @@ VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPa
if (fpCreateRenderPass2KHR == nullptr) {
return VK_ERROR_EXTENSION_NOT_PRESENT;
} else {
- return (fpCreateRenderPass2KHR)(device, pCreateInfo, pAllocator, pRenderPass);
+ return (fpCreateRenderPass2KHR)(p_device, p_create_info, p_allocator, p_render_pass);
}
}
@@ -85,19 +85,6 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
return VK_FALSE;
}
- // Workaround for Vulkan-Loader usability bug: https://github.com/KhronosGroup/Vulkan-Loader/issues/262.
- if (strstr(pCallbackData->pMessage, "wrong ELF class: ELFCLASS32") != nullptr) {
- return VK_FALSE;
- }
-
-#ifdef WINDOWS_ENABLED
- // Some software installs Vulkan overlays in Windows registry and never cleans them up on uninstall.
- // So we get spammy error level messages from the loader about those - make them verbose instead.
- if (strstr(pCallbackData->pMessage, "loader_get_json: Failed to open JSON file") != nullptr) {
- messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
- }
-#endif
-
if (pCallbackData->pMessageIdName && strstr(pCallbackData->pMessageIdName, "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw") != nullptr) {
return VK_FALSE;
}
@@ -320,6 +307,16 @@ Error VulkanContext::_initialize_extensions() {
VkBool32 platformSurfaceExtFound = 0;
memset(extension_names, 0, sizeof(extension_names));
+ // Only enable debug utils in verbose mode or DEV_ENABLED.
+ // End users would get spammed with messages of varying verbosity due to the
+ // mess that thirdparty layers/extensions and drivers seem to leave in their
+ // wake, making the Windows registry a bottomless pit of broken layer JSON.
+#ifdef DEV_ENABLED
+ bool want_debug_utils = true;
+#else
+ bool want_debug_utils = OS::get_singleton()->is_stdout_verbose();
+#endif
+
VkResult err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr);
ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, ERR_CANT_CREATE);
@@ -347,8 +344,10 @@ Error VulkanContext::_initialize_extensions() {
}
}
if (!strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- enabled_debug_utils = true;
+ if (want_debug_utils) {
+ extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ enabled_debug_utils = true;
+ }
}
if (!strcmp(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, instance_extensions[i].extensionName)) {
extension_names[enabled_extension_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
@@ -608,10 +607,10 @@ Error VulkanContext::_check_capabilities() {
device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
}
if (device_properties_func != nullptr) {
- VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties;
- VkPhysicalDeviceMultiviewProperties multiviewProperties;
- VkPhysicalDeviceSubgroupProperties subgroupProperties;
- VkPhysicalDeviceProperties2 physicalDeviceProperties;
+ VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties{};
+ VkPhysicalDeviceMultiviewProperties multiviewProperties{};
+ VkPhysicalDeviceSubgroupProperties subgroupProperties{};
+ VkPhysicalDeviceProperties2 physicalDeviceProperties{};
void *nextptr = nullptr;
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
@@ -2261,8 +2260,6 @@ Error VulkanContext::swap_buffers() {
}
}
#endif
- static int total_frames = 0;
- total_frames++;
// print_line("current buffer: " + itos(current_buffer));
err = fpQueuePresentKHR(present_queue, &present);
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 9889cf336b..7389e86ad7 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -270,7 +270,7 @@ protected:
public:
// Extension calls.
- VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
+ VkResult vkCreateRenderPass2KHR(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass);
uint32_t get_vulkan_major() const { return vulkan_major; };
uint32_t get_vulkan_minor() const { return vulkan_minor; };
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 11fd29c8f5..c085ba372b 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -160,7 +160,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
p_dir = current_dir.path_join(p_dir);
}
- p_dir = p_dir.replace("/", "\\");
+ p_dir = p_dir.simplify_path().replace("/", "\\");
bool success;
int err;
@@ -200,9 +200,9 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) const {
return current_dir;
} else {
if (_get_root_string().is_empty()) {
- int p = current_dir.find(":");
- if (p != -1) {
- return current_dir.substr(p + 1);
+ int pos = current_dir.find(":");
+ if (pos != -1) {
+ return current_dir.substr(pos + 1);
}
}
return current_dir;
@@ -309,39 +309,13 @@ Error DirAccessWindows::remove(String p_path) {
}
}
-/*
-
-FileType DirAccessWindows::get_file_type(const String& p_file) const {
- WCHAR real_current_dir_name[2048];
- GetCurrentDirectoryW(2048, real_current_dir_name);
- String prev_dir = Strong::utf16((const char16_t *)real_current_dir_name);
-
- bool worked = SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data()));
-
- DWORD attr;
- if (worked) {
- WIN32_FILE_ATTRIBUTE_DATA fileInfo;
- attr = GetFileAttributesExW((LPCWSTR)(p_file.utf16().get_data()), GetFileExInfoStandard, &fileInfo);
- }
-
- SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data()));
-
- if (!worked) {
- return FILE_TYPE_NONE;
- }
-
- return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FILE_TYPE_
-}
-
-*/
-
uint64_t DirAccessWindows::get_space_left() {
uint64_t bytes = 0;
if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) {
return 0;
}
- //this is either 0 or a value in bytes.
+ // This is either 0 or a value in bytes.
return bytes;
}
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 095d936c78..4e8b327ffe 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -95,8 +95,8 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) {
// platforms).
if (p_mode_flags == READ) {
WIN32_FIND_DATAW d;
- HANDLE f = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d);
- if (f != INVALID_HANDLE_VALUE) {
+ HANDLE fnd = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d);
+ if (fnd != INVALID_HANDLE_VALUE) {
String fname = String::utf16((const char16_t *)(d.cFileName));
if (!fname.is_empty()) {
String base_file = path.get_file();
@@ -104,7 +104,7 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) {
WARN_PRINT("Case mismatch opening requested file '" + base_file + "', stored as '" + fname + "' in the filesystem. This file will not open when exported to other case-sensitive platforms.");
}
}
- FindClose(f);
+ FindClose(fnd);
}
}
#endif