Batch GLES2 draw calls

Adds GLES2 draw calls batching for the same render list item that uses
multiple rasterizer commands (e.g. Label node; a node with multiple
GDScript draw_* calls).
This commit is contained in:
Marcin Zawiejski 2018-07-31 23:52:55 +02:00
parent eef9c1f5b5
commit f55039b194
7 changed files with 617 additions and 475 deletions

File diff suppressed because it is too large Load diff

View file

@ -50,23 +50,44 @@ public:
Color final_modulate;
float time;
Size2 texpixel_size;
};
struct Vertex {
Vector2 v;
Color c;
Vector2 uv;
};
struct Data {
GLuint canvas_quad_vertices;
GLuint polygon_buffer;
GLuint polygon_index_buffer;
GLuint vertex_buffer;
GLuint index_buffer;
uint32_t polygon_buffer_size;
uint32_t vertex_buffer_size;
uint32_t index_buffer_size;
GLuint ninepatch_vertices;
GLuint ninepatch_elements;
int ninepatch_elements[3 * 2 * 9];
int *mem_index_buffer;
uint32_t mem_index_buffer_offset;
uint32_t mem_index_buffer_size;
Vertex *mem_vertex_buffer;
uint32_t mem_vertex_buffer_offset;
uint32_t mem_vertex_buffer_size;
GLuint primitive;
GLuint texture;
} data;
struct State {
Uniforms uniforms;
Uniforms prev_uniforms;
bool tiled;
bool canvas_texscreen_used;
CanvasShaderGLES2 canvas_shader;
// CanvasShadowShaderGLES3 canvas_shadow_shader;
@ -99,9 +120,16 @@ public:
_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
_FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _begin(const GLuint p_primitive);
_FORCE_INLINE_ void _prepare(const int p_vertex_count, const int p_index_count);
_FORCE_INLINE_ void _commit(const int p_vertex_count, const int p_index_count);
_FORCE_INLINE_ void _flush();
_FORCE_INLINE_ void _draw(const GLuint p_primitive, const int p_vertex_count, const Vertex *p_vertices, const int p_index_count, const int *p_indices);
_FORCE_INLINE_ void _untile();
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
@ -114,8 +142,8 @@ public:
virtual void reset_canvas();
RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
_FORCE_INLINE_ void _bind_shader(RasterizerStorageGLES2::Material *p_material);
void _bind_quad_buffer();
void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
void initialize();

View file

@ -345,9 +345,6 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
canvas->state.canvas_shader.set_custom_shader(0);
canvas->state.canvas_shader.bind();
@ -359,7 +356,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
// TODO normals
canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 1, 1, -1));
glBindTexture(GL_TEXTURE_2D, 0);
canvas->canvas_end();

View file

@ -252,7 +252,7 @@ public:
int mipmaps;
bool active;
GLenum tex_id;
GLuint tex_id;
uint16_t stored_cube_sides;
@ -429,6 +429,8 @@ public:
bool uses_screen_texture;
bool uses_screen_uv;
bool uses_time;
bool uses_modelview_matrix;
bool uses_vertex;
} canvas_item;

View file

@ -122,13 +122,11 @@ GLint ShaderGLES2::get_uniform_location(int p_index) const {
}
bool ShaderGLES2::bind() {
if (active != this || !version || new_conditional_version.key != conditional_version.key) {
conditional_version = new_conditional_version;
version = get_current_version();
} else {
if (!is_dirty())
return false;
}
conditional_version = new_conditional_version;
version = get_current_version();
ERR_FAIL_COND_V(!version, false);
@ -1109,3 +1107,7 @@ ShaderGLES2::ShaderGLES2() {
ShaderGLES2::~ShaderGLES2() {
finish();
}
bool ShaderGLES2::is_dirty() const {
return active != this || !version || new_conditional_version.key != conditional_version.key;
}

View file

@ -208,6 +208,7 @@ public:
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
bool is_dirty() const;
bool bind();
void unbind();
void bind_uniforms();

View file

@ -20,13 +20,6 @@ varying vec4 color_interp;
uniform highp vec2 color_texpixel_size;
#ifdef USE_TEXTURE_RECT
uniform vec4 dst_rect;
uniform vec4 src_rect;
#endif
uniform highp float time;
VERTEX_SHADER_GLOBALS
@ -44,35 +37,9 @@ void main() {
vec4 color = color_attrib;
#ifdef USE_TEXTURE_RECT
if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
} else {
uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
}
vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0);
// This is what is done in the GLES 3 bindings and should
// take care of flipped rects.
//
// But it doesn't.
// I don't know why, will need to investigate further.
outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0)));
// outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex;
#else
vec4 outvec = vec4(vertex.xy, 0.0, 1.0);
#ifdef USE_UV_ATTRIBUTE
uv_interp = uv_attrib;
#else
uv_interp = vertex.xy;
#endif
#endif
{
vec2 src_vtx=outvec.xy;