Merge pull request #37349 from lawnjelly/kessel32_1

GLES2 2d Batch rendering (across items)
This commit is contained in:
Rémi Verschelde 2020-04-17 12:55:33 +02:00 committed by GitHub
commit 008e0748c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 4583 additions and 2126 deletions

View file

@ -79,40 +79,46 @@
<constant name="RENDER_DRAW_CALLS_IN_FRAME" value="17" enum="Monitor"> <constant name="RENDER_DRAW_CALLS_IN_FRAME" value="17" enum="Monitor">
Draw calls per frame. 3D only. Draw calls per frame. 3D only.
</constant> </constant>
<constant name="RENDER_VIDEO_MEM_USED" value="18" enum="Monitor"> <constant name="RENDER_2D_ITEMS_IN_FRAME" value="18" enum="Monitor">
Items or joined items drawn per frame.
</constant>
<constant name="RENDER_2D_DRAW_CALLS_IN_FRAME" value="19" enum="Monitor">
Draw calls per frame.
</constant>
<constant name="RENDER_VIDEO_MEM_USED" value="20" enum="Monitor">
The amount of video memory used, i.e. texture and vertex memory combined. The amount of video memory used, i.e. texture and vertex memory combined.
</constant> </constant>
<constant name="RENDER_TEXTURE_MEM_USED" value="19" enum="Monitor"> <constant name="RENDER_TEXTURE_MEM_USED" value="21" enum="Monitor">
The amount of texture memory used. The amount of texture memory used.
</constant> </constant>
<constant name="RENDER_VERTEX_MEM_USED" value="20" enum="Monitor"> <constant name="RENDER_VERTEX_MEM_USED" value="22" enum="Monitor">
The amount of vertex memory used. The amount of vertex memory used.
</constant> </constant>
<constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="21" enum="Monitor"> <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="23" enum="Monitor">
Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0. Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
</constant> </constant>
<constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="22" enum="Monitor"> <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="24" enum="Monitor">
Number of active [RigidBody2D] nodes in the game. Number of active [RigidBody2D] nodes in the game.
</constant> </constant>
<constant name="PHYSICS_2D_COLLISION_PAIRS" value="23" enum="Monitor"> <constant name="PHYSICS_2D_COLLISION_PAIRS" value="25" enum="Monitor">
Number of collision pairs in the 2D physics engine. Number of collision pairs in the 2D physics engine.
</constant> </constant>
<constant name="PHYSICS_2D_ISLAND_COUNT" value="24" enum="Monitor"> <constant name="PHYSICS_2D_ISLAND_COUNT" value="26" enum="Monitor">
Number of islands in the 2D physics engine. Number of islands in the 2D physics engine.
</constant> </constant>
<constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="25" enum="Monitor"> <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="27" enum="Monitor">
Number of active [RigidBody] and [VehicleBody] nodes in the game. Number of active [RigidBody] and [VehicleBody] nodes in the game.
</constant> </constant>
<constant name="PHYSICS_3D_COLLISION_PAIRS" value="26" enum="Monitor"> <constant name="PHYSICS_3D_COLLISION_PAIRS" value="28" enum="Monitor">
Number of collision pairs in the 3D physics engine. Number of collision pairs in the 3D physics engine.
</constant> </constant>
<constant name="PHYSICS_3D_ISLAND_COUNT" value="27" enum="Monitor"> <constant name="PHYSICS_3D_ISLAND_COUNT" value="29" enum="Monitor">
Number of islands in the 3D physics engine. Number of islands in the 3D physics engine.
</constant> </constant>
<constant name="AUDIO_OUTPUT_LATENCY" value="28" enum="Monitor"> <constant name="AUDIO_OUTPUT_LATENCY" value="30" enum="Monitor">
Output latency of the [AudioServer]. Output latency of the [AudioServer].
</constant> </constant>
<constant name="MONITOR_MAX" value="29" enum="Monitor"> <constant name="MONITOR_MAX" value="31" enum="Monitor">
Represents the size of the [enum Monitor] enum. Represents the size of the [enum Monitor] enum.
</constant> </constant>
</constants> </constants>

View file

