diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-04-09 21:20:33 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-04-09 21:20:50 +0300 |
commit | 866532360c75298c88dc51724e878255295b98df (patch) | |
tree | 31974b583480531ab8c2bcd8baff75d1ea329ac0 /source/blender/gpu/intern | |
parent | 7ea4163e1e5a33d38573371c8b19969b051d5ea2 (diff) |
Fix T31546 fragment program gets created every frame
That was really crappy indeed. Now we have a separate API
for low level OpenGL programs, plus a nice interface for GPU, also
removes some GL calls from main code as a plus :)
The source for the programs is also moved to nice external .glsl files
(not sure which extension convention GPU assemply uses)
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 115 |
1 files changed, 111 insertions, 4 deletions
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 363e19908e5..e8595ecc67c 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -77,6 +77,8 @@ */ /* Non-generated shaders */ +extern char datatoc_gpu_program_smoke_frag_glsl[]; +extern char datatoc_gpu_program_smoke_color_frag_glsl[]; extern char datatoc_gpu_shader_vsm_store_vert_glsl[]; extern char datatoc_gpu_shader_vsm_store_frag_glsl[]; extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[]; @@ -94,6 +96,8 @@ extern char datatoc_gpu_shader_fx_lib_glsl[]; typedef struct GPUShaders { GPUShader *vsm_store; GPUShader *sep_gaussian_blur; + GPUProgram *smoke; + GPUProgram *smoke_colored; /* cache for shader fx. Those can exist in combinations so store them here */ GPUShader *fx_shaders[MAX_FX_SHADERS * 2]; } GPUShaders; @@ -1430,7 +1434,13 @@ struct GPUShader { int uniforms; /* required uniforms */ }; -static void shader_print_errors(const char *task, char *log, const char **code, int totcode) +struct GPUProgram { + GPUProgramType type; + GLuint prog; +}; + + +static void shader_print_errors(const char *task, const char *log, const char **code, int totcode) { int i; int line = 1; @@ -1504,6 +1514,70 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) return; } +void GPU_program_bind(GPUProgram *program) +{ + glEnable(program->type); + glBindProgramARB(program->type, program->prog); +} + +void GPU_program_unbind(GPUProgram *program) +{ + glDisable(program->type); + glBindProgramARB(program->type, 0); +} + + +GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code) +{ + GPUProgram *program; + GLint error_pos, is_native; + + if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT)) + return NULL; + + program = MEM_callocN(sizeof(GPUProgram), "GPUProgram"); + + switch (type) { + case GPU_PROGRAM_TYPE_FRAGMENT: + program->type = GL_FRAGMENT_PROGRAM_ARB; + break; + } + + /* create the object and set its code string */ + glGenProgramsARB(1, &program->prog); + glBindProgramARB(program->type, program->prog); + + glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code); + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native); + if ((error_pos == -1) && (is_native == 1)) { + return program; + } + else { + /* glGetError is set before that, clear it */ + while (glGetError() != GL_NO_ERROR) + ; + shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1); + MEM_freeN(program); + } + + return NULL; +} + +void GPU_program_free(GPUProgram *program) +{ + glDeleteProgramsARB(1, &program->prog); + MEM_freeN(program); +} + +void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w) +{ + glProgramLocalParameter4fARB(program->type, location, x, y, z, w); +} + + + GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number) { GLint status; @@ -1824,6 +1898,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) return retval; } +GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program) +{ + GPUProgram *retval = NULL; + + switch (program) { + case GPU_PROGRAM_SMOKE: + if (!GG.shaders.smoke) + GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl); + retval = GG.shaders.smoke; + break; + case GPU_PROGRAM_SMOKE_COLORED: + if (!GG.shaders.smoke_colored) + GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl); + retval = GG.shaders.smoke_colored; + break; + } + + if (retval == NULL) + printf("Unable to create a GPUProgram for builtin program: %d\n", program); + + return retval; +} + #define MAX_DEFINES 100 GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) @@ -1905,18 +2002,28 @@ void GPU_shader_free_builtin_shaders(void) int i; if (GG.shaders.vsm_store) { - MEM_freeN(GG.shaders.vsm_store); + GPU_shader_free(GG.shaders.vsm_store); GG.shaders.vsm_store = NULL; } if (GG.shaders.sep_gaussian_blur) { - MEM_freeN(GG.shaders.sep_gaussian_blur); + GPU_shader_free(GG.shaders.sep_gaussian_blur); GG.shaders.sep_gaussian_blur = NULL; } + if (GG.shaders.smoke) { + GPU_program_free(GG.shaders.smoke); + GG.shaders.smoke = NULL; + } + + if (GG.shaders.smoke_colored) { + GPU_program_free(GG.shaders.smoke_colored); + GG.shaders.smoke_colored = NULL; + } + for (i = 0; i < 2 * MAX_FX_SHADERS; i++) { if (GG.shaders.fx_shaders[i]) { - MEM_freeN(GG.shaders.fx_shaders[i]); + GPU_shader_free(GG.shaders.fx_shaders[i]); GG.shaders.fx_shaders[i] = NULL; } } |