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)
This commit is contained in:
Antony Riakiotakis
2015-04-09 20:20:33 +02:00
parent 7ea4163e1e
commit 866532360c
8 changed files with 215 additions and 95 deletions

View File

@@ -758,6 +758,9 @@ if B.targets != ['cudakernels']:
data_to_c_simple("release/datafiles/preview_cycles.blend") data_to_c_simple("release/datafiles/preview_cycles.blend")
# --- glsl --- # --- glsl ---
data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_vert.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")

View File

@@ -135,76 +135,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
unsigned char *spec_data; unsigned char *spec_data;
float *spec_pixels; float *spec_pixels;
GPUTexture *tex_spec; GPUTexture *tex_spec;
GPUProgram *smoke_program;
/* Fragment program to calculate the view3d of smoke */ int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
/* using 4 textures, density, shadow, flame and flame spectrum */
const char *shader_basic =
"!!ARBfp1.0\n"
"PARAM dx = program.local[0];\n"
"PARAM darkness = program.local[1];\n"
"PARAM render = program.local[2];\n"
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
"TEMP temp, shadow, flame, spec, value;\n"
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
"TEX spec, flame.r, texture[3], 1D;\n"
/* calculate shading factor from density */
"MUL value.r, temp.a, darkness.a;\n"
"MUL value.r, value.r, dx.r;\n"
"MUL value.r, value.r, f.r;\n"
"EX2 temp, -value.r;\n"
/* alpha */
"SUB temp.a, 1.0, temp.r;\n"
/* shade colors */
"MUL temp.r, temp.r, shadow.r;\n"
"MUL temp.g, temp.g, shadow.r;\n"
"MUL temp.b, temp.b, shadow.r;\n"
"MUL temp.r, temp.r, darkness.r;\n"
"MUL temp.g, temp.g, darkness.g;\n"
"MUL temp.b, temp.b, darkness.b;\n"
/* for now this just replace smoke shading if rendering fire */
"CMP result.color, render.r, temp, spec;\n"
"END\n";
/* color shader */
const char *shader_color =
"!!ARBfp1.0\n"
"PARAM dx = program.local[0];\n"
"PARAM darkness = program.local[1];\n"
"PARAM render = program.local[2];\n"
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
"TEMP temp, shadow, flame, spec, value;\n"
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
"TEX spec, flame.r, texture[3], 1D;\n"
/* unpremultiply volume texture */
"RCP value.r, temp.a;\n"
"MUL temp.r, temp.r, value.r;\n"
"MUL temp.g, temp.g, value.r;\n"
"MUL temp.b, temp.b, value.r;\n"
/* calculate shading factor from density */
"MUL value.r, temp.a, darkness.a;\n"
"MUL value.r, value.r, dx.r;\n"
"MUL value.r, value.r, f.r;\n"
"EX2 value.r, -value.r;\n"
/* alpha */
"SUB temp.a, 1.0, value.r;\n"
/* shade colors */
"MUL temp.r, temp.r, shadow.r;\n"
"MUL temp.g, temp.g, shadow.r;\n"
"MUL temp.b, temp.b, shadow.r;\n"
"MUL temp.r, temp.r, value.r;\n"
"MUL temp.g, temp.g, value.r;\n"
"MUL temp.b, temp.b, value.r;\n"
/* for now this just replace smoke shading if rendering fire */
"CMP result.color, render.r, temp, spec;\n"
"END\n";
GLuint prog;
float size[3]; float size[3];
if (!tex) { if (!tex) {
@@ -349,24 +281,17 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
// printf("i: %d\n", i); // printf("i: %d\n", i);
// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { smoke_program = GPU_shader_get_builtin_program(progtype);
glEnable(GL_FRAGMENT_PROGRAM_ARB); if (smoke_program) {
glGenProgramsARB(1, &prog); GPU_program_bind(smoke_program);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
/* set shader */
if (sds->active_fields & SM_ACTIVE_COLORS)
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
else
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);
/* cell spacing */ /* cell spacing */
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0);
/* custom parameter for smoke style (higher = thicker) */ /* custom parameter for smoke style (higher = thicker) */
if (sds->active_fields & SM_ACTIVE_COLORS) if (sds->active_fields & SM_ACTIVE_COLORS)
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0); GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0);
else else
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
} }
else else
printf("Your gfx card does not support 3D View smoke drawing.\n"); printf("Your gfx card does not support 3D View smoke drawing.\n");
@@ -446,7 +371,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else else
glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0); GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON); glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) { for (i = 0; i < numpoints; i++) {
@@ -466,7 +391,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0); GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON); glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) { for (i = 0; i < numpoints; i++) {
@@ -499,10 +424,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
free(spec_data); free(spec_data);
free(spec_pixels); free(spec_pixels);
if (GLEW_ARB_fragment_program) { if (smoke_program)
glDisable(GL_FRAGMENT_PROGRAM_ARB); GPU_program_unbind(smoke_program);
glDeleteProgramsARB(1, &prog);
}
MEM_freeN(points); MEM_freeN(points);

View File

@@ -57,6 +57,9 @@ set(SRC
intern/gpu_compositing.c intern/gpu_compositing.c
intern/gpu_debug.c intern/gpu_debug.c
shaders/gpu_program_smoke_frag.glsl
shaders/gpu_program_smoke_color_frag.glsl
shaders/gpu_shader_fx_lib.glsl shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl shaders/gpu_shader_fx_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl shaders/gpu_shader_fx_dof_frag.glsl
@@ -89,6 +92,8 @@ set(SRC
intern/gpu_private.h intern/gpu_private.h
) )
data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC)
data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)

View File

