2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2005 Blender Foundation. All rights reserved. */
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
2023-02-12 17:40:13 +01:00
|
|
|
*
|
|
|
|
|
* A #GPUShader is a container for backend specific shader program.
|
2015-12-06 21:20:19 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2023-02-12 17:37:01 +01:00
|
|
|
#include "GPU_shader_builtin.h"
|
|
|
|
|
|
2015-12-06 21:20:19 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
struct GPUVertBuf;
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2022-01-17 14:45:22 +01:00
|
|
|
/** Opaque type hiding #blender::gpu::shader::ShaderCreateInfo */
|
|
|
|
|
typedef struct GPUShaderCreateInfo GPUShaderCreateInfo;
|
2021-02-05 16:23:34 +11:00
|
|
|
/** Opaque type hiding #blender::gpu::Shader */
|
2020-08-21 13:48:34 +02:00
|
|
|
typedef struct GPUShader GPUShader;
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2023-02-12 17:40:13 +01:00
|
|
|
/* Hardware limit is 16. Position attribute is always needed so we reduce to 15.
|
|
|
|
|
* This makes sure the GPUVertexFormat name buffer does not overflow. */
|
|
|
|
|
#define GPU_MAX_ATTR 15
|
|
|
|
|
|
|
|
|
|
/* Determined by the maximum uniform buffer size divided by chunk size. */
|
|
|
|
|
#define GPU_MAX_UNIFORM_ATTR 8
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Creation
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a shader using the given #GPUShaderCreateInfo.
|
|
|
|
|
* Can return a NULL pointer if compilation fails.
|
|
|
|
|
*/
|
|
|
|
|
GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a shader using a named #GPUShaderCreateInfo registered at startup.
|
|
|
|
|
* These are declared inside `*_info.hh` files using the `GPU_SHADER_CREATE_INFO()` macro.
|
|
|
|
|
* They are also expected to have been flagged using `do_static_compilation`.
|
|
|
|
|
* Can return a NULL pointer if compilation fails.
|
|
|
|
|
*/
|
|
|
|
|
GPUShader *GPU_shader_create_from_info_name(const char *info_name);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetch a named #GPUShaderCreateInfo registered at startup.
|
|
|
|
|
* These are declared inside `*_info.hh` files using the `GPU_SHADER_CREATE_INFO()` macro.
|
|
|
|
|
* Can return a NULL pointer if no match is found.
|
|
|
|
|
*/
|
|
|
|
|
const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Error checking for user created shaders.
|
|
|
|
|
* \return true is create info is valid.
|
|
|
|
|
*/
|
|
|
|
|
bool GPU_shader_create_info_check_error(const GPUShaderCreateInfo *_info, char r_error[128]);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Free
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
void GPU_shader_free(GPUShader *shader);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Binding
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the given shader as active shader for the active GPU context.
|
|
|
|
|
* It replaces any already bound shader.
|
|
|
|
|
* All following draw-calls and dispatches will use this shader.
|
|
|
|
|
* Uniform functions need to have the shader bound in order to work. (TODO: until we use
|
|
|
|
|
* glProgramUniform)
|
|
|
|
|
*/
|
|
|
|
|
void GPU_shader_bind(GPUShader *shader);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unbind the active shader.
|
|
|
|
|
* \note this is a no-op in release builds. But it make sense to actually do it in user land code
|
|
|
|
|
* to detect incorrect API usage.
|
|
|
|
|
*/
|
|
|
|
|
void GPU_shader_unbind(void);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the currently bound shader to the active GPU context.
|
|
|
|
|
* \return NULL pointer if no shader is bound of if no context is active.
|
|
|
|
|
*/
|
|
|
|
|
GPUShader *GPU_shader_get_bound(void);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Debugging introspection API.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
const char *GPU_shader_get_name(GPUShader *shader);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Uniform API.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns binding point location.
|
2023-02-12 22:52:27 +01:00
|
|
|
* Binding location are given to be set at shader compile time and immutable.
|
2023-02-12 17:40:13 +01:00
|
|
|
*/
|
2023-02-12 22:52:27 +01:00
|
|
|
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name);
|
|
|
|
|
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name);
|
|
|
|
|
int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name);
|
2023-02-12 17:40:13 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns uniform location.
|
|
|
|
|
* If cached, it is faster than querying the interface for each uniform assignment.
|
|
|
|
|
*/
|
|
|
|
|
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets a generic push constant (a.k.a. uniform).
|
|
|
|
|
* \a length and \a array_size should match the create info push_constant declaration.
|
|
|
|
|
*/
|
2023-02-12 23:39:48 +01:00
|
|
|
void GPU_shader_uniform_float_ex(
|
2023-02-12 17:40:13 +01:00
|
|
|
GPUShader *shader, int location, int length, int array_size, const float *value);
|
2023-02-12 23:39:48 +01:00
|
|
|
void GPU_shader_uniform_int_ex(
|
2023-02-12 17:40:13 +01:00
|
|
|
GPUShader *shader, int location, int length, int array_size, const int *value);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets a generic push constant (a.k.a. uniform).
|
|
|
|
|
* \a length and \a array_size should match the create info push_constant declaration.
|
|
|
|
|
* These functions need to have the shader bound in order to work. (TODO: until we use
|
|
|
|
|
* glProgramUniform)
|
|
|
|
|
*/
|
|
|
|
|
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value);
|
|
|
|
|
void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value);
|
|
|
|
|
void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value);
|
|
|
|
|
void GPU_shader_uniform_2f(GPUShader *sh, const char *name, float x, float y);
|
|
|
|
|
void GPU_shader_uniform_3f(GPUShader *sh, const char *name, float x, float y, float z);
|
|
|
|
|
void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, float z, float w);
|
|
|
|
|
void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]);
|
|
|
|
|
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]);
|
|
|
|
|
void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]);
|
|
|
|
|
void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]);
|
|
|
|
|
void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]);
|
|
|
|
|
void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]);
|
|
|
|
|
void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]);
|
|
|
|
|
void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Attribute API.
|
|
|
|
|
*
|
|
|
|
|
* Used to create #GPUVertexFormat from the shader's vertex input layout.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
unsigned int GPU_shader_get_attribute_len(const GPUShader *shader);
|
|
|
|
|
int GPU_shader_get_attribute(const GPUShader *shader, const char *name);
|
|
|
|
|
bool GPU_shader_get_attribute_info(const GPUShader *shader,
|
|
|
|
|
int attr_location,
|
|
|
|
|
char r_name[256],
|
|
|
|
|
int *r_type);
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Legacy API
|
|
|
|
|
*
|
|
|
|
|
* All of this section is deprecated and should be ported to use the API described above.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2019-01-23 14:15:43 +11:00
|
|
|
typedef enum eGPUShaderTFBType {
|
2018-05-16 12:47:15 +02:00
|
|
|
GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */
|
|
|
|
|
GPU_SHADER_TFB_POINTS = 1,
|
|
|
|
|
GPU_SHADER_TFB_LINES = 2,
|
|
|
|
|
GPU_SHADER_TFB_TRIANGLES = 3,
|
2019-01-23 14:15:43 +11:00
|
|
|
} eGPUShaderTFBType;
|
2018-05-16 12:47:15 +02:00
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
GPUShader *GPU_shader_create(const char *vertcode,
|
2016-01-10 07:12:10 +11:00
|
|
|
const char *fragcode,
|
2020-09-04 20:59:13 +02:00
|
|
|
const char *geomcode,
|
2016-01-10 07:12:10 +11:00
|
|
|
const char *libcode,
|
2018-08-02 18:31:38 +02:00
|
|
|
const char *defines,
|
2020-09-04 20:59:13 +02:00
|
|
|
const char *shname);
|
2021-05-26 16:49:17 +02:00
|
|
|
GPUShader *GPU_shader_create_compute(const char *computecode,
|
|
|
|
|
const char *libcode,
|
|
|
|
|
const char *defines,
|
|
|
|
|
const char *shname);
|
2020-09-04 20:59:13 +02:00
|
|
|
GPUShader *GPU_shader_create_from_python(const char *vertcode,
|
2020-04-14 20:44:45 +02:00
|
|
|
const char *fragcode,
|
2020-09-04 20:59:13 +02:00
|
|
|
const char *geomcode,
|
2020-04-14 20:44:45 +02:00
|
|
|
const char *libcode,
|
2021-09-13 16:12:12 +10:00
|
|
|
const char *defines,
|
|
|
|
|
const char *name);
|
2020-09-04 20:59:13 +02:00
|
|
|
GPUShader *GPU_shader_create_ex(const char *vertcode,
|
2016-01-10 07:12:10 +11:00
|
|
|
const char *fragcode,
|
2020-09-04 20:59:13 +02:00
|
|
|
const char *geomcode,
|
2021-05-26 16:49:17 +02:00
|
|
|
const char *computecode,
|
2016-01-10 07:12:10 +11:00
|
|
|
const char *libcode,
|
|
|
|
|
const char *defines,
|
2022-01-07 11:38:08 +11:00
|
|
|
eGPUShaderTFBType tf_type,
|
2018-05-16 12:47:15 +02:00
|
|
|
const char **tf_names,
|
2022-01-07 11:38:08 +11:00
|
|
|
int tf_count,
|
2020-09-04 20:59:13 +02:00
|
|
|
const char *shname);
|
2021-09-13 16:12:12 +10:00
|
|
|
|
2021-12-09 20:01:47 +11:00
|
|
|
/**
|
|
|
|
|
* Returns true if transform feedback was successfully enabled.
|
|
|
|
|
*/
|
2020-08-14 15:20:35 +02:00
|
|
|
bool GPU_shader_transform_feedback_enable(GPUShader *shader, struct GPUVertBuf *vertbuf);
|
2018-05-16 12:47:15 +02:00
|
|
|
void GPU_shader_transform_feedback_disable(GPUShader *shader);
|
|
|
|
|
|
2023-02-14 21:51:03 +01:00
|
|
|
/**
|
|
|
|
|
* Shader cache warming.
|
|
|
|
|
* For each shader, rendering APIs perform a two-step compilation:
|
|
|
|
|
*
|
|
|
|
|
* * The first stage is Front-End compilation which only needs to be performed once, and generates
|
|
|
|
|
* a portable intermediate representation. This happens during `gpu::Shader::finalize()`.
|
|
|
|
|
*
|
|
|
|
|
* * The second is Back-End compilation which compiles a device-specific executable shader
|
|
|
|
|
* program. This compilation requires some contextual pipeline state which is baked into the
|
|
|
|
|
* executable shader source, producing a Pipeline State Object (PSO). In OpenGL, backend
|
|
|
|
|
* compilation happens in the background, within the driver, but can still incur runtime stutters.
|
|
|
|
|
* In Metal/Vulkan, PSOs are compiled explicitly. These are currently resolved within the backend
|
|
|
|
|
* based on the current pipeline state and can incur runtime stalls when they occur.
|
|
|
|
|
*
|
|
|
|
|
* Shader Cache warming uses the specified parent shader set using `GPU_shader_set_parent(..)` as a
|
|
|
|
|
* template reference for pre-compiling Render Pipeline State Objects (PSOs) outside of the main
|
|
|
|
|
* render pipeline.
|
|
|
|
|
*
|
|
|
|
|
* PSOs require descriptors containing information on the render state for a given shader, which
|
|
|
|
|
* includes input vertex data layout and output pixel formats, along with some state such as
|
|
|
|
|
* blend mode and colour output masks. As this state information is usually consistent between
|
|
|
|
|
* similar draws, we can assign a parent shader and use this shader's cached pipeline state's to
|
|
|
|
|
* prime compilations.
|
|
|
|
|
*
|
|
|
|
|
* Shaders do not necessarily have to be similar in functionality to be used as a parent, so long
|
|
|
|
|
* as the GPUVertFormt and GPUFrameBuffer which they are used with remain the same. Other bindings
|
|
|
|
|
* such as textures, uniforms and UBOs are all assigned independently as dynamic state.
|
|
|
|
|
*
|
|
|
|
|
* This function should be called asynchronously, mitigating the impact of run-time stuttering from
|
|
|
|
|
* dynamic compilation of PSOs during normal rendering.
|
|
|
|
|
*
|
|
|
|
|
* \param: shader: The shader whose cache to warm.
|
|
|
|
|
* \param limit: The maximum number of PSOs to compile within a call. Specifying
|
|
|
|
|
* a limit <= 0 will compile a PSO for all cached PSOs in the parent shader. */
|
|
|
|
|
void GPU_shader_warm_cache(GPUShader *shader, int limit);
|
|
|
|
|
|
|
|
|
|
/* We expect the parent shader to be compiled and already have some cached PSOs when being assigned
|
|
|
|
|
* as a reference. Ensure the parent shader still exists when `GPU_shader_cache_warm(..)` is
|
|
|
|
|
* called. */
|
|
|
|
|
void GPU_shader_set_parent(GPUShader *shader, GPUShader *parent);
|
|
|
|
|
|
2021-12-09 20:01:47 +11:00
|
|
|
/** DEPRECATED: Kept only because of BGL API. */
|
2017-02-07 11:20:15 +01:00
|
|
|
int GPU_shader_get_program(GPUShader *shader);
|
2017-03-02 21:46:54 -05:00
|
|
|
|
2023-02-12 17:40:13 +01:00
|
|
|
/**
|
|
|
|
|
* Indexed commonly used uniform name for faster lookup into the uniform cache.
|
|
|
|
|
*/
|
2020-08-20 13:05:22 +02:00
|
|
|
typedef enum {
|
|
|
|
|
GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */
|
|
|
|
|
GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */
|
|
|
|
|
GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */
|
|
|
|
|
GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */
|
|
|
|
|
GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */
|
|
|
|
|
GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */
|
|
|
|
|
|
|
|
|
|
GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */
|
|
|
|
|
GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */
|
|
|
|
|
GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */
|
|
|
|
|
GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */
|
|
|
|
|
GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */
|
|
|
|
|
|
|
|
|
|
GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
|
|
|
|
|
GPU_UNIFORM_ORCO, /* vec4 OrcoTexCoFactors[] */
|
|
|
|
|
GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */
|
|
|
|
|
|
|
|
|
|
GPU_UNIFORM_COLOR, /* vec4 color */
|
|
|
|
|
GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */
|
|
|
|
|
GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */
|
|
|
|
|
GPU_UNIFORM_RESOURCE_ID, /* int resourceId */
|
|
|
|
|
GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */
|
|
|
|
|
} GPUUniformBuiltin;
|
2023-02-12 17:40:13 +01:00
|
|
|
#define GPU_NUM_UNIFORMS (GPU_UNIFORM_SRGB_TRANSFORM + 1)
|
2020-08-20 13:05:22 +02:00
|
|
|
|
2023-02-14 10:29:48 +11:00
|
|
|
/**
|
|
|
|
|
* TODO: To be moved as private API. Not really used outside of gpu_matrix.cc and doesn't really
|
|
|
|
|
* offer a noticeable performance boost.
|
|
|
|
|
*/
|
2023-02-12 17:40:13 +01:00
|
|
|
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
|
|
|
|
|
|
|
|
|
|
/** DEPRECATED: Use hardcoded buffer location instead. */
|
2020-08-20 13:05:22 +02:00
|
|
|
typedef enum {
|
|
|
|
|
GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */
|
|
|
|
|
GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */
|
|
|
|
|
GPU_UNIFORM_BLOCK_INFO, /* infoBlock */
|
2023-02-12 17:40:13 +01:00
|
|
|
|
2022-01-26 12:46:37 +01:00
|
|
|
GPU_UNIFORM_BLOCK_DRW_VIEW,
|
|
|
|
|
GPU_UNIFORM_BLOCK_DRW_MODEL,
|
|
|
|
|
GPU_UNIFORM_BLOCK_DRW_INFOS,
|
2022-10-07 00:06:27 +02:00
|
|
|
GPU_UNIFORM_BLOCK_DRW_CLIPPING,
|
2020-08-20 13:05:22 +02:00
|
|
|
|
|
|
|
|
GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */
|
|
|
|
|
} GPUUniformBlockBuiltin;
|
|
|
|
|
|
2023-02-12 17:40:13 +01:00
|
|
|
/** DEPRECATED: Use hardcoded buffer location instead. */
|
|
|
|
|
int GPU_shader_get_builtin_block(GPUShader *shader, int builtin);
|
|
|
|
|
|
2021-12-09 20:01:47 +11:00
|
|
|
/** DEPRECATED: Kept only because of Python GPU API. */
|
2017-02-07 11:20:15 +01:00
|
|
|
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2023-02-12 17:40:13 +01: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
|
|
|
|
2015-12-06 21:20:19 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|