From 8fb2ff458ba579dba08bfdf57d043ad158b5db07 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 17 Jan 2022 14:32:03 +0100 Subject: GPUShaderCreateInfo for interface abstraction This is a first part of the Shader Create Info system could be. A shader create info provides a way to define shader structure, resources and interfaces. This makes for a quick way to provide backend agnostic binding informations while also making shader variations easy to declare. - Clear source input (only one file). Cleans up the GPU api since we can create a shader from one descriptor - Resources and interfaces are generated by the backend (much simpler than parsing). - Bindings are explicit from position in the array. - GPUShaderInterface becomes a trivial translation of enums and string copy. - No external dependency to third party lib. - Cleaner code, less fragmentation of resources in several libs. - Easy to modify / extend at runtime. - no parser involve, very easy to code. - Does not hold any data, can be static and kept on disc. - Could hold precompiled bytecode for static shaders. This also includes a new global dependency system. GLSL shaders can include other sources by using #pragma BLENDER_REQUIRE(...). This patch already migrated several builtin shaders. Other shaders should be migrated one at a time, and could be done inside master. There is a new compile directive `WITH_GPU_SHADER_BUILDER` this is an optional directive for linting shaders to increase turn around time. What is remaining: - pyGPU API {T94975} - Migration of other shaders. This could be a community effort. Reviewed By: jbakker Maniphest Tasks: T94975 Differential Revision: https://developer.blender.org/D13360 --- .../workbench/shaders/workbench_common_lib.glsl | 13 +- .../workbench/shaders/workbench_data_lib.glsl | 5 +- .../shaders/workbench_effect_cavity_frag.glsl | 4 + .../shaders/workbench_effect_cavity_info.hh | 28 +++++ .../workbench/shaders/workbench_image_lib.glsl | 2 + .../workbench/shaders/workbench_prepass_frag.glsl | 4 +- .../shaders/workbench_prepass_hair_vert.glsl | 6 +- .../workbench/shaders/workbench_prepass_info.hh | 136 +++++++++++++++++++++ .../shaders/workbench_prepass_pointcloud_vert.glsl | 4 +- .../workbench/shaders/workbench_prepass_vert.glsl | 6 +- .../shaders/workbench_shader_interface_lib.glsl | 8 +- .../shaders/workbench_transparent_accum_frag.glsl | 2 + .../engines/workbench/workbench_shader_shared.h | 48 ++++++++ 13 files changed, 246 insertions(+), 20 deletions(-) create mode 100644 source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_info.hh create mode 100644 source/blender/draw/engines/workbench/shaders/workbench_prepass_info.hh create mode 100644 source/blender/draw/engines/workbench/workbench_shader_shared.h (limited to 'source/blender/draw/engines') diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 8cbc8608f5b..9b142fe56b5 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -3,10 +3,6 @@ #define CAVITY_BUFFER_RANGE 4.0 -#ifdef WORKBENCH_ENCODE_NORMALS - -# define WB_Normal vec2 - /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ vec3 workbench_normal_decode(vec4 enc) @@ -22,7 +18,7 @@ vec3 workbench_normal_decode(vec4 enc) /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ -WB_Normal workbench_normal_encode(bool front_face, vec3 n) +vec2 workbench_normal_encode(bool front_face, vec3 n) { n = normalize(front_face ? n : -n); float p = sqrt(n.z * 8.0 + 8.0); @@ -30,13 +26,6 @@ WB_Normal workbench_normal_encode(bool front_face, vec3 n) return n.xy; } -#else -# define WB_Normal vec3 -/* Well just do nothing... */ -# define workbench_normal_encode(f, a) (a) -# define workbench_normal_decode(a) (a.xyz) -#endif /* WORKBENCH_ENCODE_NORMALS */ - /* Encoding into the alpha of a RGBA16F texture. (10bit mantissa) */ #define TARGET_BITCOUNT 8u #define METALLIC_BITS 3u /* Metallic channel is less important. */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl index 2e229d4d83a..c784c8b2db9 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -1,3 +1,5 @@ + +#ifndef WORKBENCH_SHADER_SHARED_H struct LightData { vec4 direction; vec4 specular_color; @@ -37,9 +39,10 @@ struct WorldData { int _pad2; }; -#define viewport_size_inv viewport_size.zw +# define viewport_size_inv viewport_size.zw layout(std140) uniform world_block { WorldData world_data; }; +#endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl index 328d50e69e0..0b571040df5 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl @@ -4,6 +4,8 @@ #pragma BLENDER_REQUIRE(workbench_cavity_lib.glsl) #pragma BLENDER_REQUIRE(workbench_curvature_lib.glsl) +#ifndef DRW_SHADER_SHARED_H + uniform sampler2D depthBuffer; uniform sampler2D normalBuffer; uniform usampler2D objectIdBuffer; @@ -12,6 +14,8 @@ in vec4 uvcoordsvar; out vec4 fragColor; +#endif + void main() { float cavity = 0.0, edges = 0.0, curvature = 0.0; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_info.hh b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_info.hh new file mode 100644 index 00000000000..31e5f5e7641 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_info.hh @@ -0,0 +1,28 @@ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(workbench_effect_cavity_common) + .fragment_out(0, Type::VEC4, "fragColor") + .sampler(0, ImageType::FLOAT_2D, "depthBuffer") + .sampler(1, ImageType::FLOAT_2D, "normalBuffer") + .sampler(2, ImageType::UINT_2D, "objectIdBuffer") + .uniform_buf(3, "vec4", "samples_coords[512]") + .fragment_source("workbench_effect_cavity_frag.glsl") + .additional_info("draw_fullscreen") + .additional_info("draw_view"); + +GPU_SHADER_CREATE_INFO(workbench_effect_cavity) + .do_static_compilation(true) + .define("USE_CAVITY") + .additional_info("workbench_effect_cavity_common"); + +GPU_SHADER_CREATE_INFO(workbench_effect_curvature) + .do_static_compilation(true) + .define("USE_CURVATURE") + .additional_info("workbench_effect_cavity_common"); + +GPU_SHADER_CREATE_INFO(workbench_effect_cavity_curvature) + .do_static_compilation(true) + .define("USE_CAVITY") + .define("USE_CURVATURE") + .additional_info("workbench_effect_cavity_common"); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl index 57d648d3565..49e3f57ab2e 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl @@ -25,12 +25,14 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) return true; } +#ifndef WORKBENCH_SHADER_SHARED_H uniform sampler2DArray imageTileArray; uniform sampler1DArray imageTileData; uniform sampler2D imageTexture; uniform float imageTransparencyCutoff = 0.1; uniform bool imagePremult; +#endif vec3 workbench_image_color(vec2 uvs) { diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 6d24b001d4d..7a3ebc4035e 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -4,9 +4,11 @@ #pragma BLENDER_REQUIRE(workbench_common_lib.glsl) #pragma BLENDER_REQUIRE(workbench_image_lib.glsl) +#ifndef WORKBENCH_SHADER_SHARED_H layout(location = 0) out vec4 materialData; -layout(location = 1) out WB_Normal normalData; +layout(location = 1) out vec2 normalData; layout(location = 2) out uint objectId; +#endif uniform bool useMatcap = false; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl index 3e1ea14f47c..c3faa3957ef 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl @@ -5,8 +5,10 @@ #pragma BLENDER_REQUIRE(workbench_material_lib.glsl) #pragma BLENDER_REQUIRE(workbench_image_lib.glsl) +#ifndef WORKBENCH_SHADER_SHARED_H uniform samplerBuffer ac; /* active color layer */ uniform samplerBuffer au; /* active texture layer */ +#endif /* From http://libnoise.sourceforge.net/noisegen/index.html */ float integer_noise(int n) @@ -71,8 +73,10 @@ void main() normal_interp = normalize(normal_world_to_view(nor)); -#ifdef OPAQUE_MATERIAL +#ifndef WORKBENCH_SHADER_SHARED_H +# ifdef OPAQUE_MATERIAL float metallic, roughness; +# endif #endif workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_info.hh b/source/blender/draw/engines/workbench/shaders/workbench_prepass_info.hh new file mode 100644 index 00000000000..1dd706c9460 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_info.hh @@ -0,0 +1,136 @@ + +#include "gpu_shader_create_info.hh" + +/* -------------------------------------------------------------------- */ +/** \name Object Type + * \{ */ + +GPU_SHADER_CREATE_INFO(workbench_mesh) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::VEC3, "nor") + .vertex_in(2, Type::VEC4, "ac") + .vertex_in(3, Type::VEC2, "au") + .vertex_source("workbench_prepass_vert.glsl") + .additional_info("draw_mesh"); + +GPU_SHADER_CREATE_INFO(workbench_hair) + .sampler(0, ImageType::FLOAT_BUFFER, "ac", Frequency::BATCH) + .sampler(1, ImageType::FLOAT_BUFFER, "au", Frequency::BATCH) + .vertex_source("workbench_prepass_hair_vert.glsl") + .additional_info("draw_hair"); + +GPU_SHADER_CREATE_INFO(workbench_pointcloud) + .vertex_source("workbench_prepass_pointcloud_vert.glsl") + .additional_info("draw_pointcloud"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Texture Type + * \{ */ + +GPU_SHADER_CREATE_INFO(workbench_texture_none).define("TEXTURE_NONE"); + +GPU_SHADER_CREATE_INFO(workbench_texture_single) + .sampler(2, ImageType::FLOAT_2D, "imageTexture", Frequency::BATCH) + .push_constant(1, Type::BOOL, "imagePremult") + .push_constant(2, Type::FLOAT, "imageTransparencyCutoff") + .define("V3D_SHADING_TEXTURE_COLOR"); + +GPU_SHADER_CREATE_INFO(workbench_texture_tile) + .sampler(2, ImageType::FLOAT_2D_ARRAY, "imageTileArray", Frequency::BATCH) + .sampler(3, ImageType::FLOAT_1D_ARRAY, "imageTileData", Frequency::BATCH) + .push_constant(1, Type::BOOL, "imagePremult") + .push_constant(2, Type::FLOAT, "imageTransparencyCutoff") + .define("TEXTURE_IMAGE_ARRAY"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lighting Type + * \{ */ + +GPU_SHADER_CREATE_INFO(workbench_lighting_studio).define("V3D_LIGHTING_STUDIO"); +GPU_SHADER_CREATE_INFO(workbench_lighting_matcap).define("V3D_LIGHTING_MATCAP"); +GPU_SHADER_CREATE_INFO(workbench_lighting_flat).define("V3D_LIGHTING_FLAT"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Material Interface + * \{ */ + +GPU_SHADER_INTERFACE_INFO(workbench_material_iface, "") + .smooth(Type::VEC3, "normal_interp") + .smooth(Type::VEC3, "color_interp") + .smooth(Type::FLOAT, "alpha_interp") + .smooth(Type::VEC2, "uv_interp") + .flat(Type::INT, "object_id") + .flat(Type::FLOAT, "roughness") + .flat(Type::FLOAT, "metallic"); + +GPU_SHADER_CREATE_INFO(workbench_material).vertex_out(workbench_material_iface); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pipeline Type + * \{ */ + +GPU_SHADER_CREATE_INFO(workbench_transparent_accum) + /* Note: Blending will be skipped on objectId because output is a + non-normalized integer buffer. */ + .fragment_out(0, Type::VEC4, "transparentAccum") + .fragment_out(1, Type::VEC4, "revealageAccum") + .fragment_out(2, Type::UINT, "objectId") + .uniform_buf(4, "WorldData", "world_data", Frequency::PASS) + .typedef_source("workbench_shader_shared.h") + .fragment_source("workbench_transparent_accum_frag.glsl") + .additional_info("workbench_material"); + +GPU_SHADER_CREATE_INFO(workbench_opaque) + .fragment_out(0, Type::VEC4, "materialData") + .fragment_out(1, Type::VEC2, "normalData") + .fragment_out(2, Type::UINT, "objectId") + .uniform_buf(4, "WorldData", "world_data", Frequency::PASS) + .typedef_source("workbench_shader_shared.h") + .fragment_source("workbench_prepass_frag.glsl") + .additional_info("workbench_material"); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Variations Declaration + * \{ */ + +#define WORKBENCH_SURFACETYPE_VARIATIONS(prefix, ...) \ + GPU_SHADER_CREATE_INFO(prefix##_mesh) \ + .additional_info("workbench_mesh", __VA_ARGS__) \ + .do_static_compilation(true); \ + GPU_SHADER_CREATE_INFO(prefix##_hair) \ + .additional_info("workbench_hair", __VA_ARGS__) \ + .do_static_compilation(true); \ + GPU_SHADER_CREATE_INFO(prefix##_ptcloud) \ + .additional_info("workbench_pointcloud", __VA_ARGS__) \ + .do_static_compilation(true); + +#define WORKBENCH_PIPELINE_VARIATIONS(prefix, ...) \ + WORKBENCH_SURFACETYPE_VARIATIONS(prefix##_transp_studio, \ + "workbench_transparent_accum", \ + "workbench_lighting_studio", \ + __VA_ARGS__) \ + WORKBENCH_SURFACETYPE_VARIATIONS(prefix##_transp_matcap, \ + "workbench_transparent_accum", \ + "workbench_lighting_matcap", \ + __VA_ARGS__) \ + WORKBENCH_SURFACETYPE_VARIATIONS(prefix##_transp_flat, \ + "workbench_transparent_accum", \ + "workbench_lighting_flat", \ + __VA_ARGS__) \ + WORKBENCH_SURFACETYPE_VARIATIONS(prefix##_opaque, "workbench_opaque", __VA_ARGS__) + +WORKBENCH_PIPELINE_VARIATIONS(workbench_tex_none, "workbench_texture_none") +WORKBENCH_PIPELINE_VARIATIONS(workbench_tex_single, "workbench_texture_single") +WORKBENCH_PIPELINE_VARIATIONS(workbench_tex_tile, "workbench_texture_tile") + +/** \} */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl index 6f61874b8f5..8efe10b8236 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl @@ -21,8 +21,10 @@ void main() uv_interp = vec2(0.0); -#ifdef OPAQUE_MATERIAL +#ifndef WORKBENCH_SHADER_SHARED_H +# ifdef OPAQUE_MATERIAL float metallic, roughness; +# endif #endif workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 1192081caf1..1f6a8a63944 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -5,10 +5,12 @@ #pragma BLENDER_REQUIRE(workbench_material_lib.glsl) #pragma BLENDER_REQUIRE(workbench_image_lib.glsl) +#ifndef WORKBENCH_SHADER_SHARED_H in vec3 pos; in vec3 nor; in vec4 ac; /* active color */ in vec2 au; /* active texture layer */ +#endif void main() { @@ -23,8 +25,10 @@ void main() normal_interp = normalize(normal_object_to_view(nor)); -#ifdef OPAQUE_MATERIAL +#ifndef WORKBENCH_SHADER_SHARED_H +# ifdef OPAQUE_MATERIAL float metallic, roughness; +# endif #endif workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl index 6bfa351aeb0..178e61c8a8d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl @@ -1,15 +1,17 @@ +#ifndef WORKBENCH_SHADER_SHARED_H IN_OUT ShaderStageInterface { vec3 normal_interp; vec3 color_interp; float alpha_interp; vec2 uv_interp; -#ifdef TRANSPARENT_MATERIAL +# ifdef TRANSPARENT_MATERIAL flat float roughness; flat float metallic; -#else +# else flat float packed_rough_metal; -#endif +# endif flat int object_id; }; +#endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl index 3f113fd4b2e..0062cbe17a2 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl @@ -6,6 +6,7 @@ #pragma BLENDER_REQUIRE(workbench_matcap_lib.glsl) #pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl) +#ifndef WORKBENCH_SHADER_SHARED_H /* Revealage is actually stored in transparentAccum alpha channel. * This is a workaround to older hardware not having separate blend equation per render target. */ layout(location = 0) out vec4 transparentAccum; @@ -13,6 +14,7 @@ layout(location = 1) out vec4 revealageAccum; /* NOTE: Blending will be skipped on objectId because output is a non-normalized integer buffer. */ layout(location = 2) out uint objectId; +#endif /* Special function only to be used with calculate_transparent_weight(). */ float linear_zdepth(float depth, vec4 viewvecs[2], mat4 proj_mat) diff --git a/source/blender/draw/engines/workbench/workbench_shader_shared.h b/source/blender/draw/engines/workbench/workbench_shader_shared.h new file mode 100644 index 00000000000..42d38e54d9a --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_shader_shared.h @@ -0,0 +1,48 @@ + +#ifndef GPU_SHADER +# include "gpu_shader_shared_utils.h" +#endif + +#define WORKBENCH_SHADER_SHARED_H + +struct LightData { + float4 direction; + float4 specular_color; + float4 diffuse_color_wrap; /* rgb: diffuse col a: wrapped lighting factor */ +}; + +struct WorldData { + float4 viewport_size; + float4 object_outline_color; + float4 shadow_direction_vs; + float shadow_focus; + float shadow_shift; + float shadow_mul; + float shadow_add; + /* - 16 bytes alignment - */ + LightData lights[4]; + float4 ambient_color; + + int cavity_sample_start; + int cavity_sample_end; + float cavity_sample_count_inv; + float cavity_jitter_scale; + + float cavity_valley_factor; + float cavity_ridge_factor; + float cavity_attenuation; + float cavity_distance; + + float curvature_ridge; + float curvature_valley; + float ui_scale; + float _pad0; + + int matcap_orientation; + bool use_specular; + int _pad1; + int _pad2; +}; + +#define viewport_size_inv viewport_size.zw +#define packed_rough_metal roughness -- cgit v1.2.3