@ -969,6 +969,30 @@
<member name="rendering/environment/default_environment" type="String" setter="" getter="" default="&quot;&quot;"> <member name="rendering/environment/default_environment" type="String" setter="" getter="" default="&quot;&quot;">
[Environment] that will be used as a fallback environment in case a scene does not specify its own environment. The default environment is loaded in at scene load time regardless of whether you have set an environment or not. If you do not rely on the fallback environment, it is best to delete [code]default_env.tres[/code], or to specify a different default environment here. [Environment] that will be used as a fallback environment in case a scene does not specify its own environment. The default environment is loaded in at scene load time regardless of whether you have set an environment or not. If you do not rely on the fallback environment, it is best to delete [code]default_env.tres[/code], or to specify a different default environment here.
</member> </member>
<member name="rendering/gles2/batching/batch_buffer_size" type="int" setter="" getter="" default="16384">
Size of buffer reserved for batched vertices. Larger size enables larger batches, but there are diminishing returns for the memory used.
</member>
<member name="rendering/gles2/batching/colored_vertex_format_threshold" type="float" setter="" getter="" default="0.25">
Including color in the vertex format has a cost, however, not including color prevents batching across color changes. This threshold determines the ratio of [code]number of vertex color changes / total number of vertices[/code] above which vertices will be translated to colored format. A value of 0 will always use colored vertices, 1 will never use colored vertices.
</member>
<member name="rendering/gles2/batching/light_scissor_area_threshold" type="float" setter="" getter="" default="1.0">
Sets the proportion of the screen area that must be saved by a scissor operation in order to activate light scissoring. This can prevent parts of items being rendered outside the light area. Lower values scissor more aggressively. A value of 1 scissors none of the items, a value of 0 scissors every item. This can reduce fill rate requirements in scenes with a lot of lighting.
</member>
<member name="rendering/gles2/batching/max_join_item_commands" type="int" setter="" getter="" default="16">
Sets the number of commands to lookahead to determine whether to batch render items. A value of 1 can join items consisting of single commands, 0 turns off joining. Higher values are in theory more likely to join, however this has diminishing returns and has a runtime cost so a small value is recommended.
</member>
<member name="rendering/gles2/batching/use_batching" type="bool" setter="" getter="" default="true">
Turns batching on and off. Batching increases performance by reducing the amount of graphics API drawcalls.
</member>
<member name="rendering/gles2/debug/diagnose_frame" type="bool" setter="" getter="" default="false">
When batching is on, this regularly prints a frame diagnosis log. Note that this will degrade performance.
</member>
<member name="rendering/gles2/debug/flash_batching" type="bool" setter="" getter="" default="false">
[b]Experimental[/b] For regression testing against the old renderer. If this is switched on, and [code]use_batching[/code] is set, the renderer will swap alternately between using the old renderer, and the batched renderer, on each frame. This makes it easy to identify visual differences. Performance will be degraded.
</member>
<member name="rendering/gles2/debug/use_batching_in_editor" type="bool" setter="" getter="" default="true">
[b]Experimental[/b] Switches on batching within the editor. Use with caution - note that if your editor does not render correctly you may need to edit your [code]project.godot[/code] and remove the use_batching_in_editor setting manually.
</member>
<member name="rendering/limits/buffers/blend_shape_max_buffer_size_kb" type="int" setter="" getter="" default="4096"> <member name="rendering/limits/buffers/blend_shape_max_buffer_size_kb" type="int" setter="" getter="" default="4096">
Max buffer size for blend shapes. Any blend shape bigger than this will not work. Max buffer size for blend shapes. Any blend shape bigger than this will not work.
</member> </member>

View file

@ -377,7 +377,13 @@
<constant name="RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo"> <constant name="RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo">
Amount of draw calls in frame. Amount of draw calls in frame.
</constant> </constant>
<constant name="RENDER_INFO_MAX" value="6" enum="RenderInfo"> <constant name="RENDER_INFO_2D_ITEMS_IN_FRAME" value="6" enum="RenderInfo">
Amount of items or joined items in frame.
</constant>
<constant name="RENDER_INFO_2D_DRAW_CALLS_IN_FRAME" value="7" enum="RenderInfo">
Amount of draw calls in frame.
</constant>
<constant name="RENDER_INFO_MAX" value="8" enum="RenderInfo">
Represents the size of the [enum RenderInfo] enum. Represents the size of the [enum RenderInfo] enum.
</constant> </constant>
<constant name="DEBUG_DRAW_DISABLED" value="0" enum="DebugDraw"> <constant name="DEBUG_DRAW_DISABLED" value="0" enum="DebugDraw">

View file

@ -4601,7 +4601,13 @@
<constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo"> <constant name="VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="ViewportRenderInfo">
Number of draw calls during this frame. Number of draw calls during this frame.
</constant> </constant>
<constant name="VIEWPORT_RENDER_INFO_MAX" value="6" enum="ViewportRenderInfo"> <constant name="VIEWPORT_RENDER_INFO_2D_ITEMS_IN_FRAME" value="6" enum="ViewportRenderInfo">
Number of 2d items drawn this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_2D_DRAW_CALLS_IN_FRAME" value="7" enum="ViewportRenderInfo">
Number of 2d draw calls during this frame.
</constant>
<constant name="VIEWPORT_RENDER_INFO_MAX" value="8" enum="ViewportRenderInfo">
Represents the size of the [enum ViewportRenderInfo] enum. Represents the size of the [enum ViewportRenderInfo] enum.
</constant> </constant>
<constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0" enum="ViewportDebugDraw"> <constant name="VIEWPORT_DEBUG_DRAW_DISABLED" value="0" enum="ViewportDebugDraw">
@ -4748,16 +4754,22 @@
<constant name="INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo"> <constant name="INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo">
The amount of draw calls in frame. The amount of draw calls in frame.
</constant> </constant>
<constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="6" enum="RenderInfo"> <constant name="INFO_2D_ITEMS_IN_FRAME" value="6" enum="RenderInfo">
The amount of 2d items in the frame.
</constant>
<constant name="INFO_2D_DRAW_CALLS_IN_FRAME" value="7" enum="RenderInfo">
The amount of 2d draw calls in frame.
</constant>
<constant name="INFO_USAGE_VIDEO_MEM_TOTAL" value="8" enum="RenderInfo">
Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0. Unimplemented in the GLES2 and GLES3 rendering backends, always returns 0.
</constant> </constant>
<constant name="INFO_VIDEO_MEM_USED" value="7" enum="RenderInfo"> <constant name="INFO_VIDEO_MEM_USED" value="9" enum="RenderInfo">
The amount of video memory used, i.e. texture and vertex memory combined. The amount of video memory used, i.e. texture and vertex memory combined.
</constant> </constant>
<constant name="INFO_TEXTURE_MEM_USED" value="8" enum="RenderInfo"> <constant name="INFO_TEXTURE_MEM_USED" value="10" enum="RenderInfo">
The amount of texture memory used. The amount of texture memory used.
</constant> </constant>
<constant name="INFO_VERTEX_MEM_USED" value="9" enum="RenderInfo"> <constant name="INFO_VERTEX_MEM_USED" value="11" enum="RenderInfo">
The amount of vertex memory used. The amount of vertex memory used.
</constant> </constant>
<constant name="FEATURE_SHADERS" value="0" enum="Features"> <constant name="FEATURE_SHADERS" value="0" enum="Features">