@@ -52,6 +52,9 @@ typedef struct GPUOffScreen GPUOffScreen;
struct GPUShader; struct GPUShader;
typedef struct GPUShader GPUShader; typedef struct GPUShader GPUShader;
struct GPUProgram;
typedef struct GPUProgram GPUProgram;
/* GPU extensions support */ /* GPU extensions support */
void GPU_extensions_disable(void); void GPU_extensions_disable(void);
@@ -181,6 +184,18 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs); int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs); int GPU_offscreen_height(const GPUOffScreen *ofs);
/* Builtin/Non-generated shaders */
typedef enum GPUProgramType {
GPU_PROGRAM_TYPE_FRAGMENT = 0
} GPUProgramType;
GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
void GPU_program_free(GPUProgram *program);
void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
void GPU_program_bind(GPUProgram *);
void GPU_program_unbind(GPUProgram *);
/* GPU Shader /* GPU Shader
* - only for fragment shaders now * - only for fragment shaders now
* - must call texture bind before setting a texture as uniform! */ * - must call texture bind before setting a texture as uniform! */
@@ -205,11 +220,17 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */ /* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader { typedef enum GPUBuiltinShader {
GPU_SHADER_VSM_STORE = (1<<0), GPU_SHADER_VSM_STORE = 0,
GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1), GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
} GPUBuiltinShader; } GPUBuiltinShader;
typedef enum GPUBuiltinProgram {
GPU_PROGRAM_SMOKE = 0,
GPU_PROGRAM_SMOKE_COLORED = 1,
} GPUBuiltinProgram;
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp); GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
void GPU_shader_free_builtin_shaders(void); void GPU_shader_free_builtin_shaders(void);

View File

@@ -63,6 +63,8 @@ if env['WITH_BF_DDS']:
# generated data files # generated data files
import os import os
sources.extend(( sources.extend((
os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),

View File

@@ -77,6 +77,8 @@
*/ */
/* Non-generated shaders */ /* 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_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[]; extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_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 { typedef struct GPUShaders {
GPUShader *vsm_store; GPUShader *vsm_store;
GPUShader *sep_gaussian_blur; GPUShader *sep_gaussian_blur;
GPUProgram *smoke;
GPUProgram *smoke_colored;
/* cache for shader fx. Those can exist in combinations so store them here */ /* cache for shader fx. Those can exist in combinations so store them here */
GPUShader *fx_shaders[MAX_FX_SHADERS * 2]; GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
} GPUShaders; } GPUShaders;
@@ -1430,7 +1434,13 @@ struct GPUShader {
int uniforms; /* required uniforms */ 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 i;
int line = 1; int line = 1;
@@ -1504,6 +1514,70 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
return; 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) 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; GLint status;
@@ -1824,6 +1898,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
return retval; 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 #define MAX_DEFINES 100
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp) GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
@@ -1905,18 +2002,28 @@ void GPU_shader_free_builtin_shaders(void)
int i; int i;
if (GG.shaders.vsm_store) { if (GG.shaders.vsm_store) {
MEM_freeN(GG.shaders.vsm_store); GPU_shader_free(GG.shaders.vsm_store);
GG.shaders.vsm_store = NULL; GG.shaders.vsm_store = NULL;
} }
if (GG.shaders.sep_gaussian_blur) { 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; 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++) { for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
if (GG.shaders.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; GG.shaders.fx_shaders[i] = NULL;
} }
} }

View File

@@ -0,0 +1,32 @@
!!ARBfp1.0
PARAM dx = program.local[0];
PARAM darkness = program.local[1];
PARAM render = program.local[2];
PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};
TEMP temp, shadow, flame, spec, value;
TEX temp, fragment.texcoord[0], texture[0], 3D;
TEX shadow, fragment.texcoord[0], texture[1], 3D;
TEX flame, fragment.texcoord[0], texture[2], 3D;
TEX spec, flame.r, texture[3], 1D;
# unpremultiply volume texture
RCP value.r, temp.a;
MUL temp.r, temp.r, value.r;
MUL temp.g, temp.g, value.r;
MUL temp.b, temp.b, value.r;
# calculate shading factor from density
MUL value.r, temp.a, darkness.a;
MUL value.r, value.r, dx.r;
MUL value.r, value.r, f.r;
EX2 value.r, -value.r;
# alpha
SUB temp.a, 1.0, value.r;
# shade colors
MUL temp.r, temp.r, shadow.r;
MUL temp.g, temp.g, shadow.r;
MUL temp.b, temp.b, shadow.r;
MUL temp.r, temp.r, value.r;
MUL temp.g, temp.g, value.r;
MUL temp.b, temp.b, value.r;
# for now this just replace smoke shading if rendering fire
CMP result.color, render.r, temp, spec;
END

View File

@@ -0,0 +1,27 @@
!!ARBfp1.0
PARAM dx = program.local[0];
PARAM darkness = program.local[1];
PARAM render = program.local[2];
PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};
TEMP temp, shadow, flame, spec, value;
TEX temp, fragment.texcoord[0], texture[0], 3D;
TEX shadow, fragment.texcoord[0], texture[1], 3D;
TEX flame, fragment.texcoord[0], texture[2], 3D;
TEX spec, flame.r, texture[3], 1D;
# calculate shading factor from density
MUL value.r, temp.a, darkness.a;
MUL value.r, value.r, dx.r;
MUL value.r, value.r, f.r;
EX2 temp, -value.r;
# alpha
SUB temp.a, 1.0, temp.r;
# shade colors
MUL temp.r, temp.r, shadow.r;
MUL temp.g, temp.g, shadow.r;
MUL temp.b, temp.b, shadow.r;
MUL temp.r, temp.r, darkness.r;
MUL temp.g, temp.g, darkness.g;
MUL temp.b, temp.b, darkness.b;
# for now this just replace smoke shading if rendering fire
CMP result.color, render.r, temp, spec;
END