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")
# --- 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_vert.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;
float *spec_pixels;
GPUTexture *tex_spec;
/* Fragment program to calculate the view3d of 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;
GPUProgram *smoke_program;
int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
float size[3];
if (!tex) {
@@ -349,24 +281,17 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
// printf("i: %d\n", i);
// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) {
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glGenProgramsARB(1, &prog);
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);
smoke_program = GPU_shader_get_builtin_program(progtype);
if (smoke_program) {
GPU_program_bind(smoke_program);
/* 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) */
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
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
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
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);
glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) {
@@ -466,7 +391,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else
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);
glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) {
@@ -499,10 +424,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
free(spec_data);
free(spec_pixels);
if (GLEW_ARB_fragment_program) {
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glDeleteProgramsARB(1, &prog);
}
if (smoke_program)
GPU_program_unbind(smoke_program);
MEM_freeN(points);

View File

@@ -57,6 +57,9 @@ set(SRC
intern/gpu_compositing.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_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl
@@ -89,6 +92,8 @@ set(SRC
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_sep_gaussian_blur_frag.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;
typedef struct GPUShader GPUShader;
struct GPUProgram;
typedef struct GPUProgram GPUProgram;
/* GPU extensions support */
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_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
* - only for fragment shaders now
* - 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 */
typedef enum GPUBuiltinShader {
GPU_SHADER_VSM_STORE = (1<<0),
GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1),
GPU_SHADER_VSM_STORE = 0,
GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
} GPUBuiltinShader;
typedef enum GPUBuiltinProgram {
GPU_PROGRAM_SMOKE = 0,
GPU_PROGRAM_SMOKE_COLORED = 1,
} GPUBuiltinProgram;
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);
void GPU_shader_free_builtin_shaders(void);

View File

@@ -63,6 +63,8 @@ if env['WITH_BF_DDS']:
# generated data files
import os
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_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),

View File

@@ -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;
}
}

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