diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_shader.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 1062 |
1 files changed, 646 insertions, 416 deletions
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 66945b13aba..97be9c79811 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -25,81 +25,172 @@ * ***** END GPL LICENSE BLOCK ***** */ +/** \file blender/gpu/intern/gpu_shader.c + * \ingroup gpu + */ + #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_math_base.h" #include "BLI_math_vector.h" #include "BLI_path_util.h" +#include "BLI_string.h" #include "BKE_appdir.h" #include "BKE_global.h" -#include "GPU_compositing.h" -#include "GPU_debug.h" +#include "DNA_space_types.h" + #include "GPU_extensions.h" -#include "GPU_glew.h" +#include "GPU_context.h" +#include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_texture.h" -#include "GPU_material.h" +#include "GPU_uniformbuffer.h" -/* TODO(sergey): Find better default values for this constants. */ -#define MAX_DEFINE_LENGTH 1024 -#define MAX_EXT_DEFINE_LENGTH 1024 +#include "gpu_shader_private.h" + +/* Adjust these constants as needed. */ +#define MAX_DEFINE_LENGTH 256 +#define MAX_EXT_DEFINE_LENGTH 256 /* Non-generated shaders */ +extern char datatoc_gpu_shader_depth_only_frag_glsl[]; +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_checker_frag_glsl[]; +extern char datatoc_gpu_shader_diag_stripes_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_flat_color_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl[]; +extern char datatoc_gpu_shader_flat_color_frag_glsl[]; +extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[]; +extern char datatoc_gpu_shader_flat_id_frag_glsl[]; +extern char datatoc_gpu_shader_2D_area_borders_vert_glsl[]; +extern char datatoc_gpu_shader_2D_vert_glsl[]; +extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl[]; +extern char datatoc_gpu_shader_2D_image_vert_glsl[]; +extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[]; +extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[]; +extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[]; +extern char datatoc_gpu_shader_2D_widget_base_frag_glsl[]; +extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[]; +extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[]; +extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[]; +extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[]; + +extern char datatoc_gpu_shader_3D_image_vert_glsl[]; +extern char datatoc_gpu_shader_image_frag_glsl[]; +extern char datatoc_gpu_shader_image_linear_frag_glsl[]; +extern char datatoc_gpu_shader_image_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_desaturate_frag_glsl[]; +extern char datatoc_gpu_shader_image_varying_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_interlace_frag_glsl[]; +extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; +extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[]; +extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[]; +extern char datatoc_gpu_shader_image_multisample_resolve_frag_glsl[]; +extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_gpu_shader_3D_normal_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_normal_flat_color_vert_glsl[]; +extern char datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl[]; +extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[]; +extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[]; + +extern char datatoc_gpu_shader_instance_vert_glsl[]; +extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl[]; +extern char datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_screen_aligned_vert_glsl[]; +extern char datatoc_gpu_shader_instance_camera_vert_glsl[]; +extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[]; +extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[]; +extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_mball_handles_vert_glsl[]; + +extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[]; +extern char datatoc_gpu_shader_3D_groundline_geom_glsl[]; + +extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[]; +extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[]; +extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; +extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[]; + +extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[]; +extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[]; +extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[]; +extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl[]; +extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[]; + +extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[]; +extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[]; +extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[]; +extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[]; +extern char datatoc_gpu_shader_edges_overlay_vert_glsl[]; +extern char datatoc_gpu_shader_edges_overlay_geom_glsl[]; +extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[]; +extern char datatoc_gpu_shader_edges_overlay_frag_glsl[]; +extern char datatoc_gpu_shader_text_vert_glsl[]; +extern char datatoc_gpu_shader_text_geom_glsl[]; +extern char datatoc_gpu_shader_text_frag_glsl[]; +extern char datatoc_gpu_shader_text_simple_vert_glsl[]; +extern char datatoc_gpu_shader_text_simple_geom_glsl[]; +extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[]; +extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[]; + extern char datatoc_gpu_shader_fire_frag_glsl[]; extern char datatoc_gpu_shader_smoke_vert_glsl[]; extern char datatoc_gpu_shader_smoke_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[]; -extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[]; -extern char datatoc_gpu_shader_fx_vert_glsl[]; -extern char datatoc_gpu_shader_fx_ssao_frag_glsl[]; -extern char datatoc_gpu_shader_fx_dof_frag_glsl[]; -extern char datatoc_gpu_shader_fx_dof_vert_glsl[]; -extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[]; -extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[]; -extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[]; -extern char datatoc_gpu_shader_fx_depth_resolve_glsl[]; -extern char datatoc_gpu_shader_fx_lib_glsl[]; - -static struct GPUShadersGlobal { - struct { - GPUShader *vsm_store; - GPUShader *sep_gaussian_blur; - GPUShader *smoke; - GPUShader *smoke_fire; - GPUShader *smoke_coba; - /* cache for shader fx. Those can exist in combinations so store them here */ - GPUShader *fx_shaders[MAX_FX_SHADERS * 2]; - } shaders; -} GG = {{NULL}}; - -/* GPUShader */ - -struct GPUShader { - GLuint program; /* handle for full program (links shader stages below) */ - - GLuint vertex; /* handle for vertex shader */ - GLuint geometry; /* handle for geometry shader */ - GLuint fragment; /* handle for fragment shader */ - - int totattrib; /* total number of attributes */ - int uniforms; /* required uniforms */ - - void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */ -}; + +extern char datatoc_gpu_shader_gpencil_stroke_vert_glsl[]; +extern char datatoc_gpu_shader_gpencil_stroke_frag_glsl[]; +extern char datatoc_gpu_shader_gpencil_stroke_geom_glsl[]; + +extern char datatoc_gpu_shader_gpencil_fill_vert_glsl[]; +extern char datatoc_gpu_shader_gpencil_fill_frag_glsl[]; + +/* cache of built-in shaders (each is created on first use) */ +static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL }; + +#ifndef NDEBUG +static uint g_shaderid = 0; +#endif + +typedef struct { + const char *vert; + const char *frag; + const char *geom; /* geometry stage runs between vert & frag, but is less common, so it goes last */ +} GPUShaderStages; static void shader_print_errors(const char *task, const char *log, const char **code, int totcode) { - int i; int line = 1; fprintf(stderr, "GPUShader: %s error:\n", task); - for (i = 0; i < totcode; i++) { + for (int i = 0; i < totcode; i++) { const char *c, *pos, *end = code[i] + strlen(code[i]); if (G.debug & G_DEBUG) { @@ -122,143 +213,70 @@ static void shader_print_errors(const char *task, const char *log, const char ** static const char *gpu_shader_version(void) { - if (GLEW_VERSION_3_2) { - if (GLEW_ARB_compatibility) { - return "#version 150 compatibility\n"; - /* highest version that is widely supported - * gives us native geometry shaders! - * use compatibility profile so we can continue using builtin shader input/output names - */ - } - else { - return "#version 130\n"; - /* latest version that is compatible with existing shaders */ - } - } - else if (GLEW_VERSION_3_1) { - if (GLEW_ARB_compatibility) { - return "#version 140\n"; - /* also need the ARB_compatibility extension, handled below */ - } - else { - return "#version 130\n"; - /* latest version that is compatible with existing shaders */ - } - } - else if (GLEW_VERSION_3_0) { - return "#version 130\n"; - /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available - * older features are deprecated but still available without compatibility extension or profile - */ - } - else { - return "#version 120\n"; - /* minimum supported */ - } + return "#version 330\n"; } - -static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader) +static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) { /* enable extensions for features that are not part of our base GLSL version * don't use an extension for something already available! */ + if (GLEW_ARB_texture_gather) { + /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather + * is reported to be supported but yield a compile error (see T55802). */ + if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) || GLEW_VERSION_4_0) { + strcat(defines, "#extension GL_ARB_texture_gather: enable\n"); + + /* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the + * shader so double check the preprocessor define (see T56544). */ + if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) { + strcat(defines, "#ifdef GL_ARB_texture_gather\n"); + strcat(defines, "# define GPU_ARB_texture_gather\n"); + strcat(defines, "#endif\n"); + } + else { + strcat(defines, "#define GPU_ARB_texture_gather\n"); + } + } + } if (GLEW_ARB_texture_query_lod) { - /* a #version 400 feature, but we use #version 150 maximum so use extension */ + /* a #version 400 feature, but we use #version 330 maximum so use extension */ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); } - - if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) { - strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n"); - } - - if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) { - strcat(defines, "#extension GL_ARB_compatibility: enable\n"); - } - - if (!GLEW_VERSION_3_1) { - if (GLEW_ARB_draw_instanced) { - strcat(defines, "#extension GL_ARB_draw_instanced: enable\n"); - } - - if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) { - strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n"); - /* TODO: maybe require this? shaders become so much nicer */ - } - } } -static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], - bool use_opensubdiv, - bool use_new_shading) +static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) { /* some useful defines to detect GPU type */ - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) { + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) strcat(defines, "#define GPU_ATI\n"); - if (GLEW_VERSION_3_0) { - /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */ - strcat(defines, "#define CLIP_WORKAROUND\n"); - } - } else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) strcat(defines, "#define GPU_NVIDIA\n"); else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) strcat(defines, "#define GPU_INTEL\n"); - if (GPU_bicubic_bump_support()) - strcat(defines, "#define BUMP_BICUBIC\n"); - - if (GLEW_VERSION_3_0) { - strcat(defines, "#define BIT_OPERATIONS\n"); - } - -#ifdef WITH_OPENSUBDIV - /* TODO(sergey): Check whether we actually compiling shader for - * the OpenSubdiv mesh. - */ - if (use_opensubdiv) { - strcat(defines, "#define USE_OPENSUBDIV\n"); - - /* TODO(sergey): not strictly speaking a define, but this is - * a global typedef which we don't have better place to define - * in yet. - */ - strcat(defines, "struct VertexData {\n" - " vec4 position;\n" - " vec3 normal;\n" - " vec2 uv;" - "};\n"); - } -#else - UNUSED_VARS(use_opensubdiv); -#endif - - if (use_new_shading) { - strcat(defines, "#define USE_NEW_SHADING\n"); - } - return; } -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, + const char *shname) { - return GPU_shader_create_ex(vertexcode, - fragcode, - geocode, - libcode, - defines, - input, - output, - number, - GPU_SHADER_FLAGS_NONE); + return GPU_shader_create_ex( + vertexcode, + fragcode, + geocode, + libcode, + defines, + GPU_SHADER_TFB_NONE, + NULL, + 0, + shname); } #define DEBUG_SHADER_NONE "" @@ -308,26 +326,17 @@ static void gpu_dump_shaders(const char **code, const int num_shaders, const cha printf("Shader file written to disk: %s\n", shader_path); } -GPUShader *GPU_shader_create_ex(const char *vertexcode, - const char *fragcode, - const char *geocode, - const char *libcode, - const char *defines, - int input, - int output, - int number, - const int flags) +GPUShader *GPU_shader_create_ex( + const char *vertexcode, + const char *fragcode, + const char *geocode, + const char *libcode, + const char *defines, + const GPUShaderTFBType tf_type, + const char **tf_names, + const int tf_count, + const char *shname) { -#ifdef WITH_OPENSUBDIV - /* TODO(sergey): used to add #version 150 to the geometry shader. - * Could safely be renamed to "use_geometry_code" since it's very - * likely any of geometry code will want to use GLSL 1.5. - */ - bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0; -#else - UNUSED_VARS(flags); - bool use_opensubdiv = false; -#endif GLint status; GLchar log[5000]; GLsizei length = 0; @@ -335,12 +344,15 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, char standard_defines[MAX_DEFINE_LENGTH] = ""; char standard_extensions[MAX_EXT_DEFINE_LENGTH] = ""; - if (geocode && !GPU_geometry_shader_support()) - return NULL; - shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE); +#ifndef NDEBUG + BLI_snprintf(shader->name, sizeof(shader->name), "%s_%u", shname, g_shaderid++); +#else + UNUSED_VARS(shname); +#endif + if (vertexcode) shader->vertex = glCreateShader(GL_VERTEX_SHADER); if (fragcode) @@ -360,10 +372,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, return NULL; } - gpu_shader_standard_defines(standard_defines, - use_opensubdiv, - (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0); - gpu_shader_standard_extensions(standard_extensions, geocode != NULL); + gpu_shader_standard_defines(standard_defines); + gpu_shader_standard_extensions(standard_extensions); if (vertexcode) { const char *source[5]; @@ -402,18 +412,6 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, source[num_source++] = standard_extensions; source[num_source++] = standard_defines; -#ifdef WITH_OPENSUBDIV - /* TODO(sergey): Move to fragment shader source code generation. */ - if (use_opensubdiv) { - source[num_source++] = - "#ifdef USE_OPENSUBDIV\n" - "in block {\n" - " VertexData v;\n" - "} inpt;\n" - "#endif\n"; - } -#endif - if (defines) source[num_source++] = defines; if (libcode) source[num_source++] = libcode; source[num_source++] = fragcode; @@ -461,22 +459,14 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, GPU_shader_free(shader); return NULL; } - - if (!use_opensubdiv) { - GPU_shader_geometry_stage_primitive_io(shader, input, output, number); - } } -#ifdef WITH_OPENSUBDIV - if (use_opensubdiv) { - glBindAttribLocation(shader->program, 0, "position"); - glBindAttribLocation(shader->program, 1, "normal"); - GPU_shader_geometry_stage_primitive_io(shader, - GL_LINES_ADJACENCY_EXT, - GL_TRIANGLE_STRIP, - 4); + if (tf_names != NULL) { + glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS); + /* Primitive type must be setup */ + BLI_assert(tf_type != GPU_SHADER_TFB_NONE); + shader->feedback_transform_type = tf_type; } -#endif glLinkProgram(shader->program); glGetProgramiv(shader->program, GL_LINK_STATUS, &status); @@ -492,18 +482,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, return NULL; } -#ifdef WITH_OPENSUBDIV - /* TODO(sergey): Find a better place for this. */ - if (use_opensubdiv && GLEW_VERSION_4_1) { - glProgramUniform1i(shader->program, - glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"), - 30); /* GL_TEXTURE30 */ - - glProgramUniform1i(shader->program, - glGetUniformLocation(shader->program, "FVarDataBuffer"), - 31); /* GL_TEXTURE31 */ - } -#endif + shader->interface = GPU_shaderinterface_create(shader->program); return shader; } @@ -515,20 +494,46 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, void GPU_shader_bind(GPUShader *shader) { - GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind"); + BLI_assert(shader && shader->program); + glUseProgram(shader->program); - GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind"); + GPU_matrix_bind(shader->interface); } void GPU_shader_unbind(void) { - GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind"); glUseProgram(0); - GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind"); +} + +bool GPU_shader_transform_feedback_enable(GPUShader *shader, uint vbo_id) +{ + if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) { + return false; + } + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id); + + switch (shader->feedback_transform_type) { + case GPU_SHADER_TFB_POINTS: glBeginTransformFeedback(GL_POINTS); return true; + case GPU_SHADER_TFB_LINES: glBeginTransformFeedback(GL_LINES); return true; + case GPU_SHADER_TFB_TRIANGLES: glBeginTransformFeedback(GL_TRIANGLES); return true; + default: return false; + } +} + +void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader)) +{ + glEndTransformFeedback(); } void GPU_shader_free(GPUShader *shader) { +#if 0 /* Would be nice to have, but for now the Deferred compilation + * does not have a GPUContext. */ + BLI_assert(GPU_context_active_get() != NULL); +#endif + BLI_assert(shader); + if (shader->vertex) glDeleteShader(shader->vertex); if (shader->geometry) @@ -538,25 +543,43 @@ void GPU_shader_free(GPUShader *shader) if (shader->program) glDeleteProgram(shader->program); - if (shader->uniform_interface) - MEM_freeN(shader->uniform_interface); + if (shader->interface) + GPU_shaderinterface_discard(shader->interface); MEM_freeN(shader); } int GPU_shader_get_uniform(GPUShader *shader, const char *name) { - return glGetUniformLocation(shader->program, name); + BLI_assert(shader && shader->program); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name); + return uniform ? uniform->location : -1; +} + +int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin) +{ + BLI_assert(shader && shader->program); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin); + return uniform ? uniform->location : -1; +} + +int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) +{ + BLI_assert(shader && shader->program); + + const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); + return ubo ? ubo->location : -1; } void *GPU_shader_get_interface(GPUShader *shader) { - return shader->uniform_interface; + return shader->interface; } -void GPU_shader_set_interface(GPUShader *shader, void *interface) +/* Clement : Temp */ +int GPU_shader_get_program(GPUShader *shader) { - shader->uniform_interface = interface; + return (int)shader->program; } void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value) @@ -564,16 +587,12 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng if (location == -1 || value == NULL) return; - GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector"); - if (length == 1) glUniform1fv(location, arraysize, value); else if (length == 2) glUniform2fv(location, arraysize, value); else if (length == 3) glUniform3fv(location, arraysize, value); else if (length == 4) glUniform4fv(location, arraysize, value); else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value); else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value); - - GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector"); } void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value) @@ -581,14 +600,10 @@ void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int if (location == -1) return; - GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector"); - if (length == 1) glUniform1iv(location, arraysize, value); else if (length == 2) glUniform2iv(location, arraysize, value); else if (length == 3) glUniform3iv(location, arraysize, value); else if (length == 4) glUniform4iv(location, arraysize, value); - - GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector"); } void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) @@ -596,223 +611,438 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) if (location == -1) return; - GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value)); + glUniform1i(location, value); } -void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number) +void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo) { - if (GPU_geometry_shader_support_via_extension()) { - /* geometry shaders must provide this info themselves for #version 150 and up */ - glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input); - glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output); - glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number); + 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) { - GLenum arbnumber; int number = GPU_texture_bound_number(tex); - int bindcode = GPU_texture_opengl_bindcode(tex); - int target = GPU_texture_target(tex); - if (number >= GPU_max_textures()) { - fprintf(stderr, "Not enough texture slots.\n"); + if (number == -1) { + fprintf(stderr, "Texture is not bound.\n"); + BLI_assert(0); return; } - if (number == -1) - return; - if (location == -1) return; - GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture"); - - arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number); - - if (number != 0) glActiveTexture(arbnumber); - if (bindcode != 0) - glBindTexture(target, bindcode); - else - GPU_invalid_tex_bind(target); glUniform1i(location, number); - glEnable(target); - if (number != 0) glActiveTexture(GL_TEXTURE0); - - GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture"); } int GPU_shader_get_attribute(GPUShader *shader, const char *name) { - int index; - - GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name)); - - return index; + BLI_assert(shader && shader->program); + const GPUShaderInput *attrib = GPU_shaderinterface_attr(shader->interface, name); + return attrib ? attrib->location : -1; } -GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) -{ - GPUShader *retval = NULL; +static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = { + [GPU_SHADER_SMOKE] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + [GPU_SHADER_SMOKE_FIRE] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + [GPU_SHADER_SMOKE_COBA] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + + [GPU_SHADER_TEXT] = + { datatoc_gpu_shader_text_vert_glsl, + datatoc_gpu_shader_text_frag_glsl, + datatoc_gpu_shader_text_geom_glsl }, + [GPU_SHADER_TEXT_SIMPLE] = + { datatoc_gpu_shader_text_simple_vert_glsl, + datatoc_gpu_shader_text_frag_glsl, + datatoc_gpu_shader_text_simple_geom_glsl }, + [GPU_SHADER_KEYFRAME_DIAMOND] = + { datatoc_gpu_shader_keyframe_diamond_vert_glsl, + datatoc_gpu_shader_keyframe_diamond_frag_glsl }, + [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = + { datatoc_gpu_shader_edges_front_back_persp_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, /* this version is */ + datatoc_gpu_shader_edges_front_back_persp_geom_glsl }, /* magical but slooow */ + [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = + { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_edges_overlay_frag_glsl, + datatoc_gpu_shader_edges_overlay_simple_geom_glsl }, + [GPU_SHADER_EDGES_OVERLAY] = + { datatoc_gpu_shader_edges_overlay_vert_glsl, + datatoc_gpu_shader_edges_overlay_frag_glsl, + datatoc_gpu_shader_edges_overlay_geom_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING] = + { datatoc_gpu_shader_3D_normal_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl }, + /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ + [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl }, + + [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_mask_uniform_color_frag_glsl }, + [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_modulate_alpha_frag_glsl }, + [GPU_SHADER_3D_IMAGE_DEPTH] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_depth_linear_frag_glsl }, + [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_depth_copy_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + + [GPU_SHADER_2D_IMAGE_INTERLACE] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_interlace_frag_glsl }, + [GPU_SHADER_2D_CHECKER] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_checker_frag_glsl }, + + [GPU_SHADER_2D_DIAG_STRIPES] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_diag_stripes_frag_glsl }, + + [GPU_SHADER_2D_UNIFORM_COLOR] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_2D_FLAT_COLOR] = + { datatoc_gpu_shader_2D_flat_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_2D_SMOOTH_COLOR] = + { datatoc_gpu_shader_2D_smooth_color_vert_glsl, + datatoc_gpu_shader_2D_smooth_color_frag_glsl }, + [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = + { datatoc_gpu_shader_2D_smooth_color_vert_glsl, + datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl }, + [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_linear_frag_glsl }, + [GPU_SHADER_2D_IMAGE] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_frag_glsl }, + [GPU_SHADER_2D_IMAGE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_desaturate_frag_glsl }, + [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_alpha_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_shuffle_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_RECT_COLOR] = + { datatoc_gpu_shader_2D_image_rect_vert_glsl, + datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = + { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, + datatoc_gpu_shader_image_varying_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_U32] = + { datatoc_gpu_shader_3D_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_FLAT_COLOR_U32] = + { 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_CLIPPED_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, + datatoc_gpu_shader_uniform_color_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_passthrough_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + datatoc_gpu_shader_3D_groundline_geom_glsl }, + + [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = + { datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl, + datatoc_gpu_shader_2D_line_dashed_geom_glsl }, + [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl, + datatoc_gpu_shader_2D_line_dashed_geom_glsl }, + + [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl}, + [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = + { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = + { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + + [GPU_SHADER_CAMERA] = + { datatoc_gpu_shader_instance_camera_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_DISTANCE_LINES] = + { datatoc_gpu_shader_instance_distance_line_vert_glsl, + datatoc_gpu_shader_flat_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] = + { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, + datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = + { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_point_varying_size_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = + { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, + + [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = + { datatoc_gpu_shader_instance_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] = + { datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl, + datatoc_gpu_shader_flat_id_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = + { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] = + { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_gpu_shader_instance_edges_variying_color_geom_glsl}, + + [GPU_SHADER_2D_AREA_EDGES] = + { datatoc_gpu_shader_2D_area_borders_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl}, + [GPU_SHADER_2D_WIDGET_BASE] = + { datatoc_gpu_shader_2D_widget_base_vert_glsl, + datatoc_gpu_shader_2D_widget_base_frag_glsl}, + [GPU_SHADER_2D_WIDGET_BASE_INST] = + { datatoc_gpu_shader_2D_widget_base_vert_glsl, + datatoc_gpu_shader_2D_widget_base_frag_glsl}, + [GPU_SHADER_2D_WIDGET_SHADOW] = + { datatoc_gpu_shader_2D_widget_shadow_vert_glsl, + datatoc_gpu_shader_2D_widget_shadow_frag_glsl }, + [GPU_SHADER_2D_NODELINK] = + { datatoc_gpu_shader_2D_nodelink_vert_glsl, + datatoc_gpu_shader_2D_nodelink_frag_glsl }, + [GPU_SHADER_2D_NODELINK_INST] = + { datatoc_gpu_shader_2D_nodelink_vert_glsl, + datatoc_gpu_shader_2D_nodelink_frag_glsl }, + + [GPU_SHADER_GPENCIL_STROKE] = + { datatoc_gpu_shader_gpencil_stroke_vert_glsl, + datatoc_gpu_shader_gpencil_stroke_frag_glsl, + datatoc_gpu_shader_gpencil_stroke_geom_glsl }, + + [GPU_SHADER_GPENCIL_FILL] = + { datatoc_gpu_shader_gpencil_fill_vert_glsl, + datatoc_gpu_shader_gpencil_fill_frag_glsl }, +}; +/* just a few special cases */ +static const char *gpu_shader_get_builtin_shader_defines( + GPUBuiltinShader shader) +{ switch (shader) { - case GPU_SHADER_VSM_STORE: - if (!GG.shaders.vsm_store) - GG.shaders.vsm_store = GPU_shader_create( - datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.vsm_store; - break; - case GPU_SHADER_SEP_GAUSSIAN_BLUR: - if (!GG.shaders.sep_gaussian_blur) - GG.shaders.sep_gaussian_blur = GPU_shader_create( - datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, - datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.sep_gaussian_blur; - break; - case GPU_SHADER_SMOKE: - if (!GG.shaders.smoke) - GG.shaders.smoke = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.smoke; - break; - case GPU_SHADER_SMOKE_FIRE: - if (!GG.shaders.smoke_fire) - GG.shaders.smoke_fire = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.smoke_fire; - break; - case GPU_SHADER_SMOKE_COBA: - if (!GG.shaders.smoke_coba) - GG.shaders.smoke_coba = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl, - NULL, NULL, "#define USE_COBA;\n", 0, 0, 0); - retval = GG.shaders.smoke_coba; - break; - } + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2: + return "#define SAMPLES 2\n"; - if (retval == NULL) - printf("Unable to create a GPUShader for builtin shader: %u\n", shader); + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST: + return "#define SAMPLES 2\n" + "#define USE_DEPTH\n"; - return retval; -} + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4: + return "#define SAMPLES 4\n"; -#define MAX_DEFINES 100 + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST: + return "#define SAMPLES 4\n" + "#define USE_DEPTH\n"; -GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp) -{ - int offset; - char defines[MAX_DEFINES] = ""; - /* avoid shaders out of range */ - if (effect >= MAX_FX_SHADERS) - return NULL; + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8: + return "#define SAMPLES 8\n"; - offset = 2 * effect; + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST: + return "#define SAMPLES 8\n" + "#define USE_DEPTH\n"; - if (persp) { - offset += 1; - strcat(defines, "#define PERSP_MATRIX\n"); - } + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16: + return "#define SAMPLES 16\n"; - if (!GG.shaders.fx_shaders[offset]) { - GPUShader *shader = NULL; - - switch (effect) { - case GPU_SHADER_FX_SSAO: - shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE: - strcat(defines, "#define FIRST_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO: - strcat(defines, "#define SECOND_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE: - strcat(defines, "#define THIRD_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR: - strcat(defines, "#define FOURTH_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE: - strcat(defines, "#define FIFTH_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE: - strcat(defines, "#define FIRST_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO: - strcat(defines, "#define SECOND_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, - defines, GL_POINTS, GL_TRIANGLE_STRIP, 4); - break; - - case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE: - strcat(defines, "#define THIRD_PASS\n"); - shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); - break; - - case GPU_SHADER_FX_DEPTH_RESOLVE: - shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0); - break; - } + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST: + return "#define SAMPLES 16\n" + "#define USE_DEPTH\n"; - GG.shaders.fx_shaders[offset] = shader; - GPU_fx_shader_init_interface(shader, effect); - } + case GPU_SHADER_2D_WIDGET_BASE_INST: + case GPU_SHADER_2D_NODELINK_INST: + return "#define USE_INSTANCE\n"; - return GG.shaders.fx_shaders[offset]; -} + case GPU_SHADER_SMOKE_COBA: + return "#define USE_COBA\n"; + case GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE: + case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE: + return "#define UNIFORM_SCALE\n"; -void GPU_shader_free_builtin_shaders(void) -{ - int i; + case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS: + return "#define AXIS_NAME\n"; - if (GG.shaders.vsm_store) { - GPU_shader_free(GG.shaders.vsm_store); - GG.shaders.vsm_store = NULL; - } + case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR: + return "#define USE_INSTANCE_COLOR\n"; - if (GG.shaders.sep_gaussian_blur) { - GPU_shader_free(GG.shaders.sep_gaussian_blur); - GG.shaders.sep_gaussian_blur = NULL; - } + case GPU_SHADER_3D_FLAT_COLOR_U32: + case GPU_SHADER_3D_UNIFORM_COLOR_U32: + return "#define USE_COLOR_U32\n"; - if (GG.shaders.smoke) { - GPU_shader_free(GG.shaders.smoke); - GG.shaders.smoke = NULL; - } + case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR: + return "#define USE_FLAT_NORMAL\n"; - if (GG.shaders.smoke_fire) { - GPU_shader_free(GG.shaders.smoke_fire); - GG.shaders.smoke_fire = NULL; + default: + return NULL; } +} + +GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) +{ + BLI_assert(shader != GPU_NUM_BUILTIN_SHADERS); /* don't be a troll */ + + if (builtin_shaders[shader] == NULL) { + const char *defines = gpu_shader_get_builtin_shader_defines(shader); - if (GG.shaders.smoke_coba) { - GPU_shader_free(GG.shaders.smoke_coba); - GG.shaders.smoke_coba = NULL; + const GPUShaderStages *stages = builtin_shader_stages + shader; + + if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) { + /* TODO: remove after switch to core profile (maybe) */ + static const GPUShaderStages legacy_fancy_edges = { + datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl, + datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl, + }; + stages = &legacy_fancy_edges; + } + + if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR && !GLEW_VERSION_3_2) { + /* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */ + /* TODO: remove after switch to core profile (maybe) */ + static const GPUShaderStages legacy_dashed_lines = { + datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl, + }; + stages = &legacy_dashed_lines; + } + + /* common case */ + builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines, __func__); } - for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) { - if (GG.shaders.fx_shaders[i]) { - GPU_shader_free(GG.shaders.fx_shaders[i]); - GG.shaders.fx_shaders[i] = NULL; + return builtin_shaders[shader]; +} + +void GPU_shader_get_builtin_shader_code( + GPUBuiltinShader shader, + const char **r_vert, const char **r_frag, + const char **r_geom, const char **r_defines) +{ + const GPUShaderStages *stages = builtin_shader_stages + shader; + *r_vert = stages->vert; + *r_frag = stages->frag; + *r_geom = stages->geom; + *r_defines = gpu_shader_get_builtin_shader_defines(shader); +} + +#define MAX_DEFINES 100 + +void GPU_shader_free_builtin_shaders(void) +{ + for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) { + if (builtin_shaders[i]) { + GPU_shader_free(builtin_shaders[i]); + builtin_shaders[i] = NULL; } } } |