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
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-08-23 15:36:22 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-08-26 20:18:34 +0300
commit7f840426fd4917f56e7bafcffffd51b93c1fc6f7 (patch)
treeef90d2c4836e1f521bfc847c92d4b692369a2295 /source
parent6b189d2bcf3536231f7040926ed34fe01012f14e (diff)
GPU: add mechanism for splitting up big gpu_shader_material.glsl file
Compiling this big file for every Eevee material is bad for performance, and now that we are adding more nodes it gets worse. This patch adds a simple mechanism to split up that file, and use only the parts used by shader nodes. When a function is used by GPU_link, we detect which GLSL file it came from and use it in GLSL code generation automatically. Dependencies between GLSL files are manually specified, and function names must be unique across all GLSL files. Most of the actual splitting up will be done in later commits. Differential Revision: https://developer.blender.org/D5569
Diffstat (limited to 'source')
-rw-r--r--source/blender/gpu/CMakeLists.txt4
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c81
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h3
-rw-r--r--source/blender/gpu/intern/gpu_material.c13
-rw-r--r--source/blender/gpu/intern/gpu_material_library.h49
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl291
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material_hash.glsl206
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material_magic.glsl61
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl21
9 files changed, 410 insertions, 319 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index fb7d3c1ace8..4a67f5f6af8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SRC
intern/gpu_batch_private.h
intern/gpu_codegen.h
intern/gpu_context_private.h
+ intern/gpu_material_library.h
intern/gpu_matrix_private.h
intern/gpu_primitive_private.h
intern/gpu_private.h
@@ -232,6 +233,9 @@ data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_hash.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_magic.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_material_white_noise.glsl SRC)
data_to_c_simple(shaders/gpu_shader_gpencil_stroke_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_gpencil_stroke_frag.glsl SRC)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 55337596cbe..cbf6665b3bb 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -51,15 +51,11 @@
#include "BLI_sys_types.h" /* for intptr_t support */
#include "gpu_codegen.h"
+#include "gpu_material_library.h"
#include <string.h>
#include <stdarg.h>
-extern char datatoc_gpu_shader_material_glsl[];
-extern char datatoc_gpu_shader_geometry_glsl[];
-
-static char *glsl_material_library = NULL;
-
/* -------------------- GPUPass Cache ------------------ */
/**
* Internal shader cache: This prevent the shader recompilation / stall when
@@ -147,6 +143,7 @@ typedef struct GPUFunction {
eGPUType paramtype[MAX_PARAMETER];
GPUFunctionQual paramqual[MAX_PARAMETER];
int totparam;
+ GPUMaterialLibrary *library;
} GPUFunction;
/* Indices match the eGPUType enum */
@@ -230,15 +227,17 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
return str;
}
-static void gpu_parse_functions_string(GHash *hash, char *code)
+static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
{
GPUFunction *function;
eGPUType type;
GPUFunctionQual qual;
int i;
+ char *code = library->code;
while ((code = strstr(code, "void "))) {
function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
+ function->library = library;
code = gpu_str_skip_token(code, NULL, 0);
code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
@@ -367,11 +366,6 @@ static char *gpu_generate_function_prototyps(GHash *hash)
static GPUFunction *gpu_lookup_function(const char *name)
{
- if (!FUNCTION_HASH) {
- FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
- gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
- }
-
return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
}
@@ -395,11 +389,6 @@ void gpu_codegen_exit(void)
GPU_shader_free_builtin_shaders();
- if (glsl_material_library) {
- MEM_freeN(glsl_material_library);
- glsl_material_library = NULL;
- }
-
#if 0
if (FUNCTION_PROTOTYPES) {
MEM_freeN(FUNCTION_PROTOTYPES);
@@ -1381,20 +1370,15 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
void GPU_code_generate_glsl_lib(void)
{
- DynStr *ds;
-
- /* only initialize the library once */
- if (glsl_material_library) {
+ /* Only parse GLSL shader files once. */
+ if (FUNCTION_HASH) {
return;
}
- ds = BLI_dynstr_new();
-
- BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
-
- glsl_material_library = BLI_dynstr_get_cstring(ds);
-
- BLI_dynstr_free(ds);
+ FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
+ for (int i = 0; gpu_material_libraries[i].code; i++) {
+ gpu_parse_material_library(FUNCTION_HASH, &gpu_material_libraries[i]);
+ }
}
/* GPU pass binding/unbinding */
@@ -1796,6 +1780,19 @@ GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
return link;
}
+static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library)
+{
+ GSet *used_libraries = gpu_material_used_libraries(material);
+
+ if (BLI_gset_add(used_libraries, library->code)) {
+ if (library->dependencies) {
+ for (int i = 0; library->dependencies[i]; i++) {
+ BLI_gset_add(used_libraries, library->dependencies[i]);
+ }
+ }
+ }
+}
+
bool GPU_link(GPUMaterial *mat, const char *name, ...)
{
GPUNode *node;
@@ -1810,6 +1807,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
return false;
}
+ gpu_material_use_library(mat, function->library);
+
node = GPU_node_begin(name);
va_start(params, name);
@@ -1849,6 +1848,8 @@ bool GPU_stack_link(GPUMaterial *material,
return false;
}
+ gpu_material_use_library(material, function->library);
+
node = GPU_node_begin(name);
totin = 0;
totout = 0;
@@ -1962,6 +1963,30 @@ static bool gpu_pass_is_valid(GPUPass *pass)
return (pass->compiled == false || pass->shader != NULL);
}
+static char *code_generate_material_library(GPUMaterial *material, const char *frag_lib)
+{
+ DynStr *ds = BLI_dynstr_new();
+
+ if (frag_lib) {
+ BLI_dynstr_append(ds, frag_lib);
+ }
+
+ GSet *used_libraries = gpu_material_used_libraries(material);
+
+ /* Add library code in order, for dependencies. */
+ for (int i = 0; gpu_material_libraries[i].code; i++) {
+ GPUMaterialLibrary *library = &gpu_material_libraries[i];
+ if (BLI_gset_haskey(used_libraries, library->code)) {
+ BLI_dynstr_append(ds, library->code);
+ }
+ }
+
+ char *result = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return result;
+}
+
GPUPass *GPU_generate_pass(GPUMaterial *material,
GPUNodeLink *frag_outlink,
struct GPUVertAttrLayers *attrs,
@@ -2000,7 +2025,7 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
/* Either the shader is not compiled or there is a hash collision...
* continue generating the shader strings. */
- char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ char *tmp = code_generate_material_library(material, frag_lib);
geometrycode = code_generate_geometry(nodes, geom_code, defines);
vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL));
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 6eb6bc2f05f..4e09f16ebf8 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -33,6 +33,7 @@ struct GPUNode;
struct GPUOutput;
struct GPUShader;
struct GPUVertAttrLayers;
+struct GSet;
struct ListBase;
/* Pass Generation
@@ -207,4 +208,6 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
float *pixels,
float *row);
+struct GSet *gpu_material_used_libraries(struct GPUMaterial *material);
+
#endif
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 20b91c0c95d..05d991105c0 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
+#include "BLI_ghash.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -102,6 +103,8 @@ struct GPUMaterial {
GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
GPUColorBandBuilder *coba_builder;
+ GSet *used_libraries;
+
#ifndef NDEBUG
char name[64];
#endif
@@ -183,6 +186,8 @@ static void gpu_material_free_single(GPUMaterial *material)
if (material->coba_tex != NULL) {
GPU_texture_free(material->coba_tex);
}
+
+ BLI_gset_free(material->used_libraries, NULL);
}
void GPU_material_free(ListBase *gpumaterial)
@@ -582,6 +587,11 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
BLI_addtail(&material->nodes, node);
}
+GSet *gpu_material_used_libraries(GPUMaterial *material)
+{
+ return material->used_libraries;
+}
+
/* Return true if the material compilation has not yet begin or begin. */
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
{
@@ -659,6 +669,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
UNUSED_VARS(name);
#endif
+ mat->used_libraries = BLI_gset_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUMaterial.used_libraries");
+
/* localize tree to create links for reroute and mute */
bNodeTree *localtree = ntreeLocalize(ntree);
ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
new file mode 100644
index 00000000000..7160a56a60e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * List of all gpu_shader_material_*.glsl files used by GLSL materials. These
+ * will be parsed to make all functions in them available to use for GPU_link().
+ *
+ * If a file uses functions from another file, it must be added to the list of
+ * dependencies, and be placed after that file in the list. */
+
+#ifndef __GPU_MATERIAL_LIBRARY_H__
+#define __GPU_MATERIAL_LIBRARY_H__
+
+typedef struct GPUMaterialLibrary {
+ char *code;
+ char *dependencies[8];
+} GPUMaterialLibrary;
+
+extern char datatoc_gpu_shader_material_glsl[];
+extern char datatoc_gpu_shader_material_hash_glsl[];
+extern char datatoc_gpu_shader_material_magic_glsl[];
+extern char datatoc_gpu_shader_material_white_noise_glsl[];
+
+static GPUMaterialLibrary gpu_material_libraries[] = {
+ {datatoc_gpu_shader_material_hash_glsl, {NULL}},
+ {datatoc_gpu_shader_material_glsl, {datatoc_gpu_shader_material_hash_glsl, NULL}},
+ {datatoc_gpu_shader_material_magic_glsl, {NULL}},
+ {datatoc_gpu_shader_material_white_noise_glsl, {datatoc_gpu_shader_material_hash_glsl, NULL}},
+ {NULL, {NULL}}};
+
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 24fef4f05d8..57061ad1628 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1167,235 +1167,6 @@ float integer_noise(int n)
return 0.5 * (float(nn) / 1073741824.0);
}
-/* ***** Jenkins Lookup3 Hash Functions ***** */
-
-/* Source: http://burtleburtle.net/bob/c/lookup3.c */
-
-#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
-
-#define mix(a, b, c) \
- { \
- a -= c; \
- a ^= rot(c, 4); \
- c += b; \
- b -= a; \
- b ^= rot(a, 6); \
- a += c; \
- c -= b; \
- c ^= rot(b, 8); \
- b += a; \
- a -= c; \
- a ^= rot(c, 16); \
- c += b; \
- b -= a; \
- b ^= rot(a, 19); \
- a += c; \
- c -= b; \
- c ^= rot(b, 4); \
- b += a; \
- }
-
-#define final(a, b, c) \
- { \
- c ^= b; \
- c -= rot(b, 14); \
- a ^= c; \
- a -= rot(c, 11); \
- b ^= a; \
- b -= rot(a, 25); \
- c ^= b; \
- c -= rot(b, 16); \
- a ^= c; \
- a -= rot(c, 4); \
- b ^= a; \
- b -= rot(a, 14); \
- c ^= b; \
- c -= rot(b, 24); \
- }
-
-uint hash_uint(uint kx)
-{
- uint a, b, c;
- a = b = c = 0xdeadbeefu + (1u << 2u) + 13u;
-
- a += kx;
- final(a, b, c);
-
- return c;
-}
-
-uint hash_uint2(uint kx, uint ky)
-{
- uint a, b, c;
- a = b = c = 0xdeadbeefu + (2u << 2u) + 13u;
-
- b += ky;
- a += kx;
- final(a, b, c);
-
- return c;
-}
-
-uint hash_uint3(uint kx, uint ky, uint kz)
-{
- uint a, b, c;
- a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;
-
- c += kz;
- b += ky;
- a += kx;
- final(a, b, c);
-
- return c;
-}
-
-uint hash_uint4(uint kx, uint ky, uint kz, uint kw)
-{
- uint a, b, c;
- a = b = c = 0xdeadbeefu + (4u << 2u) + 13u;
-
- a += kx;
- b += ky;
- c += kz;
- mix(a, b, c);
-
- a += kw;
- final(a, b, c);
-
- return c;
-}
-
-#undef rot
-#undef final
-#undef mix
-
-uint hash_int(int kx)
-{
- return hash_uint(uint(kx));
-}
-
-uint hash_int2(int kx, int ky)
-{
- return hash_uint2(uint(kx), uint(ky));
-}
-
-uint hash_int3(int kx, int ky, int kz)
-{
- return hash_uint3(uint(kx), uint(ky), uint(kz));
-}
-
-uint hash_int4(int kx, int ky, int kz, int kw)
-{
- return hash_uint4(uint(kx), uint(ky), uint(kz), uint(kw));
-}
-
-/* Hashing uint or uint[234] into a float in the range [0, 1]. */
-
-float hash_uint_to_float(uint kx)
-{
- return float(hash_uint(kx)) / float(0xFFFFFFFFu);
-}
-
-float hash_uint2_to_float(uint kx, uint ky)
-{
- return float(hash_uint2(kx, ky)) / float(0xFFFFFFFFu);
-}
-
-float hash_uint3_to_float(uint kx, uint ky, uint kz)
-{
- return float(hash_uint3(kx, ky, kz)) / float(0xFFFFFFFFu);
-}
-
-float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw)
-{
- return float(hash_uint4(kx, ky, kz, kw)) / float(0xFFFFFFFFu);
-}
-
-/* Hashing float or vec[234] into a float in the range [0, 1]. */
-
-float hash_float_to_float(float k)
-{
- return hash_uint_to_float(floatBitsToUint(k));
-}
-
-float hash_vec2_to_float(vec2 k)
-{
- return hash_uint2_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y));
-}
-
-float hash_vec3_to_float(vec3 k)
-{
- return hash_uint3_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z));
-}
-
-float hash_vec4_to_float(vec4 k)
-{
- return hash_uint4_to_float(
- floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z), floatBitsToUint(k.w));
-}
-
-/* Hashing vec[234] into vec[234] of components in the range [0, 1]. */
-
-vec2 hash_vec2_to_vec2(vec2 k)
-{
- return vec2(hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)));
-}
-
-vec3 hash_vec3_to_vec3(vec3 k)
-{
- return vec3(
- hash_vec3_to_float(k), hash_vec4_to_float(vec4(k, 1.0)), hash_vec4_to_float(vec4(k, 2.0)));
-}
-
-vec4 hash_vec4_to_vec4(vec4 k)
-{
- return vec4(hash_vec4_to_float(k.xyzw),
- hash_vec4_to_float(k.wxyz),
- hash_vec4_to_float(k.zwxy),
- hash_vec4_to_float(k.yzwx));
-}
-
-/* Hashing float or vec[234] into vec3 of components in range [0, 1]. */
-
-vec3 hash_float_to_vec3(float k)
-{
- return vec3(
- hash_float_to_float(k), hash_vec2_to_float(vec2(k, 1.0)), hash_vec2_to_float(vec2(k, 2.0)));
-}
-
-vec3 hash_vec2_to_vec3(vec2 k)
-{
- return vec3(
- hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)), hash_vec3_to_float(vec3(k, 2.0)));
-}
-
-vec3 hash_vec4_to_vec3(vec4 k)
-{
- return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx));
-}
-
-/* White Noise */
-
-void node_white_noise_1d(vec3 vector, float w, out float value)
-{
- value = hash_float_to_float(w);
-}
-
-void node_white_noise_2d(vec3 vector, float w, out float value)
-{
- value = hash_vec2_to_float(vector.xy);
-}
-
-void node_white_noise_3d(vec3 vector, float w, out float value)
-{
- value = hash_vec3_to_float(vector);
-}
-
-void node_white_noise_4d(vec3 vector, float w, out float value)
-{
- value = hash_vec4_to_float(vec4(vector, w));
-}
-
/* Cell Noise */
float bits_to_01(uint bits)
@@ -3022,68 +2793,6 @@ void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
alpha = 0.0;
}
-void node_tex_magic(
- vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac)
-{
- vec3 p = co * scale;
- float x = sin((p.x + p.y + p.z) * 5.0);
- float y = cos((-p.x + p.y - p.z) * 5.0);
- float z = -cos((-p.x - p.y + p.z) * 5.0);
-
- if (depth > 0) {
- x *= distortion;
- y *= distortion;
- z *= distortion;
- y = -cos(x - y + z);
- y *= distortion;
- if (depth > 1) {
- x = cos(x - y - z);
- x *= distortion;
- if (depth > 2) {
- z = sin(-x - y - z);
- z *= distortion;
- if (depth > 3) {
- x = -cos(-x + y - z);
- x *= distortion;
- if (depth > 4) {
- y = -sin(-x + y + z);
- y *= distortion;
- if (depth > 5) {
- y = -cos(-x + y + z);
- y *= distortion;
- if (depth > 6) {
- x = cos(x + y + z);
- x *= distortion;
- if (depth > 7) {
- z = sin(x + y - z);
- z *= distortion;
- if (depth > 8) {
- x = -cos(-x - y + z);
- x *= distortion;
- if (depth > 9) {
- y = -sin(x - y + z);
- y *= distortion;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (distortion != 0.0) {
- distortion *= 2.0;
- x /= distortion;
- y /= distortion;
- z /= distortion;
- }
-
- color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0);
- fac = (color.x + color.y + color.z) / 3.0;
-}
-
float noise_fade(float t)
{
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
diff --git a/source/blender/gpu/shaders/gpu_shader_material_hash.glsl b/source/blender/gpu/shaders/gpu_shader_material_hash.glsl
new file mode 100644
index 00000000000..9f95da0a75b
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_material_hash.glsl
@@ -0,0 +1,206 @@
+/* ***** Jenkins Lookup3 Hash Functions ***** */
+
+/* Source: http://burtleburtle.net/bob/c/lookup3.c */
+
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+#define mix(a, b, c) \
+ { \
+ a -= c; \
+ a ^= rot(c, 4); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 6); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 8); \
+ b += a; \
+ a -= c; \
+ a ^= rot(c, 16); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 19); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 4); \
+ b += a; \
+ }
+
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot(b, 14); \
+ a ^= c; \
+ a -= rot(c, 11); \
+ b ^= a; \
+ b -= rot(a, 25); \
+ c ^= b; \
+ c -= rot(b, 16); \
+ a ^= c; \
+ a -= rot(c, 4); \
+ b ^= a; \
+ b -= rot(a, 14); \
+ c ^= b; \
+ c -= rot(b, 24); \
+ }
+
+uint hash_uint(uint kx)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (1u << 2u) + 13u;
+
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint2(uint kx, uint ky)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (2u << 2u) + 13u;
+
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint3(uint kx, uint ky, uint kz)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;
+
+ c += kz;
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint4(uint kx, uint ky, uint kz, uint kw)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (4u << 2u) + 13u;
+
+ a += kx;
+ b += ky;
+ c += kz;
+ mix(a, b, c);
+
+ a += kw;
+ final(a, b, c);
+
+ return c;
+}
+
+#undef rot
+#undef final
+#undef mix
+
+uint hash_int(int kx)
+{
+ return hash_uint(uint(kx));
+}
+
+uint hash_int2(int kx, int ky)
+{
+ return hash_uint2(uint(kx), uint(ky));
+}
+
+uint hash_int3(int kx, int ky, int kz)
+{
+ return hash_uint3(uint(kx), uint(ky), uint(kz));
+}
+
+uint hash_int4(int kx, int ky, int kz, int kw)
+{
+ return hash_uint4(uint(kx), uint(ky), uint(kz), uint(kw));
+}
+
+/* Hashing uint or uint[234] into a float in the range [0, 1]. */
+
+float hash_uint_to_float(uint kx)
+{
+ return float(hash_uint(kx)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint2_to_float(uint kx, uint ky)
+{
+ return float(hash_uint2(kx, ky)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint3_to_float(uint kx, uint ky, uint kz)
+{
+ return float(hash_uint3(kx, ky, kz)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw)
+{
+ return float(hash_uint4(kx, ky, kz, kw)) / float(0xFFFFFFFFu);
+}
+
+/* Hashing float or vec[234] into a float in the range [0, 1]. */
+
+float hash_float_to_float(float k)
+{
+ return hash_uint_to_float(floatBitsToUint(k));
+}
+
+float hash_vec2_to_float(vec2 k)
+{
+ return hash_uint2_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y));
+}
+
+float hash_vec3_to_float(vec3 k)
+{
+ return hash_uint3_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z));
+}
+
+float hash_vec4_to_float(vec4 k)
+{
+ return hash_uint4_to_float(
+ floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z), floatBitsToUint(k.w));
+}
+
+/* Hashing vec[234] into vec[234] of components in the range [0, 1]. */
+
+vec2 hash_vec2_to_vec2(vec2 k)
+{
+ return vec2(hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)));
+}
+
+vec3 hash_vec3_to_vec3(vec3 k)
+{
+ return vec3(
+ hash_vec3_to_float(k), hash_vec4_to_float(vec4(k, 1.0)), hash_vec4_to_float(vec4(k, 2.0)));
+}
+
+vec4 hash_vec4_to_vec4(vec4 k)
+{
+ return vec4(hash_vec4_to_float(k.xyzw),
+ hash_vec4_to_float(k.wxyz),
+ hash_vec4_to_float(k.zwxy),
+ hash_vec4_to_float(k.yzwx));
+}
+
+/* Hashing float or vec[234] into vec3 of components in range [0, 1]. */
+
+vec3 hash_float_to_vec3(float k)
+{
+ return vec3(
+ hash_float_to_float(k), hash_vec2_to_float(vec2(k, 1.0)), hash_vec2_to_float(vec2(k, 2.0)));
+}
+
+vec3 hash_vec2_to_vec3(vec2 k)
+{
+ return vec3(
+ hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)), hash_vec3_to_float(vec3(k, 2.0)));
+}
+
+vec3 hash_vec4_to_vec3(vec4 k)
+{
+ return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_material_magic.glsl b/source/blender/gpu/shaders/gpu_shader_material_magic.glsl
new file mode 100644
index 00000000000..942c507cc38
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_material_magic.glsl
@@ -0,0 +1,61 @@
+void node_tex_magic(
+ vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac)
+{
+ vec3 p = co * scale;
+ float x = sin((p.x + p.y + p.z) * 5.0);
+ float y = cos((-p.x + p.y - p.z) * 5.0);
+ float z = -cos((-p.x - p.y + p.z) * 5.0);
+
+ if (depth > 0) {
+ x *= distortion;
+ y *= distortion;
+ z *= distortion;
+ y = -cos(x - y + z);
+ y *= distortion;
+ if (depth > 1) {
+ x = cos(x - y - z);
+ x *= distortion;
+ if (depth > 2) {
+ z = sin(-x - y - z);
+ z *= distortion;
+ if (depth > 3) {
+ x = -cos(-x + y - z);
+ x *= distortion;
+ if (depth > 4) {
+ y = -sin(-x + y + z);
+ y *= distortion;
+ if (depth > 5) {
+ y = -cos(-x + y + z);
+ y *= distortion;
+ if (depth > 6) {
+ x = cos(x + y + z);
+ x *= distortion;
+ if (depth > 7) {
+ z = sin(x + y - z);
+ z *= distortion;
+ if (depth > 8) {
+ x = -cos(-x - y + z);
+ x *= distortion;
+ if (depth > 9) {
+ y = -sin(x - y + z);
+ y *= distortion;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (distortion != 0.0) {
+ distortion *= 2.0;
+ x /= distortion;
+ y /= distortion;
+ z /= distortion;
+ }
+
+ color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0);
+ fac = (color.x + color.y + color.z) / 3.0;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl b/source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl
new file mode 100644
index 00000000000..fce511deb79
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl
@@ -0,0 +1,21 @@
+/* White Noise */
+
+void node_white_noise_1d(vec3 vector, float w, out float value)
+{
+ value = hash_float_to_float(w);
+}
+
+void node_white_noise_2d(vec3 vector, float w, out float value)
+{
+ value = hash_vec2_to_float(vector.xy);
+}
+
+void node_white_noise_3d(vec3 vector, float w, out float value)
+{
+ value = hash_vec3_to_float(vector);
+}
+
+void node_white_noise_4d(vec3 vector, float w, out float value)
+{
+ value = hash_vec4_to_float(vec4(vector, w));
+}