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
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')
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_shader.h21
-rw-r--r--source/blender/gpu/intern/gpu_shader.c133
-rw-r--r--source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl25
4 files changed, 166 insertions, 15 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index b65b2e6844b..b76edf4068a 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -242,6 +242,8 @@ data_to_c_simple(shaders/gpu_shader_gpencil_stroke_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_gpencil_fill_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_gpencil_fill_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC)
+
if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index d2380d27464..428c7634195 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -60,6 +60,12 @@ GPUShader *GPU_shader_create_ex(
const char **tf_names,
const int tf_count,
const char *shader_name);
+struct GPU_ShaderCreateFromArray_Params { const char **vert, **geom, **frag, **defs; };
+struct GPUShader *GPU_shader_create_from_arrays_impl(
+ const struct GPU_ShaderCreateFromArray_Params *params);
+#define GPU_shader_create_from_arrays(...) \
+ GPU_shader_create_from_arrays_impl(&(const struct GPU_ShaderCreateFromArray_Params)__VA_ARGS__)
+
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
@@ -350,9 +356,15 @@ typedef enum eGPUBuiltinShader {
/* Selection */
GPU_SHADER_3D_FLAT_SELECT_ID,
GPU_SHADER_3D_UNIFORM_SELECT_ID,
-
- GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} eGPUBuiltinShader;
+#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_UNIFORM_SELECT_ID + 1)
+
+/** Support multiple configurations. */
+typedef enum eGPUShaderConfig {
+ GPU_SHADER_CFG_DEFAULT = 0,
+ GPU_SHADER_CFG_CLIPPED = 1,
+} eGPUShaderConfig;
+#define GPU_SHADER_CFG_LEN (GPU_SHADER_CFG_CLIPPED + 1)
/** Keep these in sync with:
* - `gpu_shader_image_interlace_frag.glsl`
@@ -364,7 +376,10 @@ typedef enum eGPUInterlaceShader {
GPU_SHADER_INTERLACE_CHECKER = 2,
} eGPUInterlaceShader;
-GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader);
+GPUShader *GPU_shader_get_builtin_shader_with_config(
+ eGPUBuiltinShader shader, eGPUShaderConfig shader_cfg);
+GPUShader *GPU_shader_get_builtin_shader(
+ eGPUBuiltinShader shader);
void GPU_shader_get_builtin_shader_code(
eGPUBuiltinShader shader,
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;
+ }
}
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
new file mode 100644
index 00000000000..6964b2a0c39
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
@@ -0,0 +1,25 @@
+#ifdef USE_WORLD_CLIP_PLANES
+#if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER)
+uniform vec4 WorldClipPlanes[6];
+void world_clip_planes_calc_clip_distance(vec3 wpos)
+{
+ gl_ClipDistance[0] = dot(WorldClipPlanes[0].xyz, wpos) + WorldClipPlanes[0].w;
+ gl_ClipDistance[1] = dot(WorldClipPlanes[1].xyz, wpos) + WorldClipPlanes[1].w;
+ gl_ClipDistance[2] = dot(WorldClipPlanes[2].xyz, wpos) + WorldClipPlanes[2].w;
+ gl_ClipDistance[3] = dot(WorldClipPlanes[3].xyz, wpos) + WorldClipPlanes[3].w;
+ gl_ClipDistance[4] = dot(WorldClipPlanes[4].xyz, wpos) + WorldClipPlanes[4].w;
+ gl_ClipDistance[5] = dot(WorldClipPlanes[5].xyz, wpos) + WorldClipPlanes[5].w;
+}
+#endif
+
+#define world_clip_planes_set_clip_distance(c) \
+{ \
+ gl_ClipDistance[0] = (c)[0]; \
+ gl_ClipDistance[1] = (c)[1]; \
+ gl_ClipDistance[2] = (c)[2]; \
+ gl_ClipDistance[3] = (c)[3]; \
+ gl_ClipDistance[4] = (c)[4]; \
+ gl_ClipDistance[5] = (c)[5]; \
+}
+
+#endif