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:
authorClément Foucault <foucault.clem@gmail.com>2022-01-26 14:46:37 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-01-26 14:46:37 +0300
commit5b299e5999e2b59e30edd4e770f64aa700e482d6 (patch)
tree17052358b339e20c44ca942e62b735ef63b23f88 /source/blender/draw/engines/workbench/workbench_shader.cc
parent9bce134e56c28045aee37080f5c5b6622a07927b (diff)
D13910: Workbench: Port shaders to use GPUShaderCreateInfo
Also adds a few things to GPUShader for easily create shaders. Heavy usage of macros to compose the createInfo and avoid duplications and copy paste bugs. This makes the link between the shader request functions (in workbench_shader.cc) and the actual createInfo a bit obscure since the names are composed and not searchable. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D13910
Diffstat (limited to 'source/blender/draw/engines/workbench/workbench_shader.cc')
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.cc444
1 files changed, 444 insertions, 0 deletions
diff --git a/source/blender/draw/engines/workbench/workbench_shader.cc b/source/blender/draw/engines/workbench/workbench_shader.cc
new file mode 100644
index 00000000000..b38286303f1
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_shader.cc
@@ -0,0 +1,444 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include <string>
+
+#include "workbench_engine.h"
+#include "workbench_private.h"
+
+extern char datatoc_common_math_lib_glsl[];
+extern char datatoc_common_math_geom_lib_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_pointcloud_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_common_smaa_lib_glsl[];
+
+extern char datatoc_workbench_prepass_vert_glsl[];
+extern char datatoc_workbench_prepass_hair_vert_glsl[];
+extern char datatoc_workbench_prepass_pointcloud_vert_glsl[];
+extern char datatoc_workbench_prepass_frag_glsl[];
+
+extern char datatoc_workbench_effect_cavity_frag_glsl[];
+extern char datatoc_workbench_effect_outline_frag_glsl[];
+extern char datatoc_workbench_effect_dof_frag_glsl[];
+extern char datatoc_workbench_effect_taa_frag_glsl[];
+extern char datatoc_workbench_effect_smaa_frag_glsl[];
+extern char datatoc_workbench_effect_smaa_vert_glsl[];
+
+extern char datatoc_workbench_composite_frag_glsl[];
+
+extern char datatoc_workbench_transparent_accum_frag_glsl[];
+extern char datatoc_workbench_transparent_resolve_frag_glsl[];
+
+extern char datatoc_workbench_merge_infront_frag_glsl[];
+
+extern char datatoc_workbench_shadow_vert_glsl[];
+extern char datatoc_workbench_shadow_geom_glsl[];
+extern char datatoc_workbench_shadow_caps_geom_glsl[];
+extern char datatoc_workbench_shadow_debug_frag_glsl[];
+
+extern char datatoc_workbench_volume_vert_glsl[];
+extern char datatoc_workbench_volume_frag_glsl[];
+
+extern char datatoc_workbench_cavity_lib_glsl[];
+extern char datatoc_workbench_common_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
+extern char datatoc_workbench_data_lib_glsl[];
+extern char datatoc_workbench_image_lib_glsl[];
+extern char datatoc_workbench_matcap_lib_glsl[];
+extern char datatoc_workbench_material_lib_glsl[];
+extern char datatoc_workbench_world_light_lib_glsl[];
+
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
+extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
+
+/* Maximum number of variations. */
+#define MAX_LIGHTING 3
+
+enum eWORKBENCH_TextureType {
+ TEXTURE_SH_NONE = 0,
+ TEXTURE_SH_SINGLE,
+ TEXTURE_SH_TILED,
+ TEXTURE_SH_MAX,
+};
+
+static struct {
+ struct GPUShader
+ *opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX][TEXTURE_SH_MAX];
+ struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX]
+ [MAX_LIGHTING][TEXTURE_SH_MAX];
+
+ struct GPUShader *opaque_composite_sh[MAX_LIGHTING];
+ struct GPUShader *oit_resolve_sh;
+ struct GPUShader *outline_sh;
+ struct GPUShader *merge_infront_sh;
+
+ struct GPUShader *shadow_depth_pass_sh[2];
+ struct GPUShader *shadow_depth_fail_sh[2][2];
+
+ struct GPUShader *cavity_sh[2][2];
+
+ struct GPUShader *dof_prepare_sh;
+ struct GPUShader *dof_downsample_sh;
+ struct GPUShader *dof_blur1_sh;
+ struct GPUShader *dof_blur2_sh;
+ struct GPUShader *dof_resolve_sh;
+
+ struct GPUShader *aa_accum_sh;
+ struct GPUShader *smaa_sh[3];
+
+ struct GPUShader *volume_sh[2][2][3][2];
+
+} e_data = {{{{NULL}}}};
+
+/* -------------------------------------------------------------------- */
+/** \name Conversions
+ * \{ */
+
+static const char *workbench_lighting_mode_to_str(int light)
+{
+ switch (light) {
+ default:
+ BLI_assert_msg(0, "Error: Unknown lighting mode.");
+ ATTR_FALLTHROUGH;
+ case V3D_LIGHTING_STUDIO:
+ return "_studio";
+ case V3D_LIGHTING_MATCAP:
+ return "_matcap";
+ case V3D_LIGHTING_FLAT:
+ return "_flat";
+ return "";
+ }
+}
+
+static const char *workbench_datatype_mode_to_str(eWORKBENCH_DataType datatype)
+{
+ switch (datatype) {
+ default:
+ BLI_assert_msg(0, "Error: Unknown data mode.");
+ ATTR_FALLTHROUGH;
+ case WORKBENCH_DATATYPE_MESH:
+ return "_mesh";
+ case WORKBENCH_DATATYPE_HAIR:
+ return "_hair";
+ case WORKBENCH_DATATYPE_POINTCLOUD:
+ return "_ptcloud";
+ }
+}
+
+static const char *workbench_volume_interp_to_str(eWORKBENCH_VolumeInterpType interp_type)
+{
+ switch (interp_type) {
+ default:
+ BLI_assert_msg(0, "Error: Unknown lighting mode.");
+ ATTR_FALLTHROUGH;
+ case WORKBENCH_VOLUME_INTERP_LINEAR:
+ return "_linear";
+ case WORKBENCH_VOLUME_INTERP_CUBIC:
+ return "_cubic";
+ case WORKBENCH_VOLUME_INTERP_CLOSEST:
+ return "_closest";
+ }
+}
+
+static const char *workbench_texture_type_to_str(eWORKBENCH_TextureType tex_type)
+{
+ switch (tex_type) {
+ default:
+ BLI_assert_msg(0, "Error: Unknown texture mode.");
+ ATTR_FALLTHROUGH;
+ case TEXTURE_SH_NONE:
+ return "_tex_none";
+ case TEXTURE_SH_TILED:
+ return "_tex_tile";
+ case TEXTURE_SH_SINGLE:
+ return "_tex_single";
+ }
+}
+
+static eWORKBENCH_TextureType workbench_texture_type_get(bool textured, bool tiled)
+{
+ return textured ? (tiled ? TEXTURE_SH_TILED : TEXTURE_SH_SINGLE) : TEXTURE_SH_NONE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Shader request
+ * \{ */
+
+static GPUShader *workbench_shader_get_ex(WORKBENCH_PrivateData *wpd,
+ bool transp,
+ eWORKBENCH_DataType datatype,
+ bool textured,
+ bool tiled)
+{
+ eWORKBENCH_TextureType tex_type = workbench_texture_type_get(textured, tiled);
+ int light = wpd->shading.light;
+ BLI_assert(light < MAX_LIGHTING);
+ struct GPUShader **shader =
+ (transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][datatype][light][tex_type] :
+ &e_data.opaque_prepass_sh_cache[wpd->sh_cfg][datatype][tex_type];
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench";
+ create_info_name += (transp) ? "_transp" : "_opaque";
+ if (transp) {
+ create_info_name += workbench_lighting_mode_to_str(light);
+ }
+ create_info_name += workbench_datatype_mode_to_str(datatype);
+ create_info_name += workbench_texture_type_to_str(tex_type);
+ create_info_name += (wpd->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "_clip" : "_no_clip";
+
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return *shader;
+}
+
+GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType datatype)
+{
+ return workbench_shader_get_ex(wpd, false, datatype, false, false);
+}
+
+GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd,
+ eWORKBENCH_DataType datatype,
+ bool tiled)
+{
+ return workbench_shader_get_ex(wpd, false, datatype, true, tiled);
+}
+
+GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd,
+ eWORKBENCH_DataType datatype)
+{
+ return workbench_shader_get_ex(wpd, true, datatype, false, false);
+}
+
+GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd,
+ eWORKBENCH_DataType datatype,
+ bool tiled)
+{
+ return workbench_shader_get_ex(wpd, true, datatype, true, tiled);
+}
+
+GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd)
+{
+ int light = wpd->shading.light;
+ struct GPUShader **shader = &e_data.opaque_composite_sh[light];
+ BLI_assert(light < MAX_LIGHTING);
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench_composite";
+ create_info_name += workbench_lighting_mode_to_str(light);
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return *shader;
+}
+
+GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData *UNUSED(wpd))
+{
+ if (e_data.merge_infront_sh == nullptr) {
+ e_data.merge_infront_sh = GPU_shader_create_from_info_name("workbench_merge_infront");
+ }
+ return e_data.merge_infront_sh;
+}
+
+GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *UNUSED(wpd))
+{
+ if (e_data.oit_resolve_sh == nullptr) {
+ e_data.oit_resolve_sh = GPU_shader_create_from_info_name("workbench_transparent_resolve");
+ }
+ return e_data.oit_resolve_sh;
+}
+
+static GPUShader *workbench_shader_shadow_pass_get_ex(bool depth_pass, bool manifold, bool cap)
+{
+ struct GPUShader **shader = (depth_pass) ? &e_data.shadow_depth_pass_sh[manifold] :
+ &e_data.shadow_depth_fail_sh[manifold][cap];
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench_shadow";
+ create_info_name += (depth_pass) ? "_pass" : "_fail";
+ create_info_name += (manifold) ? "_manifold" : "_no_manifold";
+ create_info_name += (cap) ? "_caps" : "_no_caps";
+#if DEBUG_SHADOW_VOLUME
+ create_info_name += "_debug";
+#endif
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return *shader;
+}
+
+GPUShader *workbench_shader_shadow_pass_get(bool manifold)
+{
+ return workbench_shader_shadow_pass_get_ex(true, manifold, false);
+}
+
+GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap)
+{
+ return workbench_shader_shadow_pass_get_ex(false, manifold, cap);
+}
+
+GPUShader *workbench_shader_cavity_get(bool cavity, bool curvature)
+{
+ BLI_assert(cavity || curvature);
+ struct GPUShader **shader = &e_data.cavity_sh[cavity][curvature];
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench_effect";
+ create_info_name += (cavity) ? "_cavity" : "";
+ create_info_name += (curvature) ? "_curvature" : "";
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return *shader;
+}
+
+GPUShader *workbench_shader_outline_get(void)
+{
+ if (e_data.outline_sh == nullptr) {
+ e_data.outline_sh = GPU_shader_create_from_info_name("workbench_effect_outline");
+ }
+ return e_data.outline_sh;
+}
+
+void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
+ GPUShader **downsample_sh,
+ GPUShader **blur1_sh,
+ GPUShader **blur2_sh,
+ GPUShader **resolve_sh)
+{
+ if (e_data.dof_prepare_sh == nullptr) {
+ e_data.dof_prepare_sh = GPU_shader_create_from_info_name("workbench_effect_dof_prepare");
+ e_data.dof_downsample_sh = GPU_shader_create_from_info_name("workbench_effect_dof_downsample");
+#if 0 /* TODO(fclem): finish COC min_max optimization */
+ e_data.dof_flatten_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_v");
+ e_data.dof_flatten_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_h");
+ e_data.dof_dilate_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_v");
+ e_data.dof_dilate_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_h");
+#endif
+ e_data.dof_blur1_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur1");
+ e_data.dof_blur2_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur2");
+ e_data.dof_resolve_sh = GPU_shader_create_from_info_name("workbench_effect_dof_resolve");
+ }
+
+ *prepare_sh = e_data.dof_prepare_sh;
+ *downsample_sh = e_data.dof_downsample_sh;
+ *blur1_sh = e_data.dof_blur1_sh;
+ *blur2_sh = e_data.dof_blur2_sh;
+ *resolve_sh = e_data.dof_resolve_sh;
+}
+
+GPUShader *workbench_shader_antialiasing_accumulation_get(void)
+{
+ if (e_data.aa_accum_sh == nullptr) {
+ e_data.aa_accum_sh = GPU_shader_create_from_info_name("workbench_taa");
+ }
+ return e_data.aa_accum_sh;
+}
+
+GPUShader *workbench_shader_antialiasing_get(int stage)
+{
+ BLI_assert(stage < 3);
+ GPUShader **shader = &e_data.smaa_sh[stage];
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench_smaa_stage_";
+ create_info_name += std::to_string(stage);
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return e_data.smaa_sh[stage];
+}
+
+GPUShader *workbench_shader_volume_get(bool slice,
+ bool coba,
+ eWORKBENCH_VolumeInterpType interp_type,
+ bool smoke)
+{
+ GPUShader **shader = &e_data.volume_sh[slice][coba][interp_type][smoke];
+
+ if (*shader == nullptr) {
+ std::string create_info_name = "workbench_volume";
+ create_info_name += (smoke) ? "_smoke" : "_object";
+ create_info_name += workbench_volume_interp_to_str(interp_type);
+ create_info_name += (coba) ? "_coba" : "_no_coba";
+ create_info_name += (slice) ? "_slice" : "_no_slice";
+ *shader = GPU_shader_create_from_info_name(create_info_name.c_str());
+ }
+ return *shader;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cleanup
+ * \{ */
+
+void workbench_shader_free(void)
+{
+ for (int j = 0; j < sizeof(e_data.opaque_prepass_sh_cache) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.opaque_prepass_sh_cache[0][0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < sizeof(e_data.transp_prepass_sh_cache) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.transp_prepass_sh_cache[0][0][0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < ARRAY_SIZE(e_data.opaque_composite_sh); j++) {
+ struct GPUShader **sh_array = &e_data.opaque_composite_sh[0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < ARRAY_SIZE(e_data.shadow_depth_pass_sh); j++) {
+ struct GPUShader **sh_array = &e_data.shadow_depth_pass_sh[0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < sizeof(e_data.shadow_depth_fail_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.shadow_depth_fail_sh[0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < sizeof(e_data.cavity_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.cavity_sh[0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < ARRAY_SIZE(e_data.smaa_sh); j++) {
+ struct GPUShader **sh_array = &e_data.smaa_sh[0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < sizeof(e_data.volume_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.volume_sh[0][0][0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+
+ DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh);
+ DRW_SHADER_FREE_SAFE(e_data.outline_sh);
+ DRW_SHADER_FREE_SAFE(e_data.merge_infront_sh);
+
+ DRW_SHADER_FREE_SAFE(e_data.dof_prepare_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_blur1_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_blur2_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh);
+
+ DRW_SHADER_FREE_SAFE(e_data.aa_accum_sh);
+}
+
+/** \} */