Skip to content

Commit

Permalink
Merge pull request #42119 from lawnjelly/ewok3
Browse files Browse the repository at this point in the history
Unified GLES3 / GLES2 Batching
  • Loading branch information
akien-mga authored Oct 19, 2020
2 parents 3495cb9 + 74c460f commit 123942f
Show file tree
Hide file tree
Showing 28 changed files with 6,982 additions and 4,116 deletions.
8 changes: 8 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,10 @@
<member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="" default="3600">
Shaders have a time variable that constantly increases. At some point, it needs to be rolled back to zero to avoid precision errors on shader animations. This setting specifies when (in seconds).
</member>
<member name="rendering/quality/2d/ninepatch_mode" type="int" setter="" getter="" default="0">
Choose between default mode where corner scalings are preserved matching the artwork, and scaling mode.
Not available in GLES3 when [member rendering/batching/options/use_batching] is off.
</member>
<member name="rendering/quality/2d/use_nvidia_rect_flicker_workaround" type="bool" setter="" getter="" default="false">
Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url=https://github.com/godotengine/godot/issues/9913]GitHub issue 9913[/url] for details.
If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option affects GLES2 and GLES3 rendering, but only on desktop platforms.
Expand All @@ -1070,6 +1074,10 @@
If [code]true[/code], forces snapping of polygons to pixels in 2D rendering. May help in some pixel art styles.
Consider using the project setting [member rendering/batching/precision/uv_contract] to prevent artifacts.
</member>
<member name="rendering/quality/2d/use_software_skinning" type="bool" setter="" getter="" default="true">
If [code]true[/code], performs 2d skinning on the CPU rather than the GPU. This provides greater compatibility with a wide range of hardware, and also may be faster in some circumstances.
Currently only available when [member rendering/batching/options/use_batching] is active.
</member>
<member name="rendering/quality/depth/hdr" type="bool" setter="" getter="" default="true">
If [code]true[/code], allocates the main framebuffer with high dynamic range. High dynamic range allows the use of [Color] values greater than 1.
[b]Note:[/b] Only available on the GLES3 backend.
Expand Down
1 change: 1 addition & 0 deletions drivers/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SConscript("winmidi/SCsub")
if env["platform"] != "server":
SConscript("gles3/SCsub")
SConscript("gles2/SCsub")
SConscript("gles_common/SCsub")
SConscript("gl_context/SCsub")
else:
SConscript("dummy/SCsub")
Expand Down
59 changes: 42 additions & 17 deletions drivers/gles2/rasterizer_canvas_base_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ void RasterizerCanvasBaseGLES2::canvas_begin() {

// always start with light_angle unset
state.using_light_angle = false;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHT_ANGLE, false);
state.using_large_vertex = false;
state.using_modulate = false;

state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LIGHT_ANGLE, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_MODULATE, false);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LARGE_VERTEX, false);
state.canvas_shader.bind();

int viewport_x, viewport_y, viewport_width, viewport_height;
Expand Down Expand Up @@ -160,13 +165,23 @@ void RasterizerCanvasBaseGLES2::draw_generic_textured_rect(const Rect2 &p_rect,
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void RasterizerCanvasBaseGLES2::_set_texture_rect_mode(bool p_texture_rect, bool p_light_angle) {
void RasterizerCanvasBaseGLES2::_set_texture_rect_mode(bool p_texture_rect, bool p_light_angle, bool p_modulate, bool p_large_vertex) {
// always set this directly (this could be state checked)
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, p_texture_rect);

if (state.using_light_angle != p_light_angle) {
state.using_light_angle = p_light_angle;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHT_ANGLE, p_light_angle);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LIGHT_ANGLE, p_light_angle);
}

if (state.using_modulate != p_modulate) {
state.using_modulate = p_modulate;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_MODULATE, p_modulate);
}

if (state.using_large_vertex != p_large_vertex) {
state.using_large_vertex = p_large_vertex;
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_ATTRIB_LARGE_VERTEX, p_large_vertex);
}
}

Expand Down Expand Up @@ -431,8 +446,21 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_

glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);

// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}
if (p_weights && p_bones) {
total_buffer_size += sizeof(float) * 4 * p_vertex_count; // weights
total_buffer_size += sizeof(int) * 4 * p_vertex_count; // bones
}

uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, total_buffer_size, p_vertices);

glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
Expand All @@ -446,14 +474,12 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
glDisableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
}

if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Vector2) * p_vertex_count;
Expand All @@ -462,12 +488,10 @@ void RasterizerCanvasBaseGLES2::_draw_polygon(const int *p_indices, int p_index_
}

if (p_weights && p_bones) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights);
glEnableVertexAttribArray(VS::ARRAY_WEIGHTS);
glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(float) * 4 * p_vertex_count;

glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones);
glEnableVertexAttribArray(VS::ARRAY_BONES);
glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(int) * 4 * p_vertex_count;
Expand Down Expand Up @@ -501,8 +525,17 @@ void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_c

glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);

// precalculate the buffer size ahead of time instead of making multiple glBufferSubData calls
uint32_t total_buffer_size = sizeof(Vector2) * p_vertex_count;
if (!p_singlecolor && p_colors) {
total_buffer_size += sizeof(Color) * p_vertex_count;
}
if (p_uvs) {
total_buffer_size += sizeof(Vector2) * p_vertex_count;
}

uint32_t buffer_ofs = 0;
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
storage->buffer_orphan_and_upload(data.polygon_buffer_size, 0, total_buffer_size, p_vertices);

glEnableVertexAttribArray(VS::ARRAY_VERTEX);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
Expand All @@ -516,14 +549,12 @@ void RasterizerCanvasBaseGLES2::_draw_generic(GLuint p_primitive, int p_vertex_c
glDisableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
} else {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
glEnableVertexAttribArray(VS::ARRAY_COLOR);
glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
buffer_ofs += sizeof(Color) * p_vertex_count;
}

if (p_uvs) {
glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs));
} else {
Expand Down Expand Up @@ -1024,10 +1055,4 @@ void RasterizerCanvasBaseGLES2::finalize() {
}

RasterizerCanvasBaseGLES2::RasterizerCanvasBaseGLES2() {
#ifdef GLES_OVER_GL
use_nvidia_rect_workaround = GLOBAL_GET("rendering/quality/2d/use_nvidia_rect_flicker_workaround");
#else
// Not needed (a priori) on GLES devices
use_nvidia_rect_workaround = false;
#endif
}
11 changes: 7 additions & 4 deletions drivers/gles2/rasterizer_canvas_base_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
#ifndef RASTERIZERCANVASBASEGLES2_H
#define RASTERIZERCANVASBASEGLES2_H

#include "rasterizer_array_gles2.h"
#include "drivers/gles_common/rasterizer_array.h"
#include "rasterizer_storage_gles2.h"
#include "servers/visual/rasterizer.h"

#include "shaders/canvas.glsl.gen.h"
#include "shaders/lens_distorted.glsl.gen.h"

#include "drivers/gles_common/rasterizer_storage_common.h"
#include "shaders/canvas_shadow.glsl.gen.h"

class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
Expand Down Expand Up @@ -77,7 +78,11 @@ class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
LensDistortedShaderGLES2 lens_shader;

bool using_texture_rect;

bool using_light_angle;
bool using_modulate;
bool using_large_vertex;

bool using_ninepatch;
bool using_skeleton;

Expand All @@ -102,8 +107,6 @@ class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {

RasterizerStorageGLES2 *storage;

bool use_nvidia_rect_workaround;

void _set_uniforms();

virtual RID light_internal_create();
Expand Down Expand Up @@ -131,7 +134,7 @@ class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow);

RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
void _set_texture_rect_mode(bool p_texture_rect, bool p_light_angle = false);
void _set_texture_rect_mode(bool p_texture_rect, bool p_light_angle = false, bool p_modulate = false, bool p_large_vertex = false);

void initialize();
void finalize();
Expand Down
Loading

0 comments on commit 123942f

Please sign in to comment.