View file

@ -0,0 +1,190 @@
#pragma once
/*************************************************************************/
/* rasterizer_array_gles2.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
/**
* Fast single-threaded growable array for POD types.
* For use in render drivers, not for general use.
* TO BE REPLACED by local_vector.
*/
#include "core/os/memory.h"
#include "core/vector.h"
#include <string.h>
template <class T>
class RasterizerArrayGLES2 {
public:
RasterizerArrayGLES2() {
_list = 0;
_size = 0;
_max_size = 0;
}
~RasterizerArrayGLES2() { free(); }
_FORCE_INLINE_ T &operator[](unsigned int ui) { return _list[ui]; }
_FORCE_INLINE_ const T &operator[](unsigned int ui) const { return _list[ui]; }
void free() {
if (_list) {
memdelete_arr(_list);
_list = 0;
}
_size = 0;
_max_size = 0;
}
void create(int p_size) {
free();
if (p_size) {
_list = memnew_arr(T, p_size);
}
_size = 0;
_max_size = p_size;
}
_FORCE_INLINE_ void reset() { _size = 0; }
_FORCE_INLINE_ T *request_with_grow() {
T *p = request();
if (!p) {
grow();
return request_with_grow();
}
return p;
}
// none of that inefficient pass by value stuff here, thanks
_FORCE_INLINE_ T *request() {
if (_size < _max_size) {
return &_list[_size++];
}
return 0;
}
// several items at a time
_FORCE_INLINE_ T *request(int p_num_items) {
int old_size = _size;
_size += p_num_items;
if (_size <= _max_size) {
return &_list[old_size];
}
// revert
_size = old_size;
return 0;
}
_FORCE_INLINE_ int size() const { return _size; }
_FORCE_INLINE_ int max_size() const { return _max_size; }
_FORCE_INLINE_ const T *get_data() const { return _list; }
bool copy_from(const RasterizerArrayGLES2<T> &o) {
// no resizing done here, it should be done manually
if (o.size() > _max_size)
return false;
// pod types only please!
memcpy(_list, o.get_data(), o.size() * sizeof(T));
_size = o.size();
return true;
}
// if you want this to be cheap, call reset before grow,
// to ensure there is no data to copy
void grow() {
unsigned int new_max_size = _max_size * 2;
if (!new_max_size)
new_max_size = 1;
T *new_list = memnew_arr(T, new_max_size);
// copy .. pod types only
if (_list) {
memcpy(new_list, _list, _size * sizeof(T));
}
unsigned int new_size = size();
free();
_list = new_list;
_size = new_size;
_max_size = new_max_size;
}
private:
T *_list;
int _size;
int _max_size;
};
template <class T>
class RasterizerArray_non_pod_GLES2 {
public:
RasterizerArray_non_pod_GLES2() {
_size = 0;
}
const T &operator[](unsigned int ui) const { return _list[ui]; }
void create(int p_size) {
_list.resize(p_size);
_size = 0;
}
void reset() { _size = 0; }
void push_back(const T &val) {
while (true) {
if (_size < max_size()) {
_list.set(_size, val);
_size++;
return;
}
grow();
}
}
int size() const { return _size; }
int max_size() const { return _list.size(); }
private:
void grow() {
unsigned int new_max_size = _list.size() * 2;
if (!new_max_size)
new_max_size = 1;
_list.resize(new_max_size);
}
Vector<T> _list;
int _size;
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,140 @@
/*************************************************************************/
/* rasterizer_canvas_base_gles2.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RASTERIZERCANVASBASEGLES2_H
#define RASTERIZERCANVASBASEGLES2_H
#include "rasterizer_array_gles2.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 "shaders/canvas_shadow.glsl.gen.h"
class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
public:
enum {
INSTANCE_ATTRIB_BASE = 8,
};
struct Uniforms {
Transform projection_matrix;
Transform2D modelview_matrix;
Transform2D extra_matrix;
Color final_modulate;
float time;
};
struct Data {
GLuint canvas_quad_vertices;
GLuint polygon_buffer;
GLuint polygon_index_buffer;
uint32_t polygon_buffer_size;
uint32_t polygon_index_buffer_size;
GLuint ninepatch_vertices;
GLuint ninepatch_elements;
} data;
struct State {
Uniforms uniforms;
bool canvas_texscreen_used;
CanvasShaderGLES2 canvas_shader;
CanvasShadowShaderGLES2 canvas_shadow_shader;
LensDistortedShaderGLES2 lens_shader;
bool using_texture_rect;
bool using_ninepatch;
bool using_skeleton;
Transform2D skeleton_transform;
Transform2D skeleton_transform_inverse;
Size2i skeleton_texture_size;
RID current_tex;
RID current_normal;
RasterizerStorageGLES2::Texture *current_tex_ptr;
Transform vp;
Light *using_light;
bool using_shadow;
bool using_transparent_rt;
} state;
typedef void Texture;
RasterizerSceneGLES2 *scene_render;
RasterizerStorageGLES2 *storage;
bool use_nvidia_rect_workaround;
void _set_uniforms();
virtual RID light_internal_create();
virtual void light_internal_update(RID p_rid, Light *p_light);
virtual void light_internal_free(RID p_rid);
virtual void canvas_begin();
virtual void canvas_end();
void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
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, const float *p_weights = NULL, const int *p_bones = NULL);
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);
void _draw_generic_indices(GLuint p_primitive, 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);
void _bind_quad_buffer();
void _copy_texscreen(const Rect2 &p_rect);
void _copy_screen(const Rect2 &p_rect);
virtual void draw_window_margins(int *black_margin, RID *black_image);
void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
virtual void reset_canvas();
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
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 initialize();
void finalize();
RasterizerCanvasBaseGLES2();
};
#endif // RASTERIZERCANVASBASEGLES2_H

File diff suppressed because it is too large Load diff

View file

@ -31,118 +31,365 @@
#ifndef RASTERIZERCANVASGLES2_H #ifndef RASTERIZERCANVASGLES2_H
#define RASTERIZERCANVASGLES2_H #define RASTERIZERCANVASGLES2_H
#include "rasterizer_storage_gles2.h" #include "rasterizer_canvas_base_gles2.h"
#include "servers/visual/rasterizer.h"
#include "shaders/canvas.glsl.gen.h"
#include "shaders/lens_distorted.glsl.gen.h"
#include "shaders/canvas_shadow.glsl.gen.h"
class RasterizerSceneGLES2; class RasterizerSceneGLES2;
class RasterizerCanvasGLES2 : public RasterizerCanvas { class RasterizerCanvasGLES2 : public RasterizerCanvasBaseGLES2 {
public:
enum { // used to determine whether we use hardware transform (none)
INSTANCE_ATTRIB_BASE = 8, // software transform all verts, or software transform just a translate
// (no rotate or scale)
enum TransformMode {
TM_NONE,
TM_ALL,
TM_TRANSLATE,
}; };
struct Uniforms { // pod versions of vector and color and RID, need to be 32 bit for vertex format
Transform projection_matrix; struct BatchVector2 {
float x, y;
void set(const Vector2 &p_o) {
x = p_o.x;
y = p_o.y;
}
void to(Vector2 &r_o) const {
r_o.x = x;
r_o.y = y;
}
};
Transform2D modelview_matrix; struct BatchColor {
Transform2D extra_matrix; float r, g, b, a;
void set(const Color &p_c) {
r = p_c.r;
g = p_c.g;
b = p_c.b;
a = p_c.a;
}
bool equals(const Color &p_c) const {
return (r == p_c.r) && (g == p_c.g) && (b == p_c.b) && (a == p_c.a);
}
const float *get_data() const { return &r; }
};
struct BatchVertex {
// must be 32 bit pod
BatchVector2 pos;
BatchVector2 uv;
};
struct BatchVertexColored : public BatchVertex {
// must be 32 bit pod
BatchColor col;
};
struct Batch {
enum CommandType : uint32_t {
BT_DEFAULT,
BT_RECT,
};
CommandType type;
uint32_t first_command; // also item reference number
uint32_t num_commands;
uint32_t first_quad;
uint32_t batch_texture_id;
BatchColor color;
};
struct BatchTex {
enum TileMode : uint32_t {
TILE_OFF,
TILE_NORMAL,
TILE_FORCE_REPEAT,
};
RID RID_texture;
RID RID_normal;
TileMode tile_mode;
BatchVector2 tex_pixel_size;
};
// batch item may represent 1 or more items
struct BItemJoined {
uint32_t first_item_ref;
uint32_t num_item_refs;
Rect2 bounding_rect;
// we are always splitting items with lots of commands,
// and items with unhandled primitives (default)
bool use_hardware_transform() const { return num_item_refs == 1; }
};
struct BItemRef {
Item *item;
Color final_modulate;
};
struct BatchData {
BatchData();
void reset_flush() {
batches.reset();
batch_textures.reset();
vertices.reset();
total_quads = 0;
total_color_changes = 0;
}
GLuint gl_vertex_buffer;
GLuint gl_index_buffer;
uint32_t max_quads;
uint32_t vertex_buffer_size_units;
uint32_t vertex_buffer_size_bytes;
uint32_t index_buffer_size_units;
uint32_t index_buffer_size_bytes;
RasterizerArrayGLES2<BatchVertex> vertices;
RasterizerArrayGLES2<BatchVertexColored> vertices_colored;
RasterizerArrayGLES2<Batch> batches;
RasterizerArrayGLES2<Batch> batches_temp; // used for translating to colored vertex batches
RasterizerArray_non_pod_GLES2<BatchTex> batch_textures; // the only reason this is non-POD is because of RIDs
bool use_colored_vertices;
RasterizerArrayGLES2<BItemJoined> items_joined;
RasterizerArrayGLES2<BItemRef> item_refs;
// counts
int total_quads;
// we keep a record of how many color changes caused new batches
// if the colors are causing an excessive number of batches, we switch
// to alternate batching method and add color to the vertex format.
int total_color_changes;
// measured in pixels, recalculated each frame
float scissor_threshold_area;
// diagnose this frame, every nTh frame when settings_diagnose_frame is on
bool diagnose_frame;
String frame_string;
uint32_t next_diagnose_tick;
uint64_t diagnose_frame_number;
// global settings
bool settings_use_batching; // the current use_batching (affected by flash)
bool settings_use_batching_original_choice; // the choice entered in project settings
bool settings_flash_batching; // for regression testing, flash between non-batched and batched renderer
bool settings_diagnose_frame; // print out batches to help optimize / regression test
int settings_max_join_item_commands;
float settings_colored_vertex_format_threshold;
int settings_batch_buffer_num_verts;
bool settings_scissor_lights;
float settings_scissor_threshold; // 0.0 to 1.0
} bdata;
struct RenderItemState {
RenderItemState() { reset(); }
void reset();
Item *current_clip;
RasterizerStorageGLES2::Shader *shader_cache;
bool rebind_shader;
bool prev_use_skeleton;
int last_blend_mode;
RID canvas_last_material;
Color final_modulate; Color final_modulate;
float time; // used for joining items only
BItemJoined *joined_item;
// 'item group' is data over a single call to canvas_render_items
int item_group_z;
Color item_group_modulate;
Light *item_group_light;
Transform2D item_group_base_transform;
} _render_item_state;
struct FillState {
void reset() {
// don't reset members that need to be preserved after flushing
// half way through a list of commands
curr_batch = 0;
batch_tex_id = -1;
texpixel_size = Vector2(1, 1);
}
Batch *curr_batch;
int batch_tex_id;
bool use_hardware_transform;
Vector2 texpixel_size;
Color final_modulate;
TransformMode transform_mode;
TransformMode orig_transform_mode;
// support for extra matrices
bool extra_matrix_sent; // whether sent on this item (in which case sofware transform can't be used untl end of item)
int transform_extra_command_number_p1; // plus one to allow fast checking against zero
Transform2D transform_combined; // final * extra
}; };
struct Data { public:
virtual void canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
GLuint canvas_quad_vertices; virtual void canvas_render_items_end();
GLuint polygon_buffer;
GLuint polygon_index_buffer;
uint32_t polygon_buffer_size;
uint32_t polygon_index_buffer_size;
GLuint ninepatch_vertices;
GLuint ninepatch_elements;
} data;
struct State {
Uniforms uniforms;
bool canvas_texscreen_used;
CanvasShaderGLES2 canvas_shader;
CanvasShadowShaderGLES2 canvas_shadow_shader;
LensDistortedShaderGLES2 lens_shader;
bool using_texture_rect;
bool using_ninepatch;
bool using_skeleton;
Transform2D skeleton_transform;
Transform2D skeleton_transform_inverse;
Size2i skeleton_texture_size;
RID current_tex;
RID current_normal;
RasterizerStorageGLES2::Texture *current_tex_ptr;
Transform vp;
Light *using_light;
bool using_shadow;
bool using_transparent_rt;
} state;
typedef void Texture;
RasterizerSceneGLES2 *scene_render;
RasterizerStorageGLES2 *storage;
bool use_nvidia_rect_workaround;
virtual RID light_internal_create();
virtual void light_internal_update(RID p_rid, Light *p_light);
virtual void light_internal_free(RID p_rid);
void _set_uniforms();
virtual void canvas_begin();
virtual void canvas_end();
_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, const float *p_weights = NULL, const int *p_bones = NULL);
_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 _draw_generic_indices(GLuint p_primitive, 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 _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material);
void _copy_screen(const Rect2 &p_rect);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform); virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow); virtual void canvas_begin();
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); private:
// legacy codepath .. to remove after testing
void _canvas_render_item(Item *p_ci, RenderItemState &r_ris);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);
virtual void reset_canvas(); // high level batch funcs
void canvas_render_items_implementation(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform);
void render_joined_item(const BItemJoined &p_bij, RenderItemState &r_ris);
void join_items(Item *p_item_list, int p_z);
bool try_join_item(Item *p_ci, RenderItemState &r_ris, bool &r_batch_break);
void render_joined_item_commands(const BItemJoined &p_bij, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);
void render_batches(Item::Command *const *p_commands, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);
bool prefill_joined_item(FillState &r_fill_state, int &r_command_start, Item *p_item, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);
void flush_render_batches(Item *p_first_item, Item *p_current_clip, bool &r_reclip, RasterizerStorageGLES2::Material *p_material);
RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); // low level batch funcs
void _batch_translate_to_colored();
_FORCE_INLINE_ int _batch_find_or_create_tex(const RID &p_texture, const RID &p_normal, bool p_tile, int p_previous_match);
RasterizerStorageGLES2::Texture *_get_canvas_texture(const RID &p_texture) const;
void _batch_upload_buffers();
void _batch_render_rects(const Batch &p_batch, RasterizerStorageGLES2::Material *p_material);
BatchVertex *_batch_vertex_request_new() { return bdata.vertices.request(); }
Batch *_batch_request_new(bool p_blank = true);
void _bind_quad_buffer(); bool _detect_batch_break(Item *p_ci);
void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src); void _software_transform_vertex(BatchVector2 &r_v, const Transform2D &p_tr) const;
void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); void _software_transform_vertex(Vector2 &r_v, const Transform2D &p_tr) const;
TransformMode _find_transform_mode(const Transform2D &p_tr) const;
_FORCE_INLINE_ void _prefill_default_batch(FillState &r_fill_state, int p_command_num, const Item &p_item);
// light scissoring
bool _light_find_intersection(const Rect2 &p_item_rect, const Transform2D &p_light_xform, const Rect2 &p_light_rect, Rect2 &r_cliprect) const;
bool _light_scissor_begin(const Rect2 &p_item_rect, const Transform2D &p_light_xform, const Rect2 &p_light_rect) const;
void _calculate_scissor_threshold_area();
// debug
void diagnose_batches(Item::Command *const *p_commands);
public:
void initialize(); void initialize();
void finalize();
virtual void draw_window_margins(int *black_margin, RID *black_image);
RasterizerCanvasGLES2(); RasterizerCanvasGLES2();
}; };
//////////////////////////////////////////////////////////////
// Default batches will not occur in software transform only items
// EXCEPT IN THE CASE OF SINGLE RECTS (and this may well not occur, check the logic in prefill_join_item TYPE_RECT)
// but can occur where transform commands have been sent during hardware batch
_FORCE_INLINE_ void RasterizerCanvasGLES2::_prefill_default_batch(FillState &r_fill_state, int p_command_num, const Item &p_item) {
if (r_fill_state.curr_batch->type == Batch::BT_DEFAULT) {
// don't need to flush an extra transform command?
if (!r_fill_state.transform_extra_command_number_p1) {
// another default command, just add to the existing batch
r_fill_state.curr_batch->num_commands++;
} else {
#ifdef DEBUG_ENABLED
if (r_fill_state.transform_extra_command_number_p1 != p_command_num) {
WARN_PRINT_ONCE("_prefill_default_batch : transform_extra_command_number_p1 != p_command_num");
}
#endif
// we do have a pending extra transform command to flush
// either the extra transform is in the prior command, or not, in which case we need 2 batches
// if (r_fill_state.transform_extra_command_number_p1 == p_command_num) {
// this should be most common case
r_fill_state.curr_batch->num_commands += 2;
// } else {
// // mad ordering .. does this even happen?
// int extra_command = r_fill_state.transform_extra_command_number_p1 - 1; // plus 1 based
// // send the extra to the GPU in a batch
// r_fill_state.curr_batch = _batch_request_new();
// r_fill_state.curr_batch->type = Batch::BT_DEFAULT;
// r_fill_state.curr_batch->first_command = extra_command;
// r_fill_state.curr_batch->num_commands = 1;
// // start default batch
// r_fill_state.curr_batch = _batch_request_new();
// r_fill_state.curr_batch->type = Batch::BT_DEFAULT;
// r_fill_state.curr_batch->first_command = p_command_num;
// r_fill_state.curr_batch->num_commands = 1;
// }
r_fill_state.transform_extra_command_number_p1 = 0; // mark as sent
r_fill_state.extra_matrix_sent = true;
// the original mode should always be hardware transform ..
// test this assumption
r_fill_state.transform_mode = r_fill_state.orig_transform_mode;
// do we need to restore anything else?
}
} else {
// end of previous different type batch, so start new default batch
// first consider whether there is a dirty extra matrix to send
if (r_fill_state.transform_extra_command_number_p1) {
// get which command the extra is in, and blank all the records as it no longer is stored CPU side
int extra_command = r_fill_state.transform_extra_command_number_p1 - 1; // plus 1 based
r_fill_state.transform_extra_command_number_p1 = 0;
r_fill_state.extra_matrix_sent = true;
// send the extra to the GPU in a batch
r_fill_state.curr_batch = _batch_request_new();
r_fill_state.curr_batch->type = Batch::BT_DEFAULT;
r_fill_state.curr_batch->first_command = extra_command;
r_fill_state.curr_batch->num_commands = 1;
// revert to the original transform mode
// e.g. go back to NONE if we were in hardware transform mode
r_fill_state.transform_mode = r_fill_state.orig_transform_mode;
// reset the original transform if we are going back to software mode,
// because the extra is now done on the GPU...
// (any subsequent extras are sent directly to the GPU, no deferring)
if (r_fill_state.orig_transform_mode != TM_NONE) {
r_fill_state.transform_combined = p_item.final_transform;
}
// can possibly combine batch with the next one in some cases
// this is more efficient than having an extra batch especially for the extra
if ((extra_command + 1) == p_command_num) {
r_fill_state.curr_batch->num_commands = 2;
return;
}
}
// start default batch
r_fill_state.curr_batch = _batch_request_new();
r_fill_state.curr_batch->type = Batch::BT_DEFAULT;
r_fill_state.curr_batch->first_command = p_command_num;
r_fill_state.curr_batch->num_commands = 1;
}
}
_FORCE_INLINE_ void RasterizerCanvasGLES2::_software_transform_vertex(BatchVector2 &r_v, const Transform2D &p_tr) const {
Vector2 vc(r_v.x, r_v.y);
vc = p_tr.xform(vc);
r_v.set(vc);
}
_FORCE_INLINE_ void RasterizerCanvasGLES2::_software_transform_vertex(Vector2 &r_v, const Transform2D &p_tr) const {
r_v = p_tr.xform(r_v);
}
_FORCE_INLINE_ RasterizerCanvasGLES2::TransformMode RasterizerCanvasGLES2::_find_transform_mode(const Transform2D &p_tr) const {
// decided whether to do translate only for software transform
if ((p_tr.elements[0].x == 1.0) &&
(p_tr.elements[0].y == 0.0) &&
(p_tr.elements[1].x == 0.0) &&
(p_tr.elements[1].y == 1.0)) {
return TM_TRANSLATE;
}
return TM_ALL;
}
#endif // RASTERIZERCANVASGLES2_H #endif // RASTERIZERCANVASGLES2_H

View file

@ -5763,6 +5763,8 @@ void RasterizerStorageGLES2::render_info_end_capture() {
info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count; info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count;
info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count; info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count;
info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count;
info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count;
info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count;
} }
int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) { int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) {
@ -5786,6 +5788,12 @@ int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) {
case VS::INFO_DRAW_CALLS_IN_FRAME: { case VS::INFO_DRAW_CALLS_IN_FRAME: {
return info.snap.draw_call_count; return info.snap.draw_call_count;
} break; } break;
case VS::INFO_2D_ITEMS_IN_FRAME: {
return info.snap._2d_item_count;
} break;
case VS::INFO_2D_DRAW_CALLS_IN_FRAME: {
return info.snap._2d_draw_call_count;
} break;
default: { default: {
return get_render_info(p_info); return get_render_info(p_info);
} }
@ -5806,6 +5814,10 @@ int RasterizerStorageGLES2::get_render_info(VS::RenderInfo p_info) {
return info.render_final.surface_switch_count; return info.render_final.surface_switch_count;
case VS::INFO_DRAW_CALLS_IN_FRAME: case VS::INFO_DRAW_CALLS_IN_FRAME:
return info.render_final.draw_call_count; return info.render_final.draw_call_count;
case VS::INFO_2D_ITEMS_IN_FRAME:
return info.render_final._2d_item_count;
case VS::INFO_2D_DRAW_CALLS_IN_FRAME:
return info.render_final._2d_draw_call_count;
case VS::INFO_USAGE_VIDEO_MEM_TOTAL: case VS::INFO_USAGE_VIDEO_MEM_TOTAL:
return 0; //no idea return 0; //no idea
case VS::INFO_VIDEO_MEM_USED: case VS::INFO_VIDEO_MEM_USED:

View file

@ -149,6 +149,8 @@ public:
uint32_t surface_switch_count; uint32_t surface_switch_count;
uint32_t shader_rebind_count; uint32_t shader_rebind_count;
uint32_t vertices_count; uint32_t vertices_count;
uint32_t _2d_item_count;
uint32_t _2d_draw_call_count;
void reset() { void reset() {
object_count = 0; object_count = 0;
@ -157,6 +159,8 @@ public:
surface_switch_count = 0; surface_switch_count = 0;
shader_rebind_count = 0; shader_rebind_count = 0;
vertices_count = 0; vertices_count = 0;
_2d_item_count = 0;
_2d_draw_call_count = 0;
} }
} render, render_final, snap; } render, render_final, snap;

View file

@ -63,6 +63,8 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(RENDER_SHADER_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_SHADER_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_SURFACE_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_SURFACE_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_2D_ITEMS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_2D_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_VIDEO_MEM_USED); BIND_ENUM_CONSTANT(RENDER_VIDEO_MEM_USED);
BIND_ENUM_CONSTANT(RENDER_TEXTURE_MEM_USED); BIND_ENUM_CONSTANT(RENDER_TEXTURE_MEM_USED);
BIND_ENUM_CONSTANT(RENDER_VERTEX_MEM_USED); BIND_ENUM_CONSTANT(RENDER_VERTEX_MEM_USED);
@ -109,6 +111,8 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"raster/shader_changes", "raster/shader_changes",
"raster/surface_changes", "raster/surface_changes",
"raster/draw_calls", "raster/draw_calls",
"2d/items",
"2d/draw_calls",
"video/video_mem", "video/video_mem",
"video/texture_mem", "video/texture_mem",
"video/vertex_mem", "video/vertex_mem",
@ -147,6 +151,8 @@ float Performance::get_monitor(Monitor p_monitor) const {
case RENDER_SHADER_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME); case RENDER_SHADER_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME);
case RENDER_SURFACE_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); case RENDER_SURFACE_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME);
case RENDER_DRAW_CALLS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); case RENDER_DRAW_CALLS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_DRAW_CALLS_IN_FRAME);
case RENDER_2D_ITEMS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_2D_ITEMS_IN_FRAME);
case RENDER_2D_DRAW_CALLS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_2D_DRAW_CALLS_IN_FRAME);
case RENDER_VIDEO_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VIDEO_MEM_USED); case RENDER_VIDEO_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VIDEO_MEM_USED);
case RENDER_TEXTURE_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED); case RENDER_TEXTURE_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED);
case RENDER_VERTEX_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VERTEX_MEM_USED); case RENDER_VERTEX_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VERTEX_MEM_USED);
@ -189,6 +195,8 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY, MONITOR_TYPE_MEMORY,

View file

@ -69,6 +69,8 @@ public:
RENDER_SHADER_CHANGES_IN_FRAME, RENDER_SHADER_CHANGES_IN_FRAME,
RENDER_SURFACE_CHANGES_IN_FRAME, RENDER_SURFACE_CHANGES_IN_FRAME,
RENDER_DRAW_CALLS_IN_FRAME, RENDER_DRAW_CALLS_IN_FRAME,
RENDER_2D_ITEMS_IN_FRAME,
RENDER_2D_DRAW_CALLS_IN_FRAME,
RENDER_VIDEO_MEM_USED, RENDER_VIDEO_MEM_USED,
RENDER_TEXTURE_MEM_USED, RENDER_TEXTURE_MEM_USED,
RENDER_VERTEX_MEM_USED, RENDER_VERTEX_MEM_USED,

View file

@ -3287,6 +3287,8 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_2D_ITEMS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_2D_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_MAX); BIND_ENUM_CONSTANT(RENDER_INFO_MAX);
BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED); BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED);

View file

@ -133,6 +133,8 @@ public:
RENDER_INFO_SHADER_CHANGES_IN_FRAME, RENDER_INFO_SHADER_CHANGES_IN_FRAME,
RENDER_INFO_SURFACE_CHANGES_IN_FRAME, RENDER_INFO_SURFACE_CHANGES_IN_FRAME,
RENDER_INFO_DRAW_CALLS_IN_FRAME, RENDER_INFO_DRAW_CALLS_IN_FRAME,
RENDER_INFO_2D_ITEMS_IN_FRAME,
RENDER_INFO_2D_DRAW_CALLS_IN_FRAME,
RENDER_INFO_MAX RENDER_INFO_MAX
}; };

View file

@ -1066,6 +1066,8 @@ public:
virtual void canvas_begin() = 0; virtual void canvas_begin() = 0;
virtual void canvas_end() = 0; virtual void canvas_end() = 0;
virtual void canvas_render_items_begin(const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {}
virtual void canvas_render_items_end() {}
virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) = 0; virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) = 0;
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;

View file

@ -42,11 +42,13 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
_render_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); _render_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
VSG::canvas_render->canvas_render_items_begin(p_modulate, p_lights, p_transform);
for (int i = 0; i < z_range; i++) { for (int i = 0; i < z_range; i++) {
if (!z_list[i]) if (!z_list[i])
continue; continue;
VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights, p_transform); VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights, p_transform);
} }
VSG::canvas_render->canvas_render_items_end();
} }
void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, const Color p_modulate, VisualServerCanvas::Item **r_items, int &r_index) { void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, const Color p_modulate, VisualServerCanvas::Item **r_items, int &r_index) {
@ -259,6 +261,7 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
_render_canvas_item(ci[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); _render_canvas_item(ci[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
} }
VSG::canvas_render->canvas_render_items_begin(p_canvas->modulate, p_lights, p_transform);
for (int i = 0; i < z_range; i++) { for (int i = 0; i < z_range; i++) {
if (!z_list[i]) if (!z_list[i])
continue; continue;
@ -269,6 +272,7 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights, p_transform); VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights, p_transform);
} }
VSG::canvas_render->canvas_render_items_end();
} else { } else {
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {

View file

@ -349,6 +349,8 @@ void VisualServerViewport::draw_viewports() {
vp->render_info[VS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME);
vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME);
vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME);
vp->render_info[VS::VIEWPORT_RENDER_INFO_2D_ITEMS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_2D_ITEMS_IN_FRAME);
vp->render_info[VS::VIEWPORT_RENDER_INFO_2D_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_2D_DRAW_CALLS_IN_FRAME);
if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) {
//copy to screen if set as such //copy to screen if set as such

View file

@ -2188,6 +2188,8 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_2D_ITEMS_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_2D_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX); BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED);
@ -2247,6 +2249,8 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_2D_ITEMS_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_2D_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL); BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL);
BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED); BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED);
BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED); BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED);
@ -2411,6 +2415,20 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false);
GLOBAL_DEF("rendering/gles2/batching/use_batching", true);
GLOBAL_DEF("rendering/gles2/batching/max_join_item_commands", 16);
GLOBAL_DEF("rendering/gles2/batching/colored_vertex_format_threshold", 0.25f);
GLOBAL_DEF("rendering/gles2/batching/light_scissor_area_threshold", 1.0f);
GLOBAL_DEF("rendering/gles2/batching/batch_buffer_size", 16384);
GLOBAL_DEF("rendering/gles2/debug/flash_batching", false);
GLOBAL_DEF("rendering/gles2/debug/diagnose_frame", false);
GLOBAL_DEF_RST("rendering/gles2/debug/use_batching_in_editor", true);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles2/batching/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/gles2/batching/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles2/batching/colored_vertex_format_threshold", PropertyInfo(Variant::REAL, "rendering/gles2/batching/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles2/batching/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/gles2/batching/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/gles2/batching/light_scissor_area_threshold", PropertyInfo(Variant::REAL, "rendering/gles2/batching/light_scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0"));
} }
VisualServer::~VisualServer() { VisualServer::~VisualServer() {

View file

@ -689,6 +689,8 @@ public:
VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME, VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME,
VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME, VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME,
VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME, VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME,
VIEWPORT_RENDER_INFO_2D_ITEMS_IN_FRAME,
VIEWPORT_RENDER_INFO_2D_DRAW_CALLS_IN_FRAME,
VIEWPORT_RENDER_INFO_MAX VIEWPORT_RENDER_INFO_MAX
}; };
@ -1016,6 +1018,8 @@ public:
INFO_SHADER_CHANGES_IN_FRAME, INFO_SHADER_CHANGES_IN_FRAME,
INFO_SURFACE_CHANGES_IN_FRAME, INFO_SURFACE_CHANGES_IN_FRAME,
INFO_DRAW_CALLS_IN_FRAME, INFO_DRAW_CALLS_IN_FRAME,
INFO_2D_ITEMS_IN_FRAME,
INFO_2D_DRAW_CALLS_IN_FRAME,
INFO_USAGE_VIDEO_MEM_TOTAL, INFO_USAGE_VIDEO_MEM_TOTAL,
INFO_VIDEO_MEM_USED, INFO_VIDEO_MEM_USED,
INFO_TEXTURE_MEM_USED, INFO_TEXTURE_MEM_USED,