diff options
Diffstat (limited to 'source/blender/gpu')
19 files changed, 654 insertions, 5 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index c5531b8542e..364e77123d9 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../imbuf ../makesdna ../makesrna + ../draw ../editors/include @@ -64,6 +65,7 @@ set(SRC intern/gpu_select.c intern/gpu_shader.c intern/gpu_texture.c + intern/gpu_uniformbuffer.c intern/gpu_viewport.c gawain/attrib_binding.c @@ -122,6 +124,7 @@ set(SRC GPU_select.h GPU_shader.h GPU_texture.h + GPU_uniformbuffer.h GPU_viewport.h intern/gpu_codegen.h @@ -145,10 +148,16 @@ data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_instance_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_groundline_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_lamp_vert.glsl SRC) + data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 31ad8243c4b..ff00a83d00b 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -53,6 +53,8 @@ int GPU_max_textures(void); float GPU_max_texture_anisotropy(void); int GPU_max_color_texture_samples(void); int GPU_max_cube_map_size(void); +int GPU_max_ubo_binds(void); +int GPU_max_ubo_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 989b874fd38..9611a6f0577 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -52,6 +52,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex); GPUFrameBuffer *GPU_framebuffer_create(void); bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot); void GPU_framebuffer_texture_detach(struct GPUTexture *tex); +void GPU_framebuffer_bind(GPUFrameBuffer *fb); void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot); void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex); void GPU_framebuffer_free(GPUFrameBuffer *fb); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 394e751ed9b..b36954dd010 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -38,6 +38,7 @@ extern "C" { typedef struct GPUShader GPUShader; struct GPUTexture; +struct GPUUniformBuffer; /* GPU Shader * - only for fragment shaders now @@ -69,14 +70,17 @@ void GPU_shader_free(GPUShader *shader); void GPU_shader_bind(GPUShader *shader); void GPU_shader_unbind(void); +int GPU_shader_get_program(GPUShader *shader); void *GPU_shader_get_interface(GPUShader *shader); void GPU_shader_set_interface(GPUShader *shader, void *interface); int GPU_shader_get_uniform(GPUShader *shader, const char *name); +int GPU_shader_get_uniform_block(GPUShader *shader, const char *name); void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, const float *value); void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length, int arraysize, const int *value); +void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo); void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex); void GPU_shader_uniform_int(GPUShader *shader, int location, int value); void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number); @@ -104,6 +108,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_2D_IMAGE_COLOR, /* for simple 3D drawing */ GPU_SHADER_3D_UNIFORM_COLOR, + GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, GPU_SHADER_3D_FLAT_COLOR, GPU_SHADER_3D_SMOOTH_COLOR, GPU_SHADER_3D_DEPTH_ONLY, @@ -126,6 +131,10 @@ typedef enum GPUBuiltinShader { GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH, GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR, GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, + /* lamp drawing */ + GPU_SHADER_3D_GROUNDPOINT, + GPU_SHADER_3D_GROUNDLINE, + GPU_SHADER_3D_LAMP_COMMON, GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */ } GPUBuiltinShader; diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h new file mode 100644 index 00000000000..bcb6e1077b7 --- /dev/null +++ b/source/blender/gpu/GPU_uniformbuffer.h @@ -0,0 +1,44 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file GPU_uniformbuffer.h + * \ingroup gpu + */ + +typedef struct GPUUniformBuffer GPUUniformBuffer; + +GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]); +void GPU_uniformbuffer_free(GPUUniformBuffer *ubo); + +void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data); + +void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number); +#if 0 +void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo); +#endif + +int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo); diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index fce509377ab..e44657a4647 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -34,12 +34,52 @@ #include <stdbool.h> +#include "DNA_vec_types.h" + +#include "GPU_framebuffer.h" +#include "GPU_texture.h" + typedef struct GPUViewport GPUViewport; -GPUViewport *GPU_viewport_create(void); +#define MAX_BUFFERS 8 +#define MAX_TEXTURES 16 +#define MAX_PASSES 16 + +/* All FramebufferLists are just the same pointers with different names */ +typedef struct FramebufferList { + struct GPUFrameBuffer *framebuffers[MAX_BUFFERS]; +} FramebufferList; + +typedef struct TextureList { + struct GPUTexture *textures[MAX_TEXTURES]; +} TextureList; + +typedef struct PassList { + struct DRWPass *passes[MAX_TEXTURES]; +} PassList; +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; +} DefaultTextureList; + +typedef struct DefaultPassList { + struct DRWPass *non_meshes_pass; + struct DRWPass *ob_center_pass; +} DefaultPassList; + +GPUViewport *GPU_viewport_create(void); +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect); +void GPU_viewport_unbind(GPUViewport *viewport); void GPU_viewport_free(GPUViewport *viewport); +void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss); + /* debug */ bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]); void GPU_viewport_debug_depth_free(GPUViewport *viewport); diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c index a60865d41d2..99c13301177 100644 --- a/source/blender/gpu/gawain/batch.c +++ b/source/blender/gpu/gawain/batch.c @@ -247,3 +247,89 @@ void Batch_draw(Batch* batch) Batch_done_using_program(batch); glBindVertexArray(0); } + +/* clement : temp stuff */ +void Batch_draw_stupid(Batch* batch) +{ + if (batch->vao_id) + glBindVertexArray(batch->vao_id); + else + Batch_prime(batch); + + if (batch->program_dirty) + Batch_update_program_bindings(batch); + + // Batch_use_program(batch); + + //gpuBindMatrices(batch->program); + + if (batch->elem) + { + const ElementList* el = batch->elem; + +#if TRACK_INDEX_RANGE + if (el->base_index) + glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index); + else + glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0); +#else + glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0); +#endif + } + else + glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); + + // Batch_done_using_program(batch); + glBindVertexArray(0); +} + +/* clement : temp stuff */ +void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count) +{ + if (batch->vao_id) + glBindVertexArray(batch->vao_id); + else + Batch_prime(batch); + + if (batch->program_dirty) + Batch_update_program_bindings(batch); + + const GLint loc = glGetAttribLocation(batch->program, "InstanceModelMatrix"); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)0); + glEnableVertexAttribArray(loc + 1); + glVertexAttribPointer(loc + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(sizeof(float)*4)); + glEnableVertexAttribArray(loc + 2); + glVertexAttribPointer(loc + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(2 * sizeof(float)*4)); + glEnableVertexAttribArray(loc + 3); + glVertexAttribPointer(loc + 3, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(3 * sizeof(float)*4)); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glVertexAttribDivisor(loc + 0, 1); + glVertexAttribDivisor(loc + 1, 1); + glVertexAttribDivisor(loc + 2, 1); + glVertexAttribDivisor(loc + 3, 1); + + // Batch_use_program(batch); + + //gpuBindMatrices(batch->program); + + if (batch->elem) + { + const ElementList* el = batch->elem; + + glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count); + } + else + glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count); + + // Batch_done_using_program(batch); + glBindVertexArray(0); +} + diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h index 932ee182703..8b5c48cca79 100644 --- a/source/blender/gpu/gawain/batch.h +++ b/source/blender/gpu/gawain/batch.h @@ -57,6 +57,8 @@ void Batch_Uniform3fv(Batch*, const char* name, const float data[3]); void Batch_Uniform4fv(Batch*, const char* name, const float data[4]); void Batch_draw(Batch*); +void Batch_draw_stupid(Batch* batch); +void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e8fd4b8b8b1..d7ed65e853e 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -69,6 +69,8 @@ static struct GPUGlobal { GLint maxtexsize; GLint maxcubemapsize; GLint maxtextures; + GLint maxubosize; + GLint maxubobinds; bool extdisabled; int colordepth; int samples_color_texture_max; @@ -121,6 +123,16 @@ int GPU_max_cube_map_size(void) return GG.maxcubemapsize; } +int GPU_max_ubo_binds(void) +{ + return GG.maxubobinds; +} + +int GPU_max_ubo_size(void) +{ + return GG.maxubosize; +} + void GPU_get_dfdy_factors(float fac[2]) { copy_v2_v2(fac, GG.dfdyfactors); @@ -154,6 +166,9 @@ void gpu_extensions_init(void) else GG.max_anisotropy = 1.0f; + glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize); + GLint r, g, b; glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index 2ef8018e5e9..1efc451f4a8 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -260,6 +260,43 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) glPushMatrix(); } +void GPU_framebuffer_bind(GPUFrameBuffer *fb) +{ + int numslots = 0, i; + GLenum attachments[4]; + GLenum readattachement = 0; + GPUTexture *tex; + + for (i = 0; i < 4; i++) { + if (fb->colortex[i]) { + attachments[numslots] = GL_COLOR_ATTACHMENT0 + i; + tex = fb->colortex[i]; + + if (!readattachement) + readattachement = GL_COLOR_ATTACHMENT0 + i; + + numslots++; + } + } + + /* bind framebuffer */ + glBindFramebuffer(GL_FRAMEBUFFER, fb->object); + + if (numslots == 0) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + tex = fb->depthtex; + } + else { + /* last bound prevails here, better allow explicit control here too */ + glDrawBuffers(numslots, attachments); + glReadBuffer(readattachement); + } + + glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex)); + GG.currentfb = fb->object; +} + void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex)) { @@ -283,7 +320,6 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot) /* push matrices and set default viewport and matrix */ glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot])); GG.currentfb = fb->object; - GG.currentfb = fb->object; } bool GPU_framebuffer_bound(GPUFrameBuffer *fb) diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index b81c19d5c70..0d6fd5f7b99 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -37,6 +37,7 @@ #include "GPU_debug.h" #include "GPU_extensions.h" #include "GPU_shader.h" +#include "GPU_uniformbuffer.h" #include "GPU_texture.h" #include "gpu_shader_private.h" @@ -64,10 +65,16 @@ extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[]; extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[]; extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_gpu_shader_3D_instance_vert_glsl[]; extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[]; +extern char datatoc_gpu_shader_3D_groundline_vert_glsl[]; +extern char datatoc_gpu_shader_3D_groundline_geom_glsl[]; +extern char datatoc_gpu_shader_3D_lamp_vert_glsl[]; + extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[]; extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[]; @@ -511,11 +518,24 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name) return glGetUniformLocation(shader->program, name); } +int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) +{ + BLI_assert(shader && shader->program); + + return glGetUniformBlockIndex(shader->program, name); +} + void *GPU_shader_get_interface(GPUShader *shader) { return shader->uniform_interface; } +/* Clement : Temp */ +int GPU_shader_get_program(GPUShader *shader) +{ + return (int)shader->program; +} + void GPU_shader_set_interface(GPUShader *shader, void *interface) { shader->uniform_interface = interface; @@ -563,6 +583,17 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou } } +void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo) +{ + int bindpoint = GPU_uniformbuffer_bindpoint(ubo); + + if (location == -1) { + return; + } + + glUniformBlockBinding(shader->program, location, bindpoint); +} + void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { int number = GPU_texture_bound_number(tex); @@ -645,12 +676,21 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_color_frag_glsl }, [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE] = { datatoc_gpu_shader_3D_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl, datatoc_gpu_shader_3D_smooth_color_frag_glsl }, [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl }, + [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_groundline_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + datatoc_gpu_shader_3D_groundline_geom_glsl }, + + [GPU_SHADER_3D_LAMP_COMMON] = { datatoc_gpu_shader_3D_lamp_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl}, + [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 6fb658e20eb..3513250993e 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -91,6 +91,7 @@ static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, /* Formats texture & renderbuffer */ case GPU_RGBA16F: return GL_RGBA16F; case GPU_RG32F: return GL_RG32F; + case GPU_RG16F: return GL_RG16F; case GPU_RGBA8: return GL_RGBA8; case GPU_R8: return GL_R8; /* Special formats texture & renderbuffer */ diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c new file mode 100644 index 00000000000..76aa1a8226f --- /dev/null +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -0,0 +1,105 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gpu_uniformbuffer.c + * \ingroup gpu + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "GPU_extensions.h" +#include "GPU_glew.h" +#include "GPU_uniformbuffer.h" + +struct GPUUniformBuffer { + int size; /* in bytes */ + GLuint bindcode; /* opengl identifier for UBO */ + int bindpoint; /* current binding point */ +}; + +GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]) +{ + GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBuffer), "GPUUniformBuffer"); + ubo->size = size; + + /* Generate Buffer object */ + glGenBuffers(1, &ubo->bindcode); + + if (!ubo->bindcode) { + if (err_out) + BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed"); + GPU_uniformbuffer_free(ubo); + return NULL; + } + + if (ubo->size > GPU_max_ubo_size()) { + if (err_out) + BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big"); + GPU_uniformbuffer_free(ubo); + return NULL; + } + + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + return ubo; +} + +void GPU_uniformbuffer_free(GPUUniformBuffer *ubo) +{ + glDeleteBuffers(1, &ubo->bindcode); + MEM_freeN(ubo); +} + +void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) +{ + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); +} + +void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number) +{ + if (number >= GPU_max_ubo_binds()) { + fprintf(stderr, "Not enough UBO slots.\n"); + return; + } + + if (ubo->bindcode != 0) { + glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode); + } + + ubo->bindpoint = number; +} + +int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo) +{ + return ubo->bindpoint; +}
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index a4fb3494639..b1964857ab1 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -31,10 +31,19 @@ * System that manages viewport drawing. */ +#include <string.h> + +#include "BLI_rect.h" + +#include "DNA_vec_types.h" + +#include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_immediate.h" -#include "GPU_viewport.h" #include "GPU_texture.h" +#include "GPU_viewport.h" + +#include "DRW_engine.h" #include "MEM_guardedalloc.h" @@ -43,19 +52,200 @@ struct GPUViewport { /* debug */ GPUTexture *debug_depth; - int debug_width, debug_height; + int size[2]; + + /* Viewport Buffer Storage */ + /* TODO indentify to what engine conf are theses buffers */ + DefaultFramebufferList *fbl; + DefaultTextureList *txl; + DefaultPassList *psl; }; +static void GPU_viewport_buffers_free(GPUViewport *viewport); +static void GPU_viewport_passes_free(GPUViewport *viewport); + GPUViewport *GPU_viewport_create(void) { GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); + viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); + viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList"); + viewport->psl = MEM_callocN(sizeof(PassList), "PassList"); + viewport->size[0] = viewport->size[1] = -1; + return viewport; } +void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss) +{ + *fbs = viewport->fbl; + *txs = viewport->txl; + *pss = viewport->psl; +} + +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) +{ + /* add one pixel because of scissor test */ + int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1; + +#ifndef WITH_VIEWPORT_CACHE_TEST + /* TODO for testing only, we need proper cache invalidation */ + GPU_viewport_passes_free(viewport); +#endif + + if (viewport->fbl->default_fb) { + if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) { + GPU_viewport_buffers_free(viewport); + } + } + + if (!viewport->fbl->default_fb) { + bool ok = true; + viewport->size[0] = rect_w; + viewport->size[1] = rect_h; + + viewport->fbl->default_fb = GPU_framebuffer_create(); + if (!viewport->fbl->default_fb) { + ok = false; + goto cleanup; + } + + /* Color */ + /* No multi samples for now */ + viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL); + if (!viewport->txl->color) { + ok = false; + goto cleanup; + } + + if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) { + ok = false; + goto cleanup; + } + + /* Depth */ + viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL); + if (!viewport->txl->depth) { + ok = false; + goto cleanup; + } + else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) { + ok = false; + goto cleanup; + } + else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) { + ok = false; + goto cleanup; + } + +cleanup: + if (!ok) { + GPU_viewport_free(viewport); + MEM_freeN(viewport); + return; + } + + GPU_framebuffer_restore(); + } + + GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0); +} + +static void draw_ofs_to_screen(GPUViewport *viewport) +{ + GPUTexture *color = viewport->txl->color; + + const float w = (float)GPU_texture_width(color); + const float h = (float)GPU_texture_height(color); + + VertexFormat *format = immVertexFormat(); + unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT); + unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + + GPU_texture_bind(color, 0); + + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + + immBegin(GL_QUADS, 4); + + immAttrib2f(texcoord, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, 0.0f); + + immAttrib2f(texcoord, 1.0f, 0.0f); + immVertex2f(pos, w, 0.0f); + + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + + immAttrib2f(texcoord, 0.0f, 1.0f); + immVertex2f(pos, 0.0f, h); + + immEnd(); + + GPU_texture_unbind(color); + + immUnbindProgram(); +} + +void GPU_viewport_unbind(GPUViewport *viewport) +{ + if (viewport->fbl->default_fb) { + GPU_framebuffer_texture_unbind(NULL, NULL); + GPU_framebuffer_restore(); + + glEnable(GL_SCISSOR_TEST); + + /* This might be bandwidth limiting */ + draw_ofs_to_screen(viewport); + } +} + +static void GPU_viewport_buffers_free(GPUViewport *viewport) +{ + FramebufferList *fbl = (FramebufferList *)viewport->fbl; + TextureList *txl = (TextureList *)viewport->txl; + int i; + for (i = MAX_BUFFERS - 1; i > -1; --i) { + GPUFrameBuffer *fb = fbl->framebuffers[i]; + if (fb) { + GPU_framebuffer_free(fb); + fbl->framebuffers[i] = NULL; + } + } + for (i = MAX_TEXTURES - 1; i > -1; --i) { + GPUTexture *tex = txl->textures[i]; + if (tex) { + GPU_texture_free(tex); + txl->textures[i] = NULL; + } + } +} + +static void GPU_viewport_passes_free(GPUViewport *viewport) +{ + PassList *psl = (PassList *)viewport->psl; + int i; + + for (i = MAX_PASSES - 1; i > -1; --i) { + struct DRWPass *pass = psl->passes[i]; + if (pass) { + DRW_pass_free(pass); + MEM_freeN(pass); + psl->passes[i] = NULL; + } + } +} + void GPU_viewport_free(GPUViewport *viewport) { GPU_viewport_debug_depth_free(viewport); - MEM_freeN(viewport); + GPU_viewport_buffers_free(viewport); + GPU_viewport_passes_free(viewport); + + MEM_freeN(viewport->fbl); + MEM_freeN(viewport->txl); + MEM_freeN(viewport->psl); } /****************** debug ********************/ diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl new file mode 100644 index 00000000000..f16fa21b342 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl @@ -0,0 +1,16 @@ + +/* Make to be used with dynamic batching so no Model Matrix needed */ +uniform mat4 ViewProjectionMatrix; + +layout(points) in; +layout(line_strip, max_vertices = 2) out; + +void main() +{ + vec3 vert = gl_in[0].gl_Position.xyz; + gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0); + EmitVertex(); + gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0); + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl new file mode 100644 index 00000000000..60793bf56b6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl @@ -0,0 +1,8 @@ + +/* Does Nothing */ +in vec3 pos; + +void main() +{ + gl_Position = vec4(pos, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl new file mode 100644 index 00000000000..be6b6014a19 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl @@ -0,0 +1,11 @@ + +/* Make to be used with dynamic batching so no Model Matrix needed */ +uniform mat4 ViewProjectionMatrix; + +in vec3 pos; + +void main() +{ + gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0); + gl_PointSize = 2.0; +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl new file mode 100644 index 00000000000..7eb321f2996 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl @@ -0,0 +1,10 @@ + +uniform mat4 ViewProjectionMatrix; + +in vec3 pos; +in mat4 InstanceModelMatrix; + +void main() +{ + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl new file mode 100644 index 00000000000..dbc683ef42b --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl @@ -0,0 +1,24 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screen_vecs[2]; +uniform float size; +uniform float pixel_size; + +in vec2 pos; +in mat4 InstanceModelMatrix; + +#define lamp_pos InstanceModelMatrix[3].xyz + +float mul_project_m4_v3_zfac(in vec3 co) +{ + return (ViewProjectionMatrix[0][3] * co.x) + + (ViewProjectionMatrix[1][3] * co.y) + + (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3]; +} + +void main() +{ + float pix_size = mul_project_m4_v3_zfac(lamp_pos) * pixel_size; + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + gl_Position = ViewProjectionMatrix * vec4(lamp_pos + screen_pos * size * pix_size, 1.0); +} |