2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
2014-01-19 23:14:24 +11:00
|
|
|
*
|
|
|
|
|
* Manages materials, lights and textures.
|
2011-02-27 20:25:53 +00:00
|
|
|
*/
|
|
|
|
|
|
2023-08-02 20:15:49 +10:00
|
|
|
#include <cstring>
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
|
|
2018-07-20 20:06:39 +02:00
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_vector.h"
|
2018-08-02 18:31:38 +02:00
|
|
|
#include "BLI_string.h"
|
2024-01-19 14:32:28 +01:00
|
|
|
#include "BLI_time.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2025-01-09 17:26:40 +01:00
|
|
|
#include "BKE_material.hh"
|
2024-02-19 15:26:10 +01:00
|
|
|
#include "BKE_node.hh"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2022-01-24 16:18:30 -06:00
|
|
|
#include "NOD_shader.h"
|
|
|
|
|
|
2024-02-01 10:40:24 -05:00
|
|
|
#include "GPU_material.hh"
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "GPU_shader.hh"
|
|
|
|
|
#include "GPU_texture.hh"
|
2024-02-11 16:10:00 -05:00
|
|
|
#include "GPU_uniform_buffer.hh"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2024-01-05 11:16:57 -05:00
|
|
|
#include "DRW_engine.hh"
|
2018-03-05 00:54:31 +01:00
|
|
|
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "gpu_codegen.hh"
|
|
|
|
|
#include "gpu_node_graph.hh"
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2022-04-20 14:35:07 +02:00
|
|
|
#include "atomic_ops.h"
|
|
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* Structs */
|
2018-08-10 15:13:39 +02:00
|
|
|
#define MAX_COLOR_BAND 128
|
2022-09-16 15:04:47 +02:00
|
|
|
#define MAX_GPU_SKIES 8
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2023-11-30 14:15:11 +11:00
|
|
|
/**
|
|
|
|
|
* Whether the optimized variant of the GPUPass should be created asynchronously.
|
2023-02-14 21:51:03 +01:00
|
|
|
* Usage of this depends on whether there are possible threading challenges of doing so.
|
|
|
|
|
* Currently, the overhead of GPU_generate_pass is relatively small in comparison to shader
|
|
|
|
|
* compilation, though this option exists in case any potential scenarios for material graph
|
|
|
|
|
* optimization cause a slow down on the main thread.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: The actual shader program for the optimized pass will always be compiled asynchronously,
|
|
|
|
|
* this flag controls whether shader node graph source serialization happens on the compilation
|
|
|
|
|
* worker thread as well. */
|
|
|
|
|
#define ASYNC_OPTIMIZED_PASS_CREATION 0
|
|
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
struct GPUColorBandBuilder {
|
2018-08-10 15:13:39 +02:00
|
|
|
float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4];
|
|
|
|
|
int current_layer;
|
2023-07-27 14:16:58 +02:00
|
|
|
};
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
struct GPUSkyBuilder {
|
2022-09-16 15:04:47 +02:00
|
|
|
float pixels[MAX_GPU_SKIES][GPU_SKY_WIDTH * GPU_SKY_HEIGHT][4];
|
|
|
|
|
int current_layer;
|
2023-07-27 14:16:58 +02:00
|
|
|
};
|
2022-09-16 15:04:47 +02:00
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
struct GPUMaterial {
|
2022-09-23 14:33:43 +10:00
|
|
|
/* Contains #GPUShader and source code for deferred compilation.
|
|
|
|
|
* Can be shared between similar material (i.e: sharing same node-tree topology). */
|
2022-04-14 18:47:58 +02:00
|
|
|
GPUPass *pass;
|
2023-02-14 21:51:03 +01:00
|
|
|
/* Optimized GPUPass, situationally compiled after initial pass for optimal realtime performance.
|
|
|
|
|
* This shader variant bakes dynamic uniform data as constant. This variant will not use
|
|
|
|
|
* the ubo, and instead bake constants directly into the shader source. */
|
|
|
|
|
GPUPass *optimized_pass;
|
|
|
|
|
/* Optimization status.
|
|
|
|
|
* We also use this status to determine whether this material should be considered for
|
|
|
|
|
* optimization. Only sufficiently complex shaders benefit from constant-folding optimizations.
|
|
|
|
|
* `GPU_MAT_OPTIMIZATION_READY` -> shader should be optimized and is ready for optimization.
|
|
|
|
|
* `GPU_MAT_OPTIMIZATION_SKIP` -> Shader should not be optimized as it would not benefit
|
|
|
|
|
* performance to do so, based on the heuristic.
|
|
|
|
|
*/
|
|
|
|
|
eGPUMaterialOptimizationStatus optimization_status;
|
|
|
|
|
double creation_time;
|
|
|
|
|
#if ASYNC_OPTIMIZED_PASS_CREATION == 1
|
|
|
|
|
struct DeferredOptimizePass {
|
|
|
|
|
GPUCodegenCallbackFn callback;
|
|
|
|
|
void *thunk;
|
|
|
|
|
} DeferredOptimizePass;
|
|
|
|
|
struct DeferredOptimizePass optimize_pass_info;
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
/** UBOs for this material parameters. */
|
|
|
|
|
GPUUniformBuf *ubo;
|
|
|
|
|
/** Compilation status. Do not use if shader is not GPU_MAT_SUCCESS. */
|
2019-01-23 14:15:43 +11:00
|
|
|
eGPUMaterialStatus status;
|
2022-04-14 18:47:58 +02:00
|
|
|
/** Some flags about the nodetree & the needed resources. */
|
|
|
|
|
eGPUMaterialFlag flag;
|
2023-12-07 16:48:09 +01:00
|
|
|
/** The engine type this material is compiled for. */
|
|
|
|
|
eGPUMaterialEngine engine;
|
|
|
|
|
/* Identify shader variations (shadow, probe, world background...) */
|
2022-04-14 18:47:58 +02:00
|
|
|
uint64_t uuid;
|
|
|
|
|
/* Number of generated function. */
|
|
|
|
|
int generated_function_len;
|
|
|
|
|
/** Object type for attribute fetching. */
|
|
|
|
|
bool is_volume_shader;
|
|
|
|
|
|
|
|
|
|
/** DEPRECATED Currently only used for deferred compilation. */
|
|
|
|
|
Scene *scene;
|
|
|
|
|
/** Source material, might be null. */
|
|
|
|
|
Material *ma;
|
|
|
|
|
/** 1D Texture array containing all color bands. */
|
|
|
|
|
GPUTexture *coba_tex;
|
|
|
|
|
/** Builder for coba_tex. */
|
|
|
|
|
GPUColorBandBuilder *coba_builder;
|
2022-09-16 15:04:47 +02:00
|
|
|
/** 2D Texture array containing all sky textures. */
|
|
|
|
|
GPUTexture *sky_tex;
|
|
|
|
|
/** Builder for sky_tex. */
|
|
|
|
|
GPUSkyBuilder *sky_builder;
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Low level node graph(s). Also contains resources needed by the material. */
|
2020-02-12 12:48:44 +01:00
|
|
|
GPUNodeGraph graph;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-14 21:51:03 +01:00
|
|
|
/** Default material reference used for PSO cache warming. Default materials may perform
|
|
|
|
|
* different operations, but the permutation will frequently share the same input PSO
|
2023-02-15 13:11:14 +11:00
|
|
|
* descriptors. This enables asynchronous PSO compilation as part of the deferred compilation
|
2023-02-14 21:51:03 +01:00
|
|
|
* pass, reducing runtime stuttering and responsiveness while compiling materials. */
|
|
|
|
|
GPUMaterial *default_mat;
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
/** DEPRECATED: To remove. */
|
2020-03-11 14:58:19 +01:00
|
|
|
bool has_surface_output;
|
2022-04-14 18:47:58 +02:00
|
|
|
bool has_volume_output;
|
2023-11-07 15:28:07 +01:00
|
|
|
bool has_displacement_output;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-20 14:35:07 +02:00
|
|
|
uint32_t refcount;
|
|
|
|
|
|
2024-06-07 16:11:50 +02:00
|
|
|
bool do_batch_compilation;
|
|
|
|
|
|
2018-08-02 18:31:38 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
char name[64];
|
2022-08-30 22:03:21 +02:00
|
|
|
#else
|
|
|
|
|
char name[16];
|
2018-08-02 18:31:38 +02:00
|
|
|
#endif
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Functions */
|
|
|
|
|
|
2022-09-16 15:04:47 +02:00
|
|
|
GPUTexture **gpu_material_sky_texture_layer_set(
|
|
|
|
|
GPUMaterial *mat, int width, int height, const float *pixels, float *row)
|
|
|
|
|
{
|
|
|
|
|
/* In order to put all sky textures into one 2D array texture,
|
|
|
|
|
* we need them to be the same size. */
|
|
|
|
|
BLI_assert(width == GPU_SKY_WIDTH);
|
|
|
|
|
BLI_assert(height == GPU_SKY_HEIGHT);
|
|
|
|
|
UNUSED_VARS_NDEBUG(width, height);
|
|
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->sky_builder == nullptr) {
|
|
|
|
|
mat->sky_builder = static_cast<GPUSkyBuilder *>(
|
|
|
|
|
MEM_mallocN(sizeof(GPUSkyBuilder), "GPUSkyBuilder"));
|
2022-09-16 15:04:47 +02:00
|
|
|
mat->sky_builder->current_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int layer = mat->sky_builder->current_layer;
|
2023-07-28 09:38:07 +10:00
|
|
|
*row = float(layer);
|
2022-09-16 15:04:47 +02:00
|
|
|
|
|
|
|
|
if (*row == MAX_GPU_SKIES) {
|
|
|
|
|
printf("Too many sky textures in shader!\n");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
float *dst = (float *)mat->sky_builder->pixels[layer];
|
|
|
|
|
memcpy(dst, pixels, sizeof(float) * GPU_SKY_WIDTH * GPU_SKY_HEIGHT * 4);
|
|
|
|
|
mat->sky_builder->current_layer += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &mat->sky_tex;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-10 15:13:39 +02:00
|
|
|
GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
|
|
|
|
|
int size,
|
2024-07-29 13:01:12 +10:00
|
|
|
const float *pixels,
|
|
|
|
|
float *r_row)
|
2018-08-10 15:13:39 +02:00
|
|
|
{
|
2020-09-07 15:57:12 +10:00
|
|
|
/* In order to put all the color-bands into one 1D array texture,
|
2018-08-10 15:13:39 +02:00
|
|
|
* we need them to be the same size. */
|
|
|
|
|
BLI_assert(size == CM_TABLE + 1);
|
2018-09-10 09:56:14 +02:00
|
|
|
UNUSED_VARS_NDEBUG(size);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->coba_builder == nullptr) {
|
|
|
|
|
mat->coba_builder = static_cast<GPUColorBandBuilder *>(
|
|
|
|
|
MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder"));
|
2018-08-10 15:13:39 +02:00
|
|
|
mat->coba_builder->current_layer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int layer = mat->coba_builder->current_layer;
|
2024-07-29 13:01:12 +10:00
|
|
|
*r_row = float(layer);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
2024-07-29 13:01:12 +10:00
|
|
|
if (*r_row == MAX_COLOR_BAND) {
|
2018-08-10 15:13:39 +02:00
|
|
|
printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
float *dst = (float *)mat->coba_builder->pixels[layer];
|
|
|
|
|
memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4);
|
|
|
|
|
mat->coba_builder->current_layer += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &mat->coba_tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gpu_material_ramp_texture_build(GPUMaterial *mat)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->coba_builder == nullptr) {
|
2018-08-10 15:13:39 +02:00
|
|
|
return;
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
2018-08-10 15:13:39 +02:00
|
|
|
|
|
|
|
|
GPUColorBandBuilder *builder = mat->coba_builder;
|
|
|
|
|
|
2023-02-25 01:52:27 +01:00
|
|
|
mat->coba_tex = GPU_texture_create_1d_array("mat_ramp",
|
|
|
|
|
CM_TABLE + 1,
|
|
|
|
|
builder->current_layer,
|
|
|
|
|
1,
|
|
|
|
|
GPU_RGBA16F,
|
|
|
|
|
GPU_TEXTURE_USAGE_SHADER_READ,
|
|
|
|
|
(float *)builder->pixels);
|
2018-08-10 15:13:39 +02:00
|
|
|
|
|
|
|
|
MEM_freeN(builder);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->coba_builder = nullptr;
|
2018-08-10 15:13:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-16 15:04:47 +02:00
|
|
|
static void gpu_material_sky_texture_build(GPUMaterial *mat)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
if (mat->sky_builder == nullptr) {
|
2022-09-16 15:04:47 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 01:52:27 +01:00
|
|
|
mat->sky_tex = GPU_texture_create_2d_array("mat_sky",
|
|
|
|
|
GPU_SKY_WIDTH,
|
|
|
|
|
GPU_SKY_HEIGHT,
|
|
|
|
|
mat->sky_builder->current_layer,
|
|
|
|
|
1,
|
|
|
|
|
GPU_RGBA32F,
|
2023-04-18 08:11:46 +02:00
|
|
|
GPU_TEXTURE_USAGE_SHADER_READ,
|
2023-02-25 01:52:27 +01:00
|
|
|
(float *)mat->sky_builder->pixels);
|
2022-09-16 15:04:47 +02:00
|
|
|
|
|
|
|
|
MEM_freeN(mat->sky_builder);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->sky_builder = nullptr;
|
2022-09-16 15:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 08:37:57 +02:00
|
|
|
void GPU_material_free_single(GPUMaterial *material)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2022-04-20 14:35:07 +02:00
|
|
|
bool do_free = atomic_sub_and_fetch_uint32(&material->refcount, 1) == 0;
|
|
|
|
|
if (!do_free) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-02-12 12:48:44 +01:00
|
|
|
gpu_node_graph_free(&material->graph);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->optimized_pass != nullptr) {
|
2023-02-14 21:51:03 +01:00
|
|
|
GPU_pass_release(material->optimized_pass);
|
|
|
|
|
}
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->pass != nullptr) {
|
2018-06-08 16:11:34 +02:00
|
|
|
GPU_pass_release(material->pass);
|
2018-08-10 15:13:39 +02:00
|
|
|
}
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->ubo != nullptr) {
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_free(material->ubo);
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
2024-05-09 19:38:22 +02:00
|
|
|
if (material->coba_builder != nullptr) {
|
|
|
|
|
MEM_freeN(material->coba_builder);
|
|
|
|
|
}
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->coba_tex != nullptr) {
|
2022-04-14 18:47:58 +02:00
|
|
|
GPU_texture_free(material->coba_tex);
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->sky_tex != nullptr) {
|
2022-09-16 15:04:47 +02:00
|
|
|
GPU_texture_free(material->sky_tex);
|
|
|
|
|
}
|
2022-05-09 09:54:26 +02:00
|
|
|
MEM_freeN(material);
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_free(ListBase *gpumaterial)
|
|
|
|
|
{
|
2020-04-03 19:15:01 +02:00
|
|
|
LISTBASE_FOREACH (LinkData *, link, gpumaterial) {
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUMaterial *material = static_cast<GPUMaterial *>(link->data);
|
2022-04-20 14:35:07 +02:00
|
|
|
DRW_deferred_shader_remove(material);
|
2022-07-29 08:37:57 +02:00
|
|
|
GPU_material_free_single(material);
|
2018-06-08 16:11:34 +02:00
|
|
|
}
|
|
|
|
|
BLI_freelistN(gpumaterial);
|
|
|
|
|
}
|
2017-11-14 00:49:54 +01:00
|
|
|
|
2013-11-25 20:58:23 +09:00
|
|
|
Scene *GPU_material_scene(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->scene;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 22:27:09 +02:00
|
|
|
GPUPass *GPU_material_get_pass(GPUMaterial *material)
|
|
|
|
|
{
|
2023-02-14 21:51:03 +01:00
|
|
|
/* If an optimized pass variant is available, and optimization is
|
|
|
|
|
* flagged as complete, we use this one instead. */
|
|
|
|
|
return ((GPU_material_optimization_status(material) == GPU_MAT_OPTIMIZATION_SUCCESS) &&
|
|
|
|
|
material->optimized_pass) ?
|
|
|
|
|
material->optimized_pass :
|
|
|
|
|
material->pass;
|
2017-04-27 22:27:09 +02:00
|
|
|
}
|
2014-11-24 17:18:56 +01:00
|
|
|
|
2020-06-02 16:58:07 +02:00
|
|
|
GPUShader *GPU_material_get_shader(GPUMaterial *material)
|
|
|
|
|
{
|
2023-02-14 21:51:03 +01:00
|
|
|
/* If an optimized material shader variant is available, and optimization is
|
|
|
|
|
* flagged as complete, we use this one instead. */
|
|
|
|
|
GPUShader *shader = ((GPU_material_optimization_status(material) ==
|
|
|
|
|
GPU_MAT_OPTIMIZATION_SUCCESS) &&
|
|
|
|
|
material->optimized_pass) ?
|
|
|
|
|
GPU_pass_shader_get(material->optimized_pass) :
|
2023-07-27 14:16:58 +02:00
|
|
|
nullptr;
|
|
|
|
|
return (shader) ? shader : ((material->pass) ? GPU_pass_shader_get(material->pass) : nullptr);
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUShader *GPU_material_get_shader_base(GPUMaterial *material)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
return (material->pass) ? GPU_pass_shader_get(material->pass) : nullptr;
|
2020-06-02 16:58:07 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-30 22:03:21 +02:00
|
|
|
const char *GPU_material_get_name(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->name;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-11 14:37:27 +02:00
|
|
|
Material *GPU_material_get_material(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->ma;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-20 23:09:37 +02:00
|
|
|
GPUUniformBuf *GPU_material_uniform_buffer_get(GPUMaterial *material)
|
2017-07-14 17:40:54 +02:00
|
|
|
{
|
|
|
|
|
return material->ubo;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-07 19:40:47 +02:00
|
|
|
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
|
2017-07-14 17:40:54 +02:00
|
|
|
{
|
2022-08-30 22:03:21 +02:00
|
|
|
material->ubo = GPU_uniformbuf_create_from_list(inputs, material->name);
|
2017-07-14 17:40:54 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:54:06 -05:00
|
|
|
ListBase GPU_material_attributes(const GPUMaterial *material)
|
2022-04-14 18:47:58 +02:00
|
|
|
{
|
|
|
|
|
return material->graph.attributes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListBase GPU_material_textures(GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
return material->graph.textures;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-02 19:01:12 +02:00
|
|
|
const GPUUniformAttrList *GPU_material_uniform_attributes(const GPUMaterial *material)
|
2022-04-14 18:47:58 +02:00
|
|
|
{
|
2022-09-02 19:01:12 +02:00
|
|
|
const GPUUniformAttrList *attrs = &material->graph.uniform_attrs;
|
2023-07-27 14:16:58 +02:00
|
|
|
return attrs->count > 0 ? attrs : nullptr;
|
2022-04-14 18:47:58 +02:00
|
|
|
}
|
|
|
|
|
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
const ListBase *GPU_material_layer_attributes(const GPUMaterial *material)
|
|
|
|
|
{
|
|
|
|
|
const ListBase *attrs = &material->graph.layer_attrs;
|
2023-07-27 14:16:58 +02:00
|
|
|
return !BLI_listbase_is_empty(attrs) ? attrs : nullptr;
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_output_surface(GPUMaterial *material, GPUNodeLink *link)
|
2020-02-14 10:47:20 +01:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
if (!material->graph.outlink_surface) {
|
|
|
|
|
material->graph.outlink_surface = link;
|
|
|
|
|
material->has_surface_output = true;
|
|
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_output_volume(GPUMaterial *material, GPUNodeLink *link)
|
2020-03-11 14:58:19 +01:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
if (!material->graph.outlink_volume) {
|
|
|
|
|
material->graph.outlink_volume = link;
|
|
|
|
|
material->has_volume_output = true;
|
|
|
|
|
}
|
2020-03-11 14:58:19 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_output_displacement(GPUMaterial *material, GPUNodeLink *link)
|
Materials: add custom object properties as uniform attributes.
This patch allows the user to type a property name into the
Attribute node, which will then output the value of the property
for each individual object, allowing to e.g. customize shaders
by object without duplicating the shader.
In order to make supporting this easier for Eevee, it is necessary
to explicitly choose whether the attribute is varying or uniform
via a dropdown option of the Attribute node. The dropdown also
allows choosing whether instancing should be taken into account.
The Cycles design treats all attributes as one common namespace,
so the Blender interface converts the enum to a name prefix that
can't be entered using keyboard.
In Eevee, the attributes are provided to the shader via a UBO indexed
with resource_id, similar to the existing Object Info data. Unlike it,
however, it is necessary to maintain a separate buffer for every
requested combination of attributes.
This is done using a hash table with the attribute set as the key,
as it is expected that technically different but similar materials
may use the same set of attributes. In addition, in order to minimize
wasted memory, a sparse UBO pool is implemented, so that chunks that
don't contain any data don't have to be allocated.
The back-end Cycles code is already refactored and committed by Brecht.
Differential Revision: https://developer.blender.org/D2057
2020-08-05 19:14:40 +03:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
if (!material->graph.outlink_displacement) {
|
|
|
|
|
material->graph.outlink_displacement = link;
|
2023-11-07 15:28:07 +01:00
|
|
|
material->has_displacement_output = true;
|
2022-04-14 18:47:58 +02:00
|
|
|
}
|
Materials: add custom object properties as uniform attributes.
This patch allows the user to type a property name into the
Attribute node, which will then output the value of the property
for each individual object, allowing to e.g. customize shaders
by object without duplicating the shader.
In order to make supporting this easier for Eevee, it is necessary
to explicitly choose whether the attribute is varying or uniform
via a dropdown option of the Attribute node. The dropdown also
allows choosing whether instancing should be taken into account.
The Cycles design treats all attributes as one common namespace,
so the Blender interface converts the enum to a name prefix that
can't be entered using keyboard.
In Eevee, the attributes are provided to the shader via a UBO indexed
with resource_id, similar to the existing Object Info data. Unlike it,
however, it is necessary to maintain a separate buffer for every
requested combination of attributes.
This is done using a hash table with the attribute set as the key,
as it is expected that technically different but similar materials
may use the same set of attributes. In addition, in order to minimize
wasted memory, a sparse UBO pool is implemented, so that chunks that
don't contain any data don't have to be allocated.
The back-end Cycles code is already refactored and committed by Brecht.
Differential Revision: https://developer.blender.org/D2057
2020-08-05 19:14:40 +03:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_output_thickness(GPUMaterial *material, GPUNodeLink *link)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
if (!material->graph.outlink_thickness) {
|
|
|
|
|
material->graph.outlink_thickness = link;
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-04 08:13:54 +01:00
|
|
|
void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUNodeGraphOutputLink *aov_link = static_cast<GPUNodeGraphOutputLink *>(
|
|
|
|
|
MEM_callocN(sizeof(GPUNodeGraphOutputLink), __func__));
|
2020-12-04 08:13:54 +01:00
|
|
|
aov_link->outlink = link;
|
|
|
|
|
aov_link->hash = hash;
|
|
|
|
|
BLI_addtail(&material->graph.outlink_aovs, aov_link);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-29 08:37:57 +02:00
|
|
|
void GPU_material_add_output_link_composite(GPUMaterial *material, GPUNodeLink *link)
|
|
|
|
|
{
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUNodeGraphOutputLink *compositor_link = static_cast<GPUNodeGraphOutputLink *>(
|
|
|
|
|
MEM_callocN(sizeof(GPUNodeGraphOutputLink), __func__));
|
2022-07-29 08:37:57 +02:00
|
|
|
compositor_link->outlink = link;
|
|
|
|
|
BLI_addtail(&material->graph.outlink_compositor, compositor_link);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
char *GPU_material_split_sub_function(GPUMaterial *material,
|
|
|
|
|
eGPUType return_type,
|
|
|
|
|
GPUNodeLink **link)
|
|
|
|
|
{
|
|
|
|
|
/* Force cast to return type. */
|
|
|
|
|
switch (return_type) {
|
|
|
|
|
case GPU_FLOAT:
|
|
|
|
|
GPU_link(material, "set_value", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
case GPU_VEC3:
|
|
|
|
|
GPU_link(material, "set_rgb", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
case GPU_VEC4:
|
|
|
|
|
GPU_link(material, "set_rgba", *link, link);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUNodeGraphFunctionLink *func_link = static_cast<GPUNodeGraphFunctionLink *>(
|
|
|
|
|
MEM_callocN(sizeof(GPUNodeGraphFunctionLink), __func__));
|
2022-04-14 18:47:58 +02:00
|
|
|
func_link->outlink = *link;
|
|
|
|
|
SNPRINTF(func_link->name, "ntree_fn%d", material->generated_function_len++);
|
|
|
|
|
BLI_addtail(&material->graph.material_functions, func_link);
|
|
|
|
|
|
|
|
|
|
return func_link->name;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-27 13:55:29 +01:00
|
|
|
GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2020-02-27 13:55:29 +01:00
|
|
|
return &material->graph;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
|
2019-08-23 14:36:22 +02:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
return mat->status;
|
2019-08-23 14:36:22 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_status_set(GPUMaterial *mat, eGPUMaterialStatus status)
|
2018-03-05 00:54:31 +01:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
mat->status = status;
|
2018-03-05 00:54:31 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-14 21:51:03 +01:00
|
|
|
eGPUMaterialOptimizationStatus GPU_material_optimization_status(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->optimization_status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_optimization_status_set(GPUMaterial *mat, eGPUMaterialOptimizationStatus status)
|
|
|
|
|
{
|
|
|
|
|
mat->optimization_status = status;
|
|
|
|
|
if (mat->optimization_status == GPU_MAT_OPTIMIZATION_READY) {
|
|
|
|
|
/* Reset creation timer to delay optimization pass. */
|
2024-02-15 13:15:56 +11:00
|
|
|
mat->creation_time = BLI_time_now_seconds();
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_optimization_ready(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
/* Timer threshold before optimizations will be queued.
|
|
|
|
|
* When materials are frequently being modified, optimization
|
|
|
|
|
* can incur CPU overhead from excessive compilation.
|
|
|
|
|
*
|
|
|
|
|
* As the optimization is entirely asynchronous, it is still beneficial
|
|
|
|
|
* to do this quickly to avoid build-up and improve runtime performance.
|
|
|
|
|
* The threshold just prevents compilations being queued frame after frame. */
|
|
|
|
|
const double optimization_time_threshold_s = 1.2;
|
2024-02-15 13:15:56 +11:00
|
|
|
return ((BLI_time_now_seconds() - mat->creation_time) >= optimization_time_threshold_s);
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_set_default(GPUMaterial *material, GPUMaterial *default_material)
|
|
|
|
|
{
|
|
|
|
|
if (material != default_material) {
|
|
|
|
|
material->default_mat = default_material;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* Code generation */
|
|
|
|
|
|
2020-03-11 14:58:19 +01:00
|
|
|
bool GPU_material_has_surface_output(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->has_surface_output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_material_has_volume_output(GPUMaterial *mat)
|
2017-10-27 16:07:44 +02:00
|
|
|
{
|
2020-03-11 14:58:19 +01:00
|
|
|
return mat->has_volume_output;
|
2017-10-27 16:07:44 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-07 15:28:07 +01:00
|
|
|
bool GPU_material_has_displacement_output(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->has_displacement_output;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
|
2017-10-27 16:07:44 +02:00
|
|
|
{
|
2024-02-24 00:00:11 +01:00
|
|
|
if ((flag & GPU_MATFLAG_GLOSSY) && (mat->flag & GPU_MATFLAG_GLOSSY)) {
|
|
|
|
|
/* Tag material using multiple glossy BSDF as using clear coat. */
|
|
|
|
|
mat->flag |= GPU_MATFLAG_COAT;
|
|
|
|
|
}
|
2022-04-14 18:47:58 +02:00
|
|
|
mat->flag |= flag;
|
2017-10-27 16:07:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
|
2018-08-03 18:53:36 +02:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
return (mat->flag & flag) != 0;
|
2018-08-03 18:53:36 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
eGPUMaterialFlag GPU_material_flag(const GPUMaterial *mat)
|
2018-08-03 18:53:36 +02:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
return mat->flag;
|
2018-08-03 18:53:36 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
bool GPU_material_recalc_flag_get(GPUMaterial *mat)
|
2017-04-27 22:27:09 +02:00
|
|
|
{
|
2023-03-29 14:16:31 +11:00
|
|
|
/* NOTE: Consumes the flags. */
|
|
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
bool updated = (mat->flag & GPU_MATFLAG_UPDATED) != 0;
|
|
|
|
|
mat->flag &= ~GPU_MATFLAG_UPDATED;
|
|
|
|
|
return updated;
|
|
|
|
|
}
|
2017-04-27 22:27:09 +02:00
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
uint64_t GPU_material_uuid_get(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
return mat->uuid;
|
2017-06-28 10:50:33 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GPUMaterial *GPU_material_from_nodetree(Scene *scene,
|
2022-04-14 18:47:58 +02:00
|
|
|
Material *ma,
|
|
|
|
|
bNodeTree *ntree,
|
2018-06-07 11:58:15 +02:00
|
|
|
ListBase *gpumaterials,
|
2020-07-30 13:55:13 +02:00
|
|
|
const char *name,
|
2023-12-07 16:48:09 +01:00
|
|
|
eGPUMaterialEngine engine,
|
2022-04-14 18:47:58 +02:00
|
|
|
uint64_t shader_uuid,
|
|
|
|
|
bool is_volume_shader,
|
|
|
|
|
bool is_lookdev,
|
|
|
|
|
GPUCodegenCallbackFn callback,
|
2024-04-30 19:44:06 +02:00
|
|
|
void *thunk,
|
2024-05-15 16:01:05 +02:00
|
|
|
GPUMaterialPassReplacementCallbackFn pass_replacement_cb)
|
2017-06-28 10:50:33 +10:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Search if this material is not already compiled. */
|
|
|
|
|
LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
|
|
|
|
|
GPUMaterial *mat = (GPUMaterial *)link->data;
|
2023-12-07 16:48:09 +01:00
|
|
|
if (mat->uuid == shader_uuid && mat->engine == engine) {
|
2022-04-14 18:47:58 +02:00
|
|
|
return mat;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-02 16:58:07 +02:00
|
|
|
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUMaterial *mat = static_cast<GPUMaterial *>(MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"));
|
2019-05-11 14:37:27 +02:00
|
|
|
mat->ma = ma;
|
2017-05-01 18:09:50 +02:00
|
|
|
mat->scene = scene;
|
2023-12-07 16:48:09 +01:00
|
|
|
mat->engine = engine;
|
2022-04-14 18:47:58 +02:00
|
|
|
mat->uuid = shader_uuid;
|
|
|
|
|
mat->flag = GPU_MATFLAG_UPDATED;
|
2022-04-20 14:50:39 +02:00
|
|
|
mat->status = GPU_MAT_CREATED;
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->default_mat = nullptr;
|
2020-03-11 14:58:19 +01:00
|
|
|
mat->is_volume_shader = is_volume_shader;
|
2022-04-14 18:47:58 +02:00
|
|
|
mat->graph.used_libraries = BLI_gset_new(
|
|
|
|
|
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries");
|
2022-04-20 14:35:07 +02:00
|
|
|
mat->refcount = 1;
|
2022-06-17 17:14:00 +10:00
|
|
|
STRNCPY(mat->name, name);
|
2022-04-14 18:47:58 +02:00
|
|
|
if (is_lookdev) {
|
|
|
|
|
mat->flag |= GPU_MATFLAG_LOOKDEV_HACK;
|
|
|
|
|
}
|
2017-04-27 22:27:09 +02:00
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Localize tree to create links for reroute and mute. */
|
2024-08-19 20:27:37 +02:00
|
|
|
bNodeTree *localtree = blender::bke::node_tree_localize(ntree, nullptr);
|
2022-04-14 18:47:58 +02:00
|
|
|
ntreeGPUMaterialNodes(localtree, mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-15 16:01:05 +02:00
|
|
|
gpu_material_ramp_texture_build(mat);
|
|
|
|
|
gpu_material_sky_texture_build(mat);
|
|
|
|
|
|
|
|
|
|
/* Use default material pass when possible. */
|
|
|
|
|
if (GPUPass *default_pass = pass_replacement_cb ? pass_replacement_cb(thunk, mat) : nullptr) {
|
|
|
|
|
mat->pass = default_pass;
|
|
|
|
|
GPU_pass_acquire(mat->pass);
|
2024-06-18 18:36:09 +02:00
|
|
|
/** WORKAROUND:
|
|
|
|
|
* The node tree code is never executed in default replaced passes,
|
|
|
|
|
* but the GPU validation will still complain if the node tree UBO is not bound.
|
|
|
|
|
* So we create a dummy UBO with (at least) the size of the default material one (192 bytes).
|
|
|
|
|
* We allocate 256 bytes to leave some room for future changes. */
|
|
|
|
|
mat->ubo = GPU_uniformbuf_create_ex(256, nullptr, "Dummy UBO");
|
2024-04-30 19:44:06 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2018-06-07 11:58:15 +02:00
|
|
|
/* Create source code and search pass cache for an already compiled version. */
|
2023-12-07 16:48:09 +01:00
|
|
|
mat->pass = GPU_generate_pass(mat, &mat->graph, engine, callback, thunk, false);
|
2024-05-15 16:01:05 +02:00
|
|
|
}
|
2019-05-16 16:43:41 +02:00
|
|
|
|
2024-05-15 16:01:05 +02:00
|
|
|
if (mat->pass == nullptr) {
|
|
|
|
|
/* We had a cache hit and the shader has already failed to compile. */
|
|
|
|
|
mat->status = GPU_MAT_FAILED;
|
|
|
|
|
gpu_node_graph_free(&mat->graph);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Determine whether we should generate an optimized variant of the graph.
|
|
|
|
|
* Heuristic is based on complexity of default material pass and shader node graph. */
|
|
|
|
|
if (GPU_pass_should_optimize(mat->pass)) {
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_READY);
|
2018-06-07 11:58:15 +02:00
|
|
|
}
|
2023-02-14 21:51:03 +01:00
|
|
|
|
2024-05-15 16:01:05 +02:00
|
|
|
GPUShader *sh = GPU_pass_shader_get(mat->pass);
|
|
|
|
|
if (sh != nullptr) {
|
|
|
|
|
/* We had a cache hit and the shader is already compiled. */
|
|
|
|
|
mat->status = GPU_MAT_SUCCESS;
|
2023-02-14 21:51:03 +01:00
|
|
|
|
2024-05-15 16:01:05 +02:00
|
|
|
if (mat->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) {
|
|
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
2024-05-15 16:01:05 +02:00
|
|
|
}
|
2023-02-14 21:51:03 +01:00
|
|
|
|
2024-05-15 16:01:05 +02:00
|
|
|
/* Generate optimized pass. */
|
|
|
|
|
if (mat->optimization_status == GPU_MAT_OPTIMIZATION_READY) {
|
2023-02-14 21:51:03 +01:00
|
|
|
#if ASYNC_OPTIMIZED_PASS_CREATION == 1
|
2024-05-15 16:01:05 +02:00
|
|
|
mat->optimized_pass = nullptr;
|
|
|
|
|
mat->optimize_pass_info.callback = callback;
|
|
|
|
|
mat->optimize_pass_info.thunk = thunk;
|
2023-02-14 21:51:03 +01:00
|
|
|
#else
|
2024-05-15 16:01:05 +02:00
|
|
|
mat->optimized_pass = GPU_generate_pass(mat, &mat->graph, engine, callback, thunk, true);
|
|
|
|
|
if (mat->optimized_pass == nullptr) {
|
|
|
|
|
/* Failed to create optimized pass. */
|
|
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GPUShader *optimized_sh = GPU_pass_shader_get(mat->optimized_pass);
|
|
|
|
|
if (optimized_sh != nullptr) {
|
|
|
|
|
/* Optimized shader already available. */
|
2023-02-14 21:51:03 +01:00
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
2024-05-15 16:01:05 +02:00
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SUCCESS);
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
2018-06-07 11:58:15 +02:00
|
|
|
}
|
2024-05-15 16:01:05 +02:00
|
|
|
#endif
|
2018-06-07 11:58:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Only free after GPU_pass_shader_get where GPUUniformBuf read data from the local tree. */
|
2024-08-19 20:27:37 +02:00
|
|
|
blender::bke::node_tree_free_local_tree(localtree);
|
2021-08-11 16:56:11 +10:00
|
|
|
BLI_assert(!localtree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
|
2018-08-01 19:25:58 +02:00
|
|
|
MEM_freeN(localtree);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-14 18:47:58 +02:00
|
|
|
/* Note that even if building the shader fails in some way, we still keep
|
2018-06-07 11:58:15 +02:00
|
|
|
* it to avoid trying to compile again and again, and simply do not use
|
2022-04-14 18:47:58 +02:00
|
|
|
* the actual shader on drawing. */
|
2023-07-27 14:16:58 +02:00
|
|
|
LinkData *link = static_cast<LinkData *>(MEM_callocN(sizeof(LinkData), "GPUMaterialLink"));
|
2017-04-27 22:27:09 +02:00
|
|
|
link->data = mat;
|
|
|
|
|
BLI_addtail(gpumaterials, link);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-27 22:27:09 +02:00
|
|
|
return mat;
|
|
|
|
|
}
|
2014-11-24 17:18:56 +01:00
|
|
|
|
2022-04-20 14:35:07 +02:00
|
|
|
void GPU_material_acquire(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
atomic_add_and_fetch_uint32(&mat->refcount, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GPU_material_release(GPUMaterial *mat)
|
|
|
|
|
{
|
2022-07-29 08:37:57 +02:00
|
|
|
GPU_material_free_single(mat);
|
2022-04-20 14:35:07 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-07 16:11:50 +02:00
|
|
|
static void gpu_material_finalize(GPUMaterial *mat, bool success)
|
2018-03-05 00:54:31 +01:00
|
|
|
{
|
2022-04-14 18:47:58 +02:00
|
|
|
mat->flag |= GPU_MATFLAG_UPDATED;
|
|
|
|
|
|
2019-08-01 17:32:42 +10:00
|
|
|
if (success) {
|
2019-06-05 13:06:11 -03:00
|
|
|
GPUShader *sh = GPU_pass_shader_get(mat->pass);
|
2023-07-27 14:16:58 +02:00
|
|
|
if (sh != nullptr) {
|
2023-02-14 21:51:03 +01:00
|
|
|
|
2023-08-05 13:46:22 +10:00
|
|
|
/** Perform asynchronous Render Pipeline State Object (PSO) compilation.
|
2023-02-14 21:51:03 +01:00
|
|
|
*
|
2023-08-05 13:46:22 +10:00
|
|
|
* Warm PSO cache within asynchronous compilation thread using default material as source.
|
2023-02-14 21:51:03 +01:00
|
|
|
* GPU_shader_warm_cache(..) performs the API-specific PSO compilation using the assigned
|
|
|
|
|
* parent shader's cached PSO descriptors as an input.
|
|
|
|
|
*
|
|
|
|
|
* This is only applied if the given material has a specified default reference
|
|
|
|
|
* material available, and the default material is already compiled.
|
|
|
|
|
*
|
|
|
|
|
* As PSOs do not always match for default shaders, we limit warming for PSO
|
|
|
|
|
* configurations to ensure compile time remains fast, as these first
|
2023-02-15 13:11:14 +11:00
|
|
|
* entries will be the most commonly used PSOs. As not all PSOs are necessarily
|
2023-02-22 16:35:48 +01:00
|
|
|
* required immediately, this limit should remain low (1-3 at most). */
|
2023-07-27 14:16:58 +02:00
|
|
|
if (!ELEM(mat->default_mat, nullptr, mat)) {
|
|
|
|
|
if (mat->default_mat->pass != nullptr) {
|
2023-02-14 21:51:03 +01:00
|
|
|
GPUShader *parent_sh = GPU_pass_shader_get(mat->default_mat->pass);
|
|
|
|
|
if (parent_sh) {
|
2023-02-22 16:35:48 +01:00
|
|
|
/* Skip warming if cached pass is identical to the default material. */
|
|
|
|
|
if (mat->default_mat->pass != mat->pass && parent_sh != sh) {
|
|
|
|
|
GPU_shader_set_parent(sh, parent_sh);
|
|
|
|
|
GPU_shader_warm_cache(sh, 1);
|
|
|
|
|
}
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Flag success. */
|
2019-06-05 13:06:11 -03:00
|
|
|
mat->status = GPU_MAT_SUCCESS;
|
2023-02-14 21:51:03 +01:00
|
|
|
if (mat->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) {
|
|
|
|
|
/* Only free node graph nodes if not required by secondary optimization pass. */
|
|
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
|
|
|
|
}
|
2019-06-05 13:06:11 -03:00
|
|
|
}
|
2022-06-06 16:57:50 +02:00
|
|
|
else {
|
|
|
|
|
mat->status = GPU_MAT_FAILED;
|
|
|
|
|
}
|
2018-03-05 00:54:31 +01:00
|
|
|
}
|
2018-03-13 03:49:04 +01:00
|
|
|
else {
|
|
|
|
|
mat->status = GPU_MAT_FAILED;
|
2018-06-07 11:58:15 +02:00
|
|
|
GPU_pass_release(mat->pass);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->pass = nullptr;
|
2020-02-14 10:47:20 +01:00
|
|
|
gpu_node_graph_free(&mat->graph);
|
2018-03-13 03:49:04 +01:00
|
|
|
}
|
2018-03-05 00:54:31 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-07 16:11:50 +02:00
|
|
|
void GPU_material_compile(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
bool success;
|
|
|
|
|
BLI_assert(ELEM(mat->status, GPU_MAT_QUEUED, GPU_MAT_CREATED));
|
|
|
|
|
BLI_assert(mat->pass);
|
|
|
|
|
|
|
|
|
|
/* NOTE: The shader may have already been compiled here since we are
|
|
|
|
|
* sharing GPUShader across GPUMaterials. In this case it's a no-op. */
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
success = GPU_pass_compile(mat->pass, mat->name);
|
|
|
|
|
#else
|
|
|
|
|
success = GPU_pass_compile(mat->pass, __func__);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
gpu_material_finalize(mat, success);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 19:18:07 +02:00
|
|
|
void GPU_material_async_compile(GPUMaterial *mat)
|
2024-06-07 16:11:50 +02:00
|
|
|
{
|
2024-07-25 19:18:07 +02:00
|
|
|
BLI_assert(ELEM(mat->status, GPU_MAT_QUEUED, GPU_MAT_CREATED));
|
|
|
|
|
BLI_assert(mat->pass);
|
2024-06-07 16:11:50 +02:00
|
|
|
#ifndef NDEBUG
|
2024-07-25 19:18:07 +02:00
|
|
|
const char *name = mat->name;
|
2024-06-07 16:11:50 +02:00
|
|
|
#else
|
2024-07-25 19:18:07 +02:00
|
|
|
const char *name = __func__;
|
2024-06-07 16:11:50 +02:00
|
|
|
#endif
|
2024-07-25 19:18:07 +02:00
|
|
|
GPU_pass_begin_async_compilation(mat->pass, name);
|
2024-06-07 16:11:50 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-25 19:18:07 +02:00
|
|
|
bool GPU_material_async_try_finalize(GPUMaterial *mat)
|
2024-06-07 16:11:50 +02:00
|
|
|
{
|
2024-07-25 19:18:07 +02:00
|
|
|
BLI_assert(ELEM(mat->status, GPU_MAT_QUEUED, GPU_MAT_CREATED));
|
|
|
|
|
if (GPU_pass_async_compilation_try_finalize(mat->pass)) {
|
|
|
|
|
gpu_material_finalize(mat, GPU_pass_shader_get(mat->pass) != nullptr);
|
|
|
|
|
return true;
|
2024-06-07 16:11:50 +02:00
|
|
|
}
|
2024-07-25 19:18:07 +02:00
|
|
|
return false;
|
2024-06-07 16:11:50 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-14 21:51:03 +01:00
|
|
|
void GPU_material_optimize(GPUMaterial *mat)
|
|
|
|
|
{
|
|
|
|
|
/* If shader is flagged for skipping optimization or has already been successfully
|
|
|
|
|
* optimized, skip. */
|
|
|
|
|
if (ELEM(mat->optimization_status, GPU_MAT_OPTIMIZATION_SKIP, GPU_MAT_OPTIMIZATION_SUCCESS)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If original shader has not been fully compiled, we are not
|
|
|
|
|
* ready to perform optimization. */
|
|
|
|
|
if (mat->status != GPU_MAT_SUCCESS) {
|
|
|
|
|
/* Reset optimization status. */
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_READY);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ASYNC_OPTIMIZED_PASS_CREATION == 1
|
|
|
|
|
/* If the optimized pass is not valid, first generate optimized pass.
|
|
|
|
|
* NOTE(Threading): Need to verify if GPU_generate_pass can cause side-effects, especially when
|
|
|
|
|
* used with "thunk". So far, this appears to work, and deferring optimized pass creation is more
|
|
|
|
|
* optimal, as these do not benefit from caching, due to baked constants. However, this could
|
2023-03-09 10:39:49 +11:00
|
|
|
* possibly be cause for concern for certain cases. */
|
2023-02-14 21:51:03 +01:00
|
|
|
if (!mat->optimized_pass) {
|
2023-12-07 16:48:09 +01:00
|
|
|
mat->optimized_pass = GPU_generate_pass(mat,
|
|
|
|
|
&mat->graph,
|
|
|
|
|
mat->engine,
|
|
|
|
|
mat->optimize_pass_info.callback,
|
|
|
|
|
mat->optimize_pass_info.thunk,
|
|
|
|
|
true);
|
2023-02-14 21:51:03 +01:00
|
|
|
BLI_assert(mat->optimized_pass);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (!mat->optimized_pass) {
|
|
|
|
|
/* Optimized pass has not been created, skip future optimization attempts. */
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bool success;
|
2023-07-27 14:16:58 +02:00
|
|
|
/* NOTE: The shader may have already been compiled here since we are
|
|
|
|
|
* sharing GPUShader across GPUMaterials. In this case it's a no-op. */
|
2023-02-14 21:51:03 +01:00
|
|
|
#ifndef NDEBUG
|
|
|
|
|
success = GPU_pass_compile(mat->optimized_pass, mat->name);
|
|
|
|
|
#else
|
|
|
|
|
success = GPU_pass_compile(mat->optimized_pass, __func__);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
GPUShader *sh = GPU_pass_shader_get(mat->optimized_pass);
|
2023-07-27 14:16:58 +02:00
|
|
|
if (sh != nullptr) {
|
2023-08-05 13:46:22 +10:00
|
|
|
/** Perform asynchronous Render Pipeline State Object (PSO) compilation.
|
2023-02-14 21:51:03 +01:00
|
|
|
*
|
2023-08-05 13:46:22 +10:00
|
|
|
* Warm PSO cache within asynchronous compilation thread for optimized materials.
|
2023-02-14 21:51:03 +01:00
|
|
|
* This setup assigns the original unoptimized shader as a "parent" shader
|
|
|
|
|
* for the optimized version. This then allows the associated GPU backend to
|
|
|
|
|
* compile PSOs within this asynchronous pass, using the identical PSO descriptors of the
|
|
|
|
|
* parent shader.
|
|
|
|
|
*
|
|
|
|
|
* This eliminates all run-time stuttering associated with material optimization and ensures
|
|
|
|
|
* realtime material editing and animation remains seamless, while retaining optimal realtime
|
|
|
|
|
* performance. */
|
|
|
|
|
GPUShader *parent_sh = GPU_pass_shader_get(mat->pass);
|
|
|
|
|
if (parent_sh) {
|
|
|
|
|
GPU_shader_set_parent(sh, parent_sh);
|
|
|
|
|
GPU_shader_warm_cache(sh, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mark as complete. */
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Optimized pass failed to compile. Disable any future optimization attempts. */
|
|
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Optimization pass generation failed. Disable future attempts to optimize. */
|
|
|
|
|
GPU_pass_release(mat->optimized_pass);
|
2023-07-27 14:16:58 +02:00
|
|
|
mat->optimized_pass = nullptr;
|
2023-02-14 21:51:03 +01:00
|
|
|
GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release node graph as no longer needed. */
|
|
|
|
|
gpu_node_graph_free_nodes(&mat->graph);
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-25 12:32:48 +02:00
|
|
|
void GPU_materials_free(Main *bmain)
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
{
|
2020-12-30 15:25:13 +01:00
|
|
|
LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
|
2014-11-24 17:18:56 +01:00
|
|
|
GPU_material_free(&ma->gpumaterial);
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
|
2020-12-30 15:25:13 +01:00
|
|
|
LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
|
2014-12-18 02:14:51 +01:00
|
|
|
GPU_material_free(&wo->gpumaterial);
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
2018-06-04 09:09:12 +02:00
|
|
|
|
2020-02-06 13:05:45 +01:00
|
|
|
BKE_material_defaults_free_gpu();
|
2011-09-09 11:55:38 +00:00
|
|
|
}
|
2022-07-29 08:37:57 +02:00
|
|
|
|
2023-12-07 16:48:09 +01:00
|
|
|
GPUMaterial *GPU_material_from_callbacks(eGPUMaterialEngine engine,
|
|
|
|
|
ConstructGPUMaterialFn construct_function_cb,
|
2022-07-29 08:37:57 +02:00
|
|
|
GPUCodegenCallbackFn generate_code_function_cb,
|
|
|
|
|
void *thunk)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate a new material and its material graph, and initialize its reference count. */
|
2023-07-27 14:16:58 +02:00
|
|
|
GPUMaterial *material = static_cast<GPUMaterial *>(
|
|
|
|
|
MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"));
|
2022-07-29 08:37:57 +02:00
|
|
|
material->graph.used_libraries = BLI_gset_new(
|
|
|
|
|
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries");
|
|
|
|
|
material->refcount = 1;
|
2023-02-14 21:51:03 +01:00
|
|
|
material->optimization_status = GPU_MAT_OPTIMIZATION_SKIP;
|
2023-07-27 14:16:58 +02:00
|
|
|
material->optimized_pass = nullptr;
|
|
|
|
|
material->default_mat = nullptr;
|
2023-12-07 16:48:09 +01:00
|
|
|
material->engine = engine;
|
2022-07-29 08:37:57 +02:00
|
|
|
|
|
|
|
|
/* Construct the material graph by adding and linking the necessary GPU material nodes. */
|
|
|
|
|
construct_function_cb(thunk, material);
|
|
|
|
|
|
|
|
|
|
/* Create and initialize the texture storing color bands used by Ramp and Curve nodes. */
|
|
|
|
|
gpu_material_ramp_texture_build(material);
|
|
|
|
|
|
|
|
|
|
/* Lookup an existing pass in the cache or generate a new one. */
|
2023-02-14 21:51:03 +01:00
|
|
|
material->pass = GPU_generate_pass(
|
2023-12-07 16:48:09 +01:00
|
|
|
material, &material->graph, material->engine, generate_code_function_cb, thunk, false);
|
2023-07-27 14:16:58 +02:00
|
|
|
material->optimized_pass = nullptr;
|
2022-07-29 08:37:57 +02:00
|
|
|
|
|
|
|
|
/* The pass already exists in the pass cache but its shader already failed to compile. */
|
2023-07-27 14:16:58 +02:00
|
|
|
if (material->pass == nullptr) {
|
2022-07-29 08:37:57 +02:00
|
|
|
material->status = GPU_MAT_FAILED;
|
|
|
|
|
gpu_node_graph_free(&material->graph);
|
|
|
|
|
return material;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The pass already exists in the pass cache and its shader is already compiled. */
|
|
|
|
|
GPUShader *shader = GPU_pass_shader_get(material->pass);
|
2023-07-27 14:16:58 +02:00
|
|
|
if (shader != nullptr) {
|
2022-07-29 08:37:57 +02:00
|
|
|
material->status = GPU_MAT_SUCCESS;
|
2023-02-14 21:51:03 +01:00
|
|
|
if (material->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) {
|
|
|
|
|
/* Only free node graph if not required by secondary optimization pass. */
|
|
|
|
|
gpu_node_graph_free_nodes(&material->graph);
|
|
|
|
|
}
|
2022-07-29 08:37:57 +02:00
|
|
|
return material;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The material was created successfully but still needs to be compiled. */
|
|
|
|
|
material->status = GPU_MAT_CREATED;
|
|
|
|
|
return material;
|
|
|
|
|
}
|