Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLES2 2D fix normal mapping - batching and nvidia workaround #41323

Merged
merged 1 commit into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions drivers/gles2/rasterizer_array_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,75 @@

#include <string.h>

// very simple non-growable array, that keeps track of the size of a 'unit'
// which can be cast to whatever vertex format FVF required, and is initially
// created with enough memory to hold the biggest FVF.
// This allows multiple FVFs to use the same array.
class RasterizerUnitArrayGLES2 {
public:
RasterizerUnitArrayGLES2() {
_list = nullptr;
free();
}
~RasterizerUnitArrayGLES2() { free(); }

uint8_t *get_unit(unsigned int ui) { return &_list[ui * _unit_size_bytes]; }
const uint8_t *get_unit(unsigned int ui) const { return &_list[ui * _unit_size_bytes]; }

int size() const { return _size; }
int max_size() const { return _max_size; }

void free() {
if (_list) {
memdelete_arr(_list);
_list = 0;
}
_size = 0;
_max_size = 0;
_max_size_bytes = 0;
_unit_size_bytes = 0;
}

void create(int p_max_size_units, int p_max_unit_size_bytes) {
free();

_max_unit_size_bytes = p_max_unit_size_bytes;
_max_size = p_max_size_units;
_max_size_bytes = p_max_size_units * p_max_unit_size_bytes;

if (_max_size_bytes) {
_list = memnew_arr(uint8_t, _max_size_bytes);
}
}

void prepare(int p_unit_size_bytes) {
_unit_size_bytes = p_unit_size_bytes;
_size = 0;
}

// several items at a time
uint8_t *request(int p_num_items = 1) {
int old_size = _size;
_size += p_num_items;

if (_size <= _max_size) {
return get_unit(old_size);
}

// revert
_size = old_size;
return nullptr;
}

private:
uint8_t *_list;
int _size; // in units
int _max_size; // in units
int _max_size_bytes;
int _unit_size_bytes;
int _max_unit_size_bytes;
};

template <class T>
class RasterizerArrayGLES2 {
public:
Expand Down
45 changes: 41 additions & 4 deletions drivers/gles2/rasterizer_canvas_base_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,13 @@ void RasterizerCanvasBaseGLES2::light_internal_free(RID p_rid) {

void RasterizerCanvasBaseGLES2::canvas_begin() {

state.canvas_shader.bind();
state.using_transparent_rt = false;

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

int viewport_x, viewport_y, viewport_width, viewport_height;

if (storage->frame.current_rt) {
Expand Down Expand Up @@ -155,6 +160,16 @@ 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) {
// 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);
}
}

RasterizerStorageGLES2::Texture *RasterizerCanvasBaseGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) {

RasterizerStorageGLES2::Texture *tex_return = NULL;
Expand Down Expand Up @@ -595,12 +610,13 @@ void RasterizerCanvasBaseGLES2::_draw_generic_indices(GLuint p_primitive, const
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) {
void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const float *p_light_angles) {

static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };

int color_offset = 0;
int uv_offset = 0;
int light_angle_offset = 0;
int stride = 2;

if (p_colors) {
Expand All @@ -613,7 +629,12 @@ void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2
stride += 2;
}

float buffer_data[(2 + 2 + 4) * 4];
if (p_light_angles) { //light_angles
light_angle_offset = stride;
stride += 1;
}

float buffer_data[(2 + 2 + 4 + 1) * 4];

for (int i = 0; i < p_points; i++) {
buffer_data[stride * i + 0] = p_vertices[i].x;
Expand All @@ -636,6 +657,12 @@ void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2
}
}

if (p_light_angles) {
for (int i = 0; i < p_points; i++) {
buffer_data[stride * i + light_angle_offset + 0] = p_light_angles[i];
}
}

glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
#ifndef GLES_OVER_GL
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
Expand All @@ -655,9 +682,19 @@ void RasterizerCanvasBaseGLES2::_draw_gui_primitive(int p_points, const Vector2
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
}

if (p_light_angles) {
glVertexAttribPointer(VS::ARRAY_TANGENT, 1, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(light_angle_offset * sizeof(float)));
glEnableVertexAttribArray(VS::ARRAY_TANGENT);
}

glDrawArrays(prim[p_points], 0, p_points);
storage->info.render._2d_draw_call_count++;

if (p_light_angles) {
// may not be needed
glDisableVertexAttribArray(VS::ARRAY_TANGENT);
}

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

Expand Down Expand Up @@ -993,7 +1030,7 @@ void RasterizerCanvasBaseGLES2::initialize() {

state.canvas_shader.init();

state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
_set_texture_rect_mode(true);
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);

state.canvas_shader.bind();
Expand Down
4 changes: 3 additions & 1 deletion drivers/gles2/rasterizer_canvas_base_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
LensDistortedShaderGLES2 lens_shader;

bool using_texture_rect;
bool using_light_angle;
bool using_ninepatch;
bool using_skeleton;

Expand Down Expand Up @@ -112,7 +113,7 @@ class RasterizerCanvasBaseGLES2 : public RasterizerCanvas {
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_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs, const float *p_light_angles = nullptr);
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);
Expand All @@ -130,6 +131,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 initialize();
void finalize();
Expand Down
Loading