Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-02-06 01:15:16 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-02-06 01:15:16 +0300
commitdbd7f36da8ec3ac1c2898aee346beecb86aac8a2 (patch)
tree0d77061a4305b7bcfef13bb753089e5f6f21e7c3 /source/blender/gpu/intern/gpu_shader.c
parenta245d533514e335f028cfa6cdb26614ed0982484 (diff)
GPU: refactor clipped drawing from DRW into GPU
Needed to fix T61196, supporting clipped back-buffer in the 3D view which is done outside the draw module. It was also inconvenient having DRW_shader_* versions of GPU_shader_* API calls. - Clipping distances are now supported as a shader configuration for builtin shaders. - Add shader config argument when accessing builtin shaders. - Move GPU_shader_create_from_arrays() from DRW to GPU.
Diffstat (limited to 'source/blender/gpu/intern/gpu_shader.c')
-rw-r--r--source/blender/gpu/intern/gpu_shader.c133
1 files changed, 121 insertions, 12 deletions
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 7c699382d3b..99f4df29418 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -28,6 +28,7 @@
#include "BLI_math_vector.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BKE_appdir.h"
#include "BKE_global.h"
@@ -169,9 +170,10 @@ 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[];
+extern char datatoc_gpu_shader_cfg_world_clip_lib_glsl[];
/* cache of built-in shaders (each is created on first use) */
-static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
+static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {NULL};
#ifndef NDEBUG
static uint g_shaderid = 0;
@@ -500,6 +502,73 @@ GPUShader *GPU_shader_create_ex(
#undef DEBUG_SHADER_VERTEX
#undef DEBUG_SHADER_NONE
+static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_is_alloc)
+{
+ bool is_alloc = false;
+ if (str_arr == NULL) {
+ *r_is_alloc = false;
+ return NULL;
+ }
+ /* Skip empty strings (avoid alloc if we can). */
+ while (str_arr[0] && str_arr[0][0] == '\0') {
+ str_arr++;
+ }
+ int i;
+ for (i = 0; str_arr[i]; i++) {
+ if (i != 0 && str_arr[i][0] != '\0') {
+ is_alloc = true;
+ }
+ }
+ *r_is_alloc = is_alloc;
+ if (is_alloc) {
+ return BLI_string_join_arrayN(str_arr, i);
+ }
+ else {
+ return str_arr[0];
+ }
+}
+
+/**
+ * Use via #GPU_shader_create_from_arrays macro (avoids passing in param).
+ *
+ * Similar to #DRW_shader_create_with_lib with the ability to include libs for each type of shader.
+ *
+ * It has the advantage that each item can be conditionally included
+ * without having to build the string inline, then free it.
+ *
+ * \param params: NULL terminated arrays of strings.
+ *
+ * Example:
+ * \code{.c}
+ * sh = GPU_shader_create_from_arrays({
+ * .vert = (const char *[]){shader_lib_glsl, shader_vert_glsl, NULL},
+ * .geom = (const char *[]){shader_geom_glsl, NULL},
+ * .frag = (const char *[]){shader_frag_glsl, NULL},
+ * .defs = (const char *[]){"#define DEFINE\n", test ? "#define OTHER_DEFINE\n" : "", NULL},
+ * });
+ * \endcode
+ */
+struct GPUShader *GPU_shader_create_from_arrays_impl(
+ const struct GPU_ShaderCreateFromArray_Params *params)
+{
+ struct { const char *str; bool is_alloc;} str_dst[4] = {0};
+ const char **str_src[4] = {params->vert, params->frag, params->geom, params->defs};
+
+ for (int i = 0; i < ARRAY_SIZE(str_src); i++) {
+ str_dst[i].str = string_join_array_maybe_alloc(str_src[i], &str_dst[i].is_alloc);
+ }
+
+ GPUShader *sh = GPU_shader_create(
+ str_dst[0].str, str_dst[1].str, str_dst[2].str, NULL, str_dst[3].str, __func__);
+
+ for (int i = 0; i < ARRAY_SIZE(str_dst); i++) {
+ if (str_dst[i].is_alloc) {
+ MEM_freeN((void *)str_dst[i].str);
+ }
+ }
+ return sh;
+}
+
void GPU_shader_bind(GPUShader *shader)
{
BLI_assert(shader && shader->program);
@@ -670,7 +739,7 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name)
return attr ? attr->location : -1;
}
-static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
+static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
[GPU_SHADER_TEXT] = {
.vert = datatoc_gpu_shader_text_vert_glsl,
.geom = datatoc_gpu_shader_text_geom_glsl,
@@ -1101,11 +1170,14 @@ static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
},
};
-GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
+GPUShader *GPU_shader_get_builtin_shader_with_config(
+ eGPUBuiltinShader shader, eGPUShaderConfig shader_cfg)
{
- BLI_assert(shader < GPU_NUM_BUILTIN_SHADERS);
+ BLI_assert(shader < GPU_SHADER_BUILTIN_LEN);
+ BLI_assert(shader_cfg < GPU_SHADER_CFG_LEN);
+ GPUShader **sh_p = &builtin_shaders[shader_cfg][shader];
- if (builtin_shaders[shader] == NULL) {
+ if (*sh_p == NULL) {
GPUShaderStages stages_legacy = {NULL};
const GPUShaderStages *stages = &builtin_shader_stages[shader];
@@ -1128,11 +1200,46 @@ GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
}
/* common case */
- builtin_shaders[shader] = GPU_shader_create(
- stages->vert, stages->frag, stages->geom, NULL, stages->defs, __func__);
+ if (shader_cfg == GPU_SHADER_CFG_DEFAULT) {
+ *sh_p = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, stages->defs, __func__);
+ }
+ else if (shader_cfg == GPU_SHADER_CFG_CLIPPED) {
+ /* Remove eventually, for now ensure support for each shader has been added. */
+ BLI_assert(ELEM(shader,
+ GPU_SHADER_3D_UNIFORM_COLOR,
+ GPU_SHADER_3D_SMOOTH_COLOR,
+ GPU_SHADER_3D_DEPTH_ONLY,
+ GPU_SHADER_CAMERA,
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE,
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR,
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED,
+ GPU_SHADER_3D_GROUNDLINE,
+ GPU_SHADER_3D_GROUNDPOINT,
+ GPU_SHADER_DISTANCE_LINES,
+ GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR));
+ const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl;
+ const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n";
+ /* In rare cases geometry shaders calculate clipping themselves. */
+ *sh_p = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){world_clip_lib, stages->vert, NULL},
+ .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL},
+ .frag = (const char *[]){stages->frag, NULL},
+ .defs = (const char *[]){world_clip_def, stages->defs, NULL},
+ });
+ }
+ else {
+ BLI_assert(0);
+ }
}
- return builtin_shaders[shader];
+ return *sh_p;
+}
+GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
+{
+ return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT);
}
void GPU_shader_get_builtin_shader_code(
@@ -1149,10 +1256,12 @@ void GPU_shader_get_builtin_shader_code(
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;
+ for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
+ for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) {
+ if (builtin_shaders[i][j]) {
+ GPU_shader_free(builtin_shaders[i][j]);
+ builtin_shaders[i][j] = NULL;
+ }
}
}
}