diff options
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 15 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 38 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 40 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_uniformbuffer.c | 105 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 196 |
6 files changed, 391 insertions, 4 deletions
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 ********************/ |