Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-01-26 23:57:44 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-01-27 00:03:58 +0300
commit4226c484bdbe7336f1221094916fcdfb12850034 (patch)
tree33428e72be40105c222ca77935ee1554b702facc /source/blender/gpu/intern
parent55a6a8900aec81e94f4d82401d6051e3b5507c0e (diff)
parentaf87b6d8cb75d9d625378dee25d726a0d55f75c6 (diff)
Merge branch 'draw-viewport-data' into eevee-rewrite
# Conflicts: # release/scripts/startup/bl_ui/properties_data_camera.py # source/blender/blenkernel/BKE_camera.h # source/blender/blenkernel/BKE_node.h # source/blender/blenkernel/intern/camera.c # source/blender/blenlib/BLI_float2.hh # source/blender/blenlib/BLI_float3.hh # source/blender/blenlib/BLI_float4.hh # source/blender/blenlib/BLI_math_geom.h # source/blender/blenlib/intern/math_geom.c # source/blender/draw/CMakeLists.txt # source/blender/draw/engines/basic/basic_engine.c # source/blender/draw/engines/eevee/eevee_cryptomatte.c # source/blender/draw/engines/eevee/eevee_effects.c # source/blender/draw/engines/eevee/eevee_engine.c # source/blender/draw/engines/eevee/eevee_lightcache.c # source/blender/draw/engines/eevee/eevee_lightcache.h # source/blender/draw/engines/eevee/eevee_lightprobes.c # source/blender/draw/engines/eevee/eevee_lights.c # source/blender/draw/engines/eevee/eevee_materials.c # source/blender/draw/engines/eevee/eevee_motion_blur.c # source/blender/draw/engines/eevee/eevee_occlusion.c # source/blender/draw/engines/eevee/eevee_private.h # source/blender/draw/engines/eevee/eevee_render.c # source/blender/draw/engines/eevee/eevee_renderpasses.c # source/blender/draw/engines/eevee/eevee_sampling.c # source/blender/draw/engines/eevee/eevee_screen_raytrace.c # source/blender/draw/engines/eevee/eevee_shaders.c # source/blender/draw/engines/eevee/eevee_shadows.c # source/blender/draw/engines/eevee/eevee_shadows_cube.c # source/blender/draw/engines/eevee/eevee_temporal_sampling.c # source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl # source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl # source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl # source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl # source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl # source/blender/draw/engines/eevee/shaders/effect_dof_reduce_frag.glsl # source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl # source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl # source/blender/draw/engines/eevee/shaders/random_lib.glsl # source/blender/draw/engines/eevee/shaders/shadow_vert.glsl # source/blender/draw/engines/eevee/shaders/surface_lib.glsl # source/blender/draw/engines/eevee/shaders/surface_vert.glsl # source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl # source/blender/draw/engines/external/external_engine.c # source/blender/draw/engines/gpencil/gpencil_engine.c # source/blender/draw/engines/image/image_engine.c # source/blender/draw/engines/overlay/overlay_engine.c # source/blender/draw/engines/select/select_engine.c # source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl # source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl # source/blender/draw/engines/workbench/workbench_engine.c # source/blender/draw/engines/workbench/workbench_shader.c # source/blender/draw/intern/DRW_render.h # source/blender/draw/intern/draw_debug.h # source/blender/draw/intern/draw_manager_data.c # source/blender/draw/intern/draw_manager_exec.c # source/blender/draw/intern/draw_view_data.h # source/blender/gpu/CMakeLists.txt # source/blender/gpu/GPU_material.h # source/blender/gpu/GPU_shader.h # source/blender/gpu/GPU_state.h # source/blender/gpu/GPU_vertex_buffer.h # source/blender/gpu/intern/gpu_codegen.c # source/blender/gpu/intern/gpu_material.c # source/blender/gpu/intern/gpu_material_library.h # source/blender/gpu/intern/gpu_node_graph.c # source/blender/gpu/intern/gpu_texture_private.hh # source/blender/gpu/intern/gpu_vertex_buffer.cc # source/blender/gpu/opengl/gl_shader.cc # source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl # source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl # source/blender/nodes/shader/node_shader_tree.cc # source/blender/nodes/shader/nodes/node_shader_background.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_hair.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_hair_principled.c # source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c # source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc # source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc # source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc # source/blender/nodes/shader/nodes/node_shader_emission.cc # source/blender/nodes/shader/nodes/node_shader_holdout.cc # source/blender/nodes/shader/nodes/node_shader_output_material.cc # source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c # source/blender/nodes/shader/nodes/node_shader_tex_coord.cc # source/blender/nodes/shader/nodes/node_shader_vector_transform.cc # source/blender/nodes/shader/nodes/node_shader_volume_absorption.cc # source/blender/nodes/shader/nodes/node_shader_volume_principled.cc # source/blender/nodes/shader/nodes/node_shader_volume_scatter.cc # source/blender/render/RE_pipeline.h # source/blender/render/intern/initrender.c
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_backend.hh14
-rw-r--r--source/blender/gpu/intern/gpu_batch.cc14
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c2
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_batch_utils.c9
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c15
-rw-r--r--source/blender/gpu/intern/gpu_capabilities.cc47
-rw-r--r--source/blender/gpu/intern/gpu_capabilities_private.hh4
-rw-r--r--source/blender/gpu/intern/gpu_context.cc19
-rw-r--r--source/blender/gpu/intern/gpu_context_private.hh14
-rw-r--r--source/blender/gpu/intern/gpu_debug.cc7
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc45
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer_private.hh8
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc8
-rw-r--r--source/blender/gpu/intern/gpu_immediate_private.hh8
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c206
-rw-r--r--source/blender/gpu/intern/gpu_index_buffer.cc21
-rw-r--r--source/blender/gpu/intern/gpu_index_buffer_private.hh10
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c8
-rw-r--r--source/blender/gpu/intern/gpu_material.c16
-rw-r--r--source/blender/gpu/intern/gpu_material_library.c16
-rw-r--r--source/blender/gpu/intern/gpu_material_library.h2
-rw-r--r--source/blender/gpu/intern/gpu_matrix.cc26
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c113
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h9
-rw-r--r--source/blender/gpu/intern/gpu_platform.cc11
-rw-r--r--source/blender/gpu/intern/gpu_platform_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_query.hh4
-rw-r--r--source/blender/gpu/intern/gpu_select.c101
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c45
-rw-r--r--source/blender/gpu/intern/gpu_select_private.h5
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.cc6
-rw-r--r--source/blender/gpu/intern/gpu_shader.cc230
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder.cc102
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder_stubs.cc258
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c350
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc263
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh622
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info_private.hh46
-rw-r--r--source/blender/gpu/intern/gpu_shader_dependency.cc388
-rw-r--r--source/blender/gpu/intern/gpu_shader_dependency_private.h44
-rw-r--r--source/blender/gpu/intern/gpu_shader_info_baked.cc24
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.cc9
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.hh53
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.hh34
-rw-r--r--source/blender/gpu/intern/gpu_shader_shared_utils.h116
-rw-r--r--source/blender/gpu/intern/gpu_state.cc11
-rw-r--r--source/blender/gpu/intern/gpu_state_private.hh10
-rw-r--r--source/blender/gpu/intern/gpu_texture.cc22
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh82
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer.cc8
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.cc37
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer_private.hh26
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc27
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c35
56 files changed, 2720 insertions, 896 deletions
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index 73792215569..00645f34173 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -42,24 +42,24 @@ class VertBuf;
class GPUBackend {
public:
- virtual ~GPUBackend(){};
+ virtual ~GPUBackend() = default;
- static GPUBackend *get(void);
+ static GPUBackend *get();
- virtual void samplers_update(void) = 0;
+ virtual void samplers_update() = 0;
virtual void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) = 0;
virtual Context *context_alloc(void *ghost_window) = 0;
- virtual Batch *batch_alloc(void) = 0;
+ virtual Batch *batch_alloc() = 0;
virtual DrawList *drawlist_alloc(int list_length) = 0;
virtual FrameBuffer *framebuffer_alloc(const char *name) = 0;
- virtual IndexBuf *indexbuf_alloc(void) = 0;
- virtual QueryPool *querypool_alloc(void) = 0;
+ virtual IndexBuf *indexbuf_alloc() = 0;
+ virtual QueryPool *querypool_alloc() = 0;
virtual Shader *shader_alloc(const char *name) = 0;
virtual Texture *texture_alloc(const char *name) = 0;
virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
- virtual VertBuf *vertbuf_alloc(void) = 0;
+ virtual VertBuf *vertbuf_alloc() = 0;
};
} // namespace gpu
diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc
index 0e5c7900da9..2874dea775f 100644
--- a/source/blender/gpu/intern/gpu_batch.cc
+++ b/source/blender/gpu/intern/gpu_batch.cc
@@ -50,7 +50,7 @@ using namespace blender::gpu;
/** \name Creation & Deletion
* \{ */
-GPUBatch *GPU_batch_calloc(void)
+GPUBatch *GPU_batch_calloc()
{
GPUBatch *batch = GPUBackend::get()->batch_alloc();
memset(batch, 0, sizeof(*batch));
@@ -90,7 +90,6 @@ void GPU_batch_init_ex(GPUBatch *batch,
batch->shader = nullptr;
}
-/* This will share the VBOs with the new batch. */
void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src)
{
GPU_batch_init_ex(
@@ -137,7 +136,6 @@ void GPU_batch_discard(GPUBatch *batch)
/** \name Buffers Management
* \{ */
-/* NOTE: Override ONLY the first instance vbo (and free them if owned). */
void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
{
BLI_assert(inst);
@@ -151,7 +149,6 @@ void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
SET_FLAG_FROM_TEST(batch->flag, own_vbo, GPU_BATCH_OWNS_INST_VBO);
}
-/* NOTE: Override any previously assigned elem (and free it if owned). */
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
{
BLI_assert(elem);
@@ -188,7 +185,6 @@ int GPU_batch_instbuf_add_ex(GPUBatch *batch, GPUVertBuf *insts, bool own_vbo)
return -1;
}
-/* Returns the index of verts in the batch. */
int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
{
BLI_assert(verts);
@@ -243,7 +239,6 @@ void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count)
GPU_batch_draw_advanced(batch, v_first, v_count, 0, 0);
}
-/* Draw multiple instance of a batch without having any instance attributes. */
void GPU_batch_draw_instanced(GPUBatch *batch, int i_count)
{
BLI_assert(batch->inst[0] == nullptr);
@@ -301,9 +296,6 @@ void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
GPU_batch_program_set_builtin_with_config(batch, shader_id, GPU_SHADER_CFG_DEFAULT);
}
-/* Bind program bound to IMM to the batch.
- * XXX Use this with much care. Drawing with the GPUBatch API is not compatible with IMM.
- * DO NOT DRAW WITH THE BATCH BEFORE CALLING immUnbindProgram. */
void GPU_batch_program_set_imm_shader(GPUBatch *batch)
{
GPU_batch_set_shader(batch, immGetShader());
@@ -315,12 +307,12 @@ void GPU_batch_program_set_imm_shader(GPUBatch *batch)
/** \name Init/Exit
* \{ */
-void gpu_batch_init(void)
+void gpu_batch_init()
{
gpu_batch_presets_init();
}
-void gpu_batch_exit(void)
+void gpu_batch_exit()
{
gpu_batch_presets_exit();
}
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index 6a1645a71d8..b97378ad638 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -154,7 +154,6 @@ GPUBatch *GPU_batch_preset_sphere_wire(int lod)
/** \name Create Sphere (3D)
* \{ */
-/* Replacement for gluSphere */
GPUBatch *gpu_batch_sphere(int lat_res, int lon_res)
{
const float lon_inc = 2 * M_PI / lon_res;
@@ -331,7 +330,6 @@ GPUBatch *GPU_batch_preset_panel_drag_widget(const float pixelsize,
return g_presets_2d.batch.panel_drag_widget;
}
-/* To be used with procedural placement inside shader. */
GPUBatch *GPU_batch_preset_quad(void)
{
if (!g_presets_2d.batch.quad) {
diff --git a/source/blender/gpu/intern/gpu_batch_private.hh b/source/blender/gpu/intern/gpu_batch_private.hh
index eed96864f20..4c2f221e9b6 100644
--- a/source/blender/gpu/intern/gpu_batch_private.hh
+++ b/source/blender/gpu/intern/gpu_batch_private.hh
@@ -47,7 +47,7 @@ class Batch : public GPUBatch {
virtual void draw(int v_first, int v_count, int i_first, int i_count) = 0;
/* Convenience casts. */
- IndexBuf *elem_(void) const
+ IndexBuf *elem_() const
{
return unwrap(elem);
}
diff --git a/source/blender/gpu/intern/gpu_batch_utils.c b/source/blender/gpu/intern/gpu_batch_utils.c
index e2d03d27035..a381df5974a 100644
--- a/source/blender/gpu/intern/gpu_batch_utils.c
+++ b/source/blender/gpu/intern/gpu_batch_utils.c
@@ -33,15 +33,6 @@
/** \name Polygon Creation (2D)
* \{ */
-/**
- * Creates triangles from a byte-array of polygons.
- *
- * See 'make_shape_2d_from_blend.py' utility to create data to pass to this function.
- *
- * \param polys_flat: Pairs of X, Y coordinates (repeating to signify closing the polygon).
- * \param polys_flat_len: Length of the array (must be an even number).
- * \param rect: Optional region to map the byte 0..255 coords to. When not set use -1..1.
- */
GPUBatch *GPU_batch_tris_from_poly_2d_encoded(const uchar *polys_flat,
uint polys_flat_len,
const rctf *rect)
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 43483916236..dd53bea4eca 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -57,6 +57,10 @@
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
+/* -------------------------------------------------------------------- */
+/** \name Private Types
+ * \{ */
+
struct GPU_PBVH_Buffers {
GPUIndexBuf *index_buf, *index_buf_fast;
GPUIndexBuf *index_lines_buf, *index_lines_buf_fast;
@@ -204,9 +208,9 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE);
}
-/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MVert *mvert,
+ const float (*vert_normals)[3],
const float *vmask,
const MLoopCol *vcol,
const int *sculpt_face_sets,
@@ -289,7 +293,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
if (buffers->smooth) {
- copy_v3_v3_short(no, v->no);
+ normal_float_to_short_v3(no, vert_normals[vtri[j]]);
}
copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
@@ -337,7 +341,6 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->mvert = mvert;
}
-/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const MPoly *mpoly,
const MLoop *mloop,
const MLoopTri *looptri,
@@ -584,7 +587,6 @@ void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
}
}
-/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
SubdivCCG *subdiv_ccg,
CCGElem **grids,
@@ -764,7 +766,6 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->show_overlay = !empty_mask || !default_face_set;
}
-/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden)
{
GPU_PBVH_Buffers *buffers;
@@ -878,9 +879,6 @@ void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
}
}
-/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
- * shading, an element index buffer.
- * Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
BMesh *bm,
GSet *bm_faces,
@@ -1048,7 +1046,6 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
/** \name Generic
* \{ */
-/* Threaded - do not call any functions that use OpenGL calls! */
GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
{
GPU_PBVH_Buffers *buffers;
diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc
index c6e9dc210cb..f12fd96d1ba 100644
--- a/source/blender/gpu/intern/gpu_capabilities.cc
+++ b/source/blender/gpu/intern/gpu_capabilities.cc
@@ -44,7 +44,7 @@ using namespace blender::gpu;
/** \name Capabilities
* \{ */
-int GPU_max_texture_size(void)
+int GPU_max_texture_size()
{
return GCaps.max_texture_size;
}
@@ -57,27 +57,27 @@ int GPU_texture_size_with_limit(int res, bool limit_gl_texture_size)
return min_ii(reslimit, res);
}
-int GPU_max_texture_layers(void)
+int GPU_max_texture_layers()
{
return GCaps.max_texture_layers;
}
-int GPU_max_textures_vert(void)
+int GPU_max_textures_vert()
{
return GCaps.max_textures_vert;
}
-int GPU_max_textures_geom(void)
+int GPU_max_textures_geom()
{
return GCaps.max_textures_geom;
}
-int GPU_max_textures_frag(void)
+int GPU_max_textures_frag()
{
return GCaps.max_textures_frag;
}
-int GPU_max_textures(void)
+int GPU_max_textures()
{
return GCaps.max_textures;
}
@@ -92,37 +92,37 @@ int GPU_max_work_group_size(int index)
return GCaps.max_work_group_size[index];
}
-int GPU_max_uniforms_vert(void)
+int GPU_max_uniforms_vert()
{
return GCaps.max_uniforms_vert;
}
-int GPU_max_uniforms_frag(void)
+int GPU_max_uniforms_frag()
{
return GCaps.max_uniforms_frag;
}
-int GPU_max_batch_indices(void)
+int GPU_max_batch_indices()
{
return GCaps.max_batch_indices;
}
-int GPU_max_batch_vertices(void)
+int GPU_max_batch_vertices()
{
return GCaps.max_batch_vertices;
}
-int GPU_max_vertex_attribs(void)
+int GPU_max_vertex_attribs()
{
return GCaps.max_vertex_attribs;
}
-int GPU_max_varying_floats(void)
+int GPU_max_varying_floats()
{
return GCaps.max_varying_floats;
}
-int GPU_extensions_len(void)
+int GPU_extensions_len()
{
return GCaps.extensions_len;
}
@@ -132,43 +132,43 @@ const char *GPU_extension_get(int i)
return GCaps.extension_get ? GCaps.extension_get(i) : "\0";
}
-bool GPU_mip_render_workaround(void)
+bool GPU_mip_render_workaround()
{
return GCaps.mip_render_workaround;
}
-bool GPU_depth_blitting_workaround(void)
+bool GPU_depth_blitting_workaround()
{
return GCaps.depth_blitting_workaround;
}
-bool GPU_use_main_context_workaround(void)
+bool GPU_use_main_context_workaround()
{
return GCaps.use_main_context_workaround;
}
-bool GPU_crappy_amd_driver(void)
+bool GPU_crappy_amd_driver()
{
/* Currently are the same drivers with the `unused_fb_slot` problem. */
return GCaps.broken_amd_driver;
}
-bool GPU_use_hq_normals_workaround(void)
+bool GPU_use_hq_normals_workaround()
{
return GCaps.use_hq_normals_workaround;
}
-bool GPU_compute_shader_support(void)
+bool GPU_compute_shader_support()
{
return GCaps.compute_shader_support;
}
-bool GPU_shader_storage_buffer_objects_support(void)
+bool GPU_shader_storage_buffer_objects_support()
{
return GCaps.shader_storage_buffer_objects_support;
}
-bool GPU_shader_image_load_store_support(void)
+bool GPU_shader_image_load_store_support()
{
return GCaps.shader_image_load_store_support;
}
@@ -179,7 +179,7 @@ bool GPU_shader_image_load_store_support(void)
/** \name Memory statistics
* \{ */
-bool GPU_mem_stats_supported(void)
+bool GPU_mem_stats_supported()
{
return GCaps.mem_stats_support;
}
@@ -189,8 +189,7 @@ void GPU_mem_stats_get(int *totalmem, int *freemem)
Context::get()->memory_statistics_get(totalmem, freemem);
}
-/* Return support for the active context + window. */
-bool GPU_stereo_quadbuffer_support(void)
+bool GPU_stereo_quadbuffer_support()
{
return Context::get()->front_right != nullptr;
}
diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh
index 95cf7fd335d..1f94b6715f1 100644
--- a/source/blender/gpu/intern/gpu_capabilities_private.hh
+++ b/source/blender/gpu/intern/gpu_capabilities_private.hh
@@ -29,10 +29,10 @@ namespace blender::gpu {
/**
* This includes both hardware capabilities & workarounds.
- * Try to limit these to the implementation codebase (i.e.: gpu/opengl/).
+ * Try to limit these to the implementation code-base (i.e.: `gpu/opengl/`).
* Only add workarounds here if they are common to all implementation or
* if you need access to it outside of the GPU module.
- * Same goes for capabilities (i.e.: texture size)
+ * Same goes for capabilities (i.e.: texture size).
*/
struct GPUCapabilities {
int max_texture_size = 0;
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 943a6151ced..98714269402 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -109,7 +109,6 @@ GPUContext *GPU_context_create(void *ghost_window)
return wrap(ctx);
}
-/* to be called after GPU_context_active_set(ctx_to_destroy) */
void GPU_context_discard(GPUContext *ctx_)
{
Context *ctx = unwrap(ctx_);
@@ -117,7 +116,6 @@ void GPU_context_discard(GPUContext *ctx_)
active_ctx = nullptr;
}
-/* ctx can be NULL */
void GPU_context_active_set(GPUContext *ctx_)
{
Context *ctx = unwrap(ctx_);
@@ -133,7 +131,7 @@ void GPU_context_active_set(GPUContext *ctx_)
}
}
-GPUContext *GPU_context_active_get(void)
+GPUContext *GPU_context_active_get()
{
return wrap(Context::get());
}
@@ -146,12 +144,12 @@ GPUContext *GPU_context_active_get(void)
static std::mutex main_context_mutex;
-void GPU_context_main_lock(void)
+void GPU_context_main_lock()
{
main_context_mutex.lock();
}
-void GPU_context_main_unlock(void)
+void GPU_context_main_unlock()
{
main_context_mutex.unlock();
}
@@ -180,7 +178,7 @@ void GPU_backend_init(eGPUBackendType backend_type)
}
}
-void GPU_backend_exit(void)
+void GPU_backend_exit()
{
/* TODO: assert no resource left. Currently UI textures are still not freed in their context
* correctly. */
@@ -188,6 +186,15 @@ void GPU_backend_exit(void)
g_backend = nullptr;
}
+eGPUBackendType GPU_backend_get_type()
+{
+ if (g_backend && dynamic_cast<GLBackend *>(g_backend) != nullptr) {
+ return GPU_BACKEND_OPENGL;
+ }
+
+ return GPU_BACKEND_NONE;
+}
+
GPUBackend *GPUBackend::get()
{
return g_backend;
diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh
index 82753b44c51..d99555b3bf5 100644
--- a/source/blender/gpu/intern/gpu_context_private.hh
+++ b/source/blender/gpu/intern/gpu_context_private.hh
@@ -75,22 +75,22 @@ class Context {
Context();
virtual ~Context();
- static Context *get(void);
+ static Context *get();
- virtual void activate(void) = 0;
- virtual void deactivate(void) = 0;
+ virtual void activate() = 0;
+ virtual void deactivate() = 0;
/* Will push all pending commands to the GPU. */
- virtual void flush(void) = 0;
+ virtual void flush() = 0;
/* Will wait until the GPU has finished executing all command. */
- virtual void finish(void) = 0;
+ virtual void finish() = 0;
virtual void memory_statistics_get(int *total_mem, int *free_mem) = 0;
virtual void debug_group_begin(const char *, int){};
- virtual void debug_group_end(void){};
+ virtual void debug_group_end(){};
- bool is_active_on_thread(void);
+ bool is_active_on_thread();
};
/* Syntactic sugar. */
diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc
index 2d9fb7822ae..85cec67d2a7 100644
--- a/source/blender/gpu/intern/gpu_debug.cc
+++ b/source/blender/gpu/intern/gpu_debug.cc
@@ -45,7 +45,7 @@ void GPU_debug_group_begin(const char *name)
ctx->debug_group_begin(name, stack.size());
}
-void GPU_debug_group_end(void)
+void GPU_debug_group_end()
{
if (!(G.debug & G_DEBUG_GPU)) {
return;
@@ -55,10 +55,6 @@ void GPU_debug_group_end(void)
ctx->debug_group_end();
}
-/**
- * Return a formatted string showing the current group hierarchy in this format:
- * "Group1 > Group 2 > Group3 > ... > GroupN : "
- */
void GPU_debug_get_groups_names(int name_buf_len, char *r_name_buf)
{
Context *ctx = Context::get();
@@ -77,7 +73,6 @@ void GPU_debug_get_groups_names(int name_buf_len, char *r_name_buf)
r_name_buf[sz - 3] = '\0';
}
-/* Return true if inside a debug group with the same name. */
bool GPU_debug_group_match(const char *ref)
{
/* Otherwise there will be no names. */
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index 9099a6e4245..5b1eac2e82f 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -216,18 +216,12 @@ void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb)
unwrap(gpu_fb)->bind(enable_srgb);
}
-/**
- * Workaround for binding a SRGB frame-buffer without doing the SRGB transform.
- */
void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *gpu_fb)
{
const bool enable_srgb = false;
unwrap(gpu_fb)->bind(enable_srgb);
}
-/**
- * For stereo rendering.
- */
void GPU_backbuffer_bind(eGPUBackBuffer buffer)
{
Context *ctx = Context::get();
@@ -240,19 +234,18 @@ void GPU_backbuffer_bind(eGPUBackBuffer buffer)
}
}
-void GPU_framebuffer_restore(void)
+void GPU_framebuffer_restore()
{
Context::get()->back_left->bind(false);
}
-GPUFrameBuffer *GPU_framebuffer_active_get(void)
+GPUFrameBuffer *GPU_framebuffer_active_get()
{
Context *ctx = Context::get();
return wrap(ctx ? ctx->active_fb : nullptr);
}
-/* Returns the default frame-buffer. Will always exists even if it's just a dummy. */
-GPUFrameBuffer *GPU_framebuffer_back_get(void)
+GPUFrameBuffer *GPU_framebuffer_back_get()
{
Context *ctx = Context::get();
return wrap(ctx ? ctx->back_left : nullptr);
@@ -302,12 +295,6 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
unwrap(tex)->detach_from(unwrap(fb));
}
-/**
- * First GPUAttachment in *config is always the depth/depth_stencil buffer.
- * Following GPUAttachments are color buffers.
- * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
- * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
- */
void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb,
const GPUAttachment *config,
int config_len)
@@ -341,11 +328,6 @@ void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb,
/* ---------- Viewport & Scissor Region ----------- */
-/**
- * Viewport and scissor size is stored per frame-buffer.
- * It is only reset to its original dimensions explicitly OR when binding the frame-buffer after
- * modifying its attachments.
- */
void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int width, int height)
{
int viewport_rect[4] = {x, y, width, height};
@@ -357,9 +339,6 @@ void GPU_framebuffer_viewport_get(GPUFrameBuffer *gpu_fb, int r_viewport[4])
unwrap(gpu_fb)->viewport_get(r_viewport);
}
-/**
- * Reset to its attachment(s) size.
- */
void GPU_framebuffer_viewport_reset(GPUFrameBuffer *gpu_fb)
{
unwrap(gpu_fb)->viewport_reset();
@@ -376,9 +355,6 @@ void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb,
unwrap(gpu_fb)->clear(buffers, clear_col, clear_depth, clear_stencil);
}
-/**
- * Clear all textures attached to this frame-buffer with a different color.
- */
void GPU_framebuffer_multi_clear(GPUFrameBuffer *gpu_fb, const float (*clear_cols)[4])
{
unwrap(gpu_fb)->clear_multi(clear_cols);
@@ -425,7 +401,6 @@ void GPU_frontbuffer_read_pixels(
Context::get()->front_left->read(GPU_COLOR_BIT, format, rect, channels, 0, data);
}
-/* read_slot and write_slot are only used for color buffers. */
/* TODO(fclem): port as texture operation. */
void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read,
int read_slot,
@@ -466,11 +441,6 @@ void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read,
prev_fb->bind(true);
}
-/**
- * Use this if you need to custom down-sample your texture and use the previous mip-level as
- * input. This function only takes care of the correct texture handling. It execute the callback
- * for each texture level.
- */
void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *gpu_fb,
int max_lvl,
void (*callback)(void *userData, int level),
@@ -514,14 +484,14 @@ void GPU_framebuffer_push(GPUFrameBuffer *fb)
FrameBufferStack.top++;
}
-GPUFrameBuffer *GPU_framebuffer_pop(void)
+GPUFrameBuffer *GPU_framebuffer_pop()
{
BLI_assert(FrameBufferStack.top > 0);
FrameBufferStack.top--;
return FrameBufferStack.framebuffers[FrameBufferStack.top];
}
-uint GPU_framebuffer_stack_level_get(void)
+uint GPU_framebuffer_stack_level_get()
{
return FrameBufferStack.top;
}
@@ -593,7 +563,7 @@ static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs)
GPUOffScreen *GPU_offscreen_create(
int width, int height, bool depth, eGPUTextureFormat format, char err_out[256])
{
- GPUOffScreen *ofs = (GPUOffScreen *)MEM_callocN(sizeof(GPUOffScreen), __func__);
+ GPUOffScreen *ofs = MEM_cnew<GPUOffScreen>(__func__);
/* Sometimes areas can have 0 height or width and this will
* create a 1D texture which we don't want. */
@@ -704,9 +674,6 @@ GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
return ofs->color;
}
-/**
- * \note only to be used by viewport code!
- */
void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs,
GPUFrameBuffer **r_fb,
GPUTexture **r_color,
diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh
index 019f3a8d940..e7505258d2a 100644
--- a/source/blender/gpu/intern/gpu_framebuffer_private.hh
+++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh
@@ -189,24 +189,24 @@ class FrameBuffer {
copy_v4_v4_int(r_scissor, scissor_);
}
- inline bool scissor_test_get(void) const
+ inline bool scissor_test_get() const
{
return scissor_test_;
}
- inline void viewport_reset(void)
+ inline void viewport_reset()
{
int viewport_rect[4] = {0, 0, width_, height_};
viewport_set(viewport_rect);
}
- inline void scissor_reset(void)
+ inline void scissor_reset()
{
int scissor_rect[4] = {0, 0, width_, height_};
scissor_set(scissor_rect);
}
- inline GPUTexture *depth_tex(void) const
+ inline GPUTexture *depth_tex() const
{
if (attachments_[GPU_FB_DEPTH_ATTACHMENT].tex) {
return attachments_[GPU_FB_DEPTH_ATTACHMENT].tex;
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index cdd56a117db..e28776c87b3 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -89,7 +89,6 @@ void immUnbindProgram()
imm->shader = nullptr;
}
-/* XXX do not use it. Special hack to use OCIO with batch API. */
GPUShader *immGetShader()
{
return imm->shader;
@@ -603,7 +602,6 @@ void immUniform4fv(const char *name, const float data[4])
GPU_shader_uniform_4fv(imm->shader, name, data);
}
-/* Note array index is not supported for name (i.e: "array[0]"). */
void immUniformArray4fv(const char *name, const float *data, int count)
{
GPU_shader_uniform_4fv_array(imm->shader, name, count, (const float(*)[4])data);
@@ -631,6 +629,12 @@ void immBindTextureSampler(const char *name, GPUTexture *tex, eGPUSamplerState s
GPU_texture_bind_ex(tex, state, binding, true);
}
+void immBindUniformBuf(const char *name, GPUUniformBuf *ubo)
+{
+ int binding = GPU_shader_get_uniform_block_binding(imm->shader, name);
+ GPU_uniformbuf_bind(ubo, binding);
+}
+
/* --- convenience functions for setting "uniform vec4 color" --- */
void immUniformColor4f(float r, float g, float b, float a)
diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh
index 382f70eeec4..bc1ae403c52 100644
--- a/source/blender/gpu/intern/gpu_immediate_private.hh
+++ b/source/blender/gpu/intern/gpu_immediate_private.hh
@@ -68,11 +68,11 @@ class Immediate {
Immediate(){};
virtual ~Immediate(){};
- virtual uchar *begin(void) = 0;
- virtual void end(void) = 0;
+ virtual uchar *begin() = 0;
+ virtual void end() = 0;
};
} // namespace blender::gpu
-void immActivate(void);
-void immDeactivate(void);
+void immActivate();
+void immDeactivate();
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
index d18dc862ce7..37a423d41a0 100644
--- a/source/blender/gpu/intern/gpu_immediate_util.c
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -143,17 +143,6 @@ void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4])
}
#endif
-/**
- * Pack color into 3 bytes
- *
- * This define converts a numerical value to the equivalent 24-bit
- * color, while not being endian-sensitive. On little-endian, this
- * is the same as doing a 'naive' indexing, on big-endian, it is not!
- *
- * \note BGR format (i.e. 0xBBGGRR)...
- *
- * \param x: color.
- */
void imm_cpack(uint x)
{
immUniformColor3ub(((x)&0xFF), (((x) >> 8) & 0xFF), (((x) >> 16) & 0xFF));
@@ -163,64 +152,44 @@ static void imm_draw_circle(GPUPrimType prim_type,
const uint shdr_pos,
float x,
float y,
- float rad_x,
- float rad_y,
+ float radius_x,
+ float radius_y,
int nsegments)
{
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
- immVertex2f(shdr_pos, x + (rad_x * cosf(angle)), y + (rad_y * sinf(angle)));
+ immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle)));
}
immEnd();
}
-/**
- * Draw a circle outline with the given \a radius.
- * The circle is centered at \a x, \a y and drawn in the XY plane.
- *
- * \param shdr_pos: The vertex attribute number for position.
- * \param x: Horizontal center.
- * \param y: Vertical center.
- * \param rad: The circle's radius.
- * \param nsegments: The number of segments to use in drawing (more = smoother).
- */
-void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
{
- imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments);
+ imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius, radius, nsegments);
}
-/**
- * Draw a filled circle with the given \a radius.
- * The circle is centered at \a x, \a y and drawn in the XY plane.
- *
- * \param shdr_pos: The vertex attribute number for position.
- * \param x: Horizontal center.
- * \param y: Vertical center.
- * \param rad: The circle's radius.
- * \param nsegments: The number of segments to use in drawing (more = smoother).
- */
-void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments)
{
- imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments);
+ imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, radius, radius, nsegments);
}
void imm_draw_circle_wire_aspect_2d(
- uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+ uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
- imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments);
+ imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
void imm_draw_circle_fill_aspect_2d(
- uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+ uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
- imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments);
+ imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
static void imm_draw_circle_partial(GPUPrimType prim_type,
uint pos,
float x,
float y,
- float rad,
+ float radius,
int nsegments,
float start,
float sweep)
@@ -234,15 +203,15 @@ static void imm_draw_circle_partial(GPUPrimType prim_type,
const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
const float angle_sin = sinf(angle);
const float angle_cos = cosf(angle);
- immVertex2f(pos, x + rad * angle_cos, y + rad * angle_sin);
+ immVertex2f(pos, x + radius * angle_cos, y + radius * angle_sin);
}
immEnd();
}
void imm_draw_circle_partial_wire_2d(
- uint pos, float x, float y, float rad, int nsegments, float start, float sweep)
+ uint pos, float x, float y, float radius, int nsegments, float start, float sweep)
{
- imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, rad, nsegments, start, sweep);
+ imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, radius, nsegments, start, sweep);
}
static void imm_draw_disk_partial(GPUPrimType prim_type,
@@ -274,21 +243,6 @@ static void imm_draw_disk_partial(GPUPrimType prim_type,
immEnd();
}
-/**
- * Draw a filled arc with the given inner and outer radius.
- * The circle is centered at \a x, \a y and drawn in the XY plane.
- *
- * \note Arguments are `gluPartialDisk` compatible.
- *
- * \param pos: The vertex attribute number for position.
- * \param x: Horizontal center.
- * \param y: Vertical center.
- * \param rad_inner: The inner circle's radius.
- * \param rad_outer: The outer circle's radius (can be zero).
- * \param nsegments: The number of segments to use in drawing (more = smoother).
- * \param start: Specifies the starting angle, in degrees, of the disk portion.
- * \param sweep: Specifies the sweep angle, in degrees, of the disk portion.
- */
void imm_draw_disk_partial_fill_2d(uint pos,
float x,
float y,
@@ -303,40 +257,31 @@ void imm_draw_disk_partial_fill_2d(uint pos,
}
static void imm_draw_circle_3D(
- GPUPrimType prim_type, uint pos, float x, float y, float rad, int nsegments)
+ GPUPrimType prim_type, uint pos, float x, float y, float radius, int nsegments)
{
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
- immVertex3f(pos, x + rad * cosf(angle), y + rad * sinf(angle), 0.0f);
+ immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f);
}
immEnd();
}
-void imm_draw_circle_wire_3d(uint pos, float x, float y, float rad, int nsegments)
+void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments)
{
- imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, rad, nsegments);
+ imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, radius, nsegments);
}
-void imm_draw_circle_dashed_3d(uint pos, float x, float y, float rad, int nsegments)
+void imm_draw_circle_dashed_3d(uint pos, float x, float y, float radius, int nsegments)
{
- imm_draw_circle_3D(GPU_PRIM_LINES, pos, x, y, rad, nsegments / 2);
+ imm_draw_circle_3D(GPU_PRIM_LINES, pos, x, y, radius, nsegments / 2);
}
-void imm_draw_circle_fill_3d(uint pos, float x, float y, float rad, int nsegments)
+void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments)
{
- imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, rad, nsegments);
+ imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, radius, nsegments);
}
-/**
- * Draw a lined box.
- *
- * \param pos: The vertex attribute number for position.
- * \param x1: left.
- * \param y1: bottom.
- * \param x2: right.
- * \param y2: top.
- */
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
{
immBegin(GPU_PRIM_LINE_LOOP, 4);
@@ -358,9 +303,6 @@ void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2)
immEnd();
}
-/**
- * Draw a standard checkerboard to indicate transparent backgrounds.
- */
void imm_draw_box_checker_2d_ex(float x1,
float y1,
float x2,
@@ -391,12 +333,12 @@ void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
imm_draw_box_checker_2d_ex(x1, y1, x2, y2, checker_primary, checker_secondary, checker_size);
}
-void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
+void imm_draw_cube_fill_3d(uint pos, const float center[3], const float aspect[3])
{
float coords[ARRAY_SIZE(cube_coords)][3];
for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
- madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
}
immBegin(GPU_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
@@ -412,12 +354,12 @@ void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
immEnd();
}
-void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
+void imm_draw_cube_wire_3d(uint pos, const float center[3], const float aspect[3])
{
float coords[ARRAY_SIZE(cube_coords)][3];
for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
- madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
}
immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
@@ -428,18 +370,36 @@ void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
immEnd();
}
-/**
- * Draw a cylinder. Replacement for gluCylinder.
- * _warning_ : Slow, better use it only if you no other choices.
- *
- * \param pos: The vertex attribute number for position.
- * \param nor: The vertex attribute number for normal.
- * \param base: Specifies the radius of the cylinder at z = 0.
- * \param top: Specifies the radius of the cylinder at z = height.
- * \param height: Specifies the height of the cylinder.
- * \param slices: Specifies the number of subdivisions around the z axis.
- * \param stacks: Specifies the number of subdivisions along the z axis.
- */
+void imm_draw_cube_corners_3d(uint pos,
+ const float center[3],
+ const float aspect[3],
+ const float factor)
+{
+ float coords[ARRAY_SIZE(cube_coords)][3];
+
+ for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
+ madd_v3_v3v3v3(coords[i], center, cube_coords[i], aspect);
+ }
+
+ immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 4);
+ for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
+ float vec[3], co[3];
+ sub_v3_v3v3(vec, coords[cube_line_index[i][1]], coords[cube_line_index[i][0]]);
+ mul_v3_fl(vec, factor);
+
+ copy_v3_v3(co, coords[cube_line_index[i][0]]);
+ immVertex3fv(pos, co);
+ add_v3_v3(co, vec);
+ immVertex3fv(pos, co);
+
+ copy_v3_v3(co, coords[cube_line_index[i][1]]);
+ immVertex3fv(pos, co);
+ sub_v3_v3(co, vec);
+ immVertex3fv(pos, co);
+ }
+ immEnd();
+}
+
void imm_draw_cylinder_fill_normal_3d(
uint pos, uint nor, float base, float top, float height, int slices, int stacks)
{
@@ -572,3 +532,55 @@ void imm_draw_cylinder_fill_3d(
}
immEnd();
}
+
+/* Circle Drawing - Tables for Optimized Drawing Speed */
+#define CIRCLE_RESOL 32
+
+static void circball_array_fill(const float verts[CIRCLE_RESOL][3],
+ const float cent[3],
+ const float radius,
+ const float tmat[4][4])
+{
+ /* 32 values of sin function (still same result!) */
+ const float sinval[CIRCLE_RESOL] = {
+ 0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213,
+ 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196,
+ 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573,
+ -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278,
+ -0.57126821, -0.39435585, -0.20129852, 0.00000000,
+ };
+
+ /* 32 values of cos function (still same result!) */
+ const float cosval[CIRCLE_RESOL] = {
+ 1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525,
+ 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661,
+ -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598,
+ -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691,
+ 0.82076344, 0.91895781, 0.97952994, 1.00000000,
+ };
+
+ float vx[3], vy[3];
+ float *viter = (float *)verts;
+
+ mul_v3_v3fl(vx, tmat[0], radius);
+ mul_v3_v3fl(vy, tmat[1], radius);
+
+ for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
+ viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
+ viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
+ viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
+ }
+}
+
+void imm_drawcircball(const float cent[3], float radius, const float tmat[4][4], uint pos)
+{
+ float verts[CIRCLE_RESOL][3];
+
+ circball_array_fill(verts, cent, radius, tmat);
+
+ immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; i++) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
+}
diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc
index be7470e79c1..895b2a8461b 100644
--- a/source/blender/gpu/intern/gpu_index_buffer.cc
+++ b/source/blender/gpu/intern/gpu_index_buffer.cc
@@ -74,11 +74,16 @@ void GPU_indexbuf_init(GPUIndexBufBuilder *builder,
GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len)
{
GPUIndexBuf *elem_ = GPU_indexbuf_calloc();
- IndexBuf *elem = unwrap(elem_);
- elem->init_build_on_device(index_len);
+ GPU_indexbuf_init_build_on_device(elem_, index_len);
return elem_;
}
+void GPU_indexbuf_init_build_on_device(GPUIndexBuf *elem, uint index_len)
+{
+ IndexBuf *elem_ = unwrap(elem);
+ elem_->init_build_on_device(index_len);
+}
+
void GPU_indexbuf_join(GPUIndexBufBuilder *builder_to, const GPUIndexBufBuilder *builder_from)
{
BLI_assert(builder_to->data == builder_from->data);
@@ -349,7 +354,7 @@ uint32_t *IndexBuf::unmap(const uint32_t *mapped_memory) const
/** \name C-API
* \{ */
-GPUIndexBuf *GPU_indexbuf_calloc(void)
+GPUIndexBuf *GPU_indexbuf_calloc()
{
return wrap(GPUBackend::get()->indexbuf_alloc());
}
@@ -410,9 +415,19 @@ int GPU_indexbuf_primitive_len(GPUPrimType prim_type)
return indices_per_primitive(prim_type);
}
+void GPU_indexbuf_use(GPUIndexBuf *elem)
+{
+ unwrap(elem)->upload_data();
+}
+
void GPU_indexbuf_bind_as_ssbo(GPUIndexBuf *elem, int binding)
{
unwrap(elem)->bind_as_ssbo(binding);
}
+void GPU_indexbuf_update_sub(GPUIndexBuf *elem, uint start, uint len, const void *data)
+{
+ unwrap(elem)->update_sub(start, len, data);
+}
+
/** \} */
diff --git a/source/blender/gpu/intern/gpu_index_buffer_private.hh b/source/blender/gpu/intern/gpu_index_buffer_private.hh
index ed7dd830c8c..4bb46689727 100644
--- a/source/blender/gpu/intern/gpu_index_buffer_private.hh
+++ b/source/blender/gpu/intern/gpu_index_buffer_private.hh
@@ -77,26 +77,30 @@ class IndexBuf {
void init_subrange(IndexBuf *elem_src, uint start, uint length);
void init_build_on_device(uint index_len);
- uint32_t index_len_get(void) const
+ uint32_t index_len_get() const
{
return index_len_;
}
/* Return size in byte of the drawable data buffer range. Actual buffer size might be bigger. */
- size_t size_get(void) const
+ size_t size_get() const
{
return index_len_ * to_bytesize(index_type_);
};
- bool is_init(void) const
+ bool is_init() const
{
return is_init_;
};
+ virtual void upload_data() = 0;
+
virtual void bind_as_ssbo(uint binding) = 0;
virtual const uint32_t *read() const = 0;
uint32_t *unmap(const uint32_t *mapped_memory) const;
+ virtual void update_sub(uint start, uint len, const void *data) = 0;
+
private:
inline void squeeze_indices_short(uint min_idx, uint max_idx);
inline uint index_range(uint *r_min, uint *r_max);
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 0eb2fe57c28..5815fb10b0c 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -32,6 +32,8 @@
#include "intern/gpu_codegen.h"
#include "intern/gpu_material_library.h"
#include "intern/gpu_private.h"
+#include "intern/gpu_shader_create_info_private.hh"
+#include "intern/gpu_shader_dependency_private.h"
/**
* although the order of initialization and shutdown should not matter
@@ -49,6 +51,9 @@ void GPU_init(void)
initialized = true;
+ gpu_shader_dependency_init();
+ gpu_shader_create_info_init();
+
gpu_codegen_init();
gpu_material_library_init();
@@ -70,6 +75,9 @@ void GPU_exit(void)
gpu_material_library_exit();
gpu_codegen_exit();
+ gpu_shader_dependency_exit();
+ gpu_shader_create_info_exit();
+
initialized = false;
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index e40d6195eab..ca1f45f7238 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -44,6 +44,8 @@
#include "BKE_scene.h"
#include "BKE_world.h"
+#include "NOD_shader.h"
+
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -84,6 +86,7 @@ struct GPUMaterial {
Material *ma;
/** 1D Texture array containing all color bands. */
GPUTexture *coba_tex;
+
GPUColorBandBuilder *coba_builder;
/* Low level node graph(s). Also contains resources needed by the material. */
GPUNodeGraph graph;
@@ -100,7 +103,6 @@ enum {
/* Functions */
-/* Returns the address of the future pointer to coba_tex */
GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
int size,
float *pixels,
@@ -189,7 +191,6 @@ GPUShader *GPU_material_get_shader(GPUMaterial *material)
return material->pass ? GPU_pass_shader_get(material->pass) : NULL;
}
-/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
return material->ma;
@@ -200,11 +201,6 @@ GPUUniformBuf *GPU_material_uniform_buffer_get(GPUMaterial *material)
return material->ubo;
}
-/**
- * Create dynamic UBO from parameters
- *
- * \param inputs: Items are #LinkData, data is #GPUInput (`BLI_genericNodeN(GPUInput)`).
- */
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
{
#ifndef NDEBUG
@@ -332,9 +328,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
bNodeTree *ntree,
ListBase *gpumaterials,
const char *name,
- const uint64_t shader_uuid,
- const bool is_volume_shader,
- const bool is_lookdev,
+ uint64_t shader_uuid,
+ bool is_volume_shader,
+ bool is_lookdev,
GPUCodegenCallbackFn callback,
void *thunk)
{
diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c
index 6d14993e2ac..6f68729eaae 100644
--- a/source/blender/gpu/intern/gpu_material_library.c
+++ b/source/blender/gpu/intern/gpu_material_library.c
@@ -62,6 +62,7 @@ extern char datatoc_gpu_shader_material_diffuse_glsl[];
extern char datatoc_gpu_shader_material_displacement_glsl[];
extern char datatoc_gpu_shader_material_eevee_specular_glsl[];
extern char datatoc_gpu_shader_material_emission_glsl[];
+extern char datatoc_gpu_shader_material_float_curve_glsl[];
extern char datatoc_gpu_shader_material_fractal_noise_glsl[];
extern char datatoc_gpu_shader_material_fresnel_glsl[];
extern char datatoc_gpu_shader_material_gamma_glsl[];
@@ -90,6 +91,7 @@ extern char datatoc_gpu_shader_material_output_aov_glsl[];
extern char datatoc_gpu_shader_material_output_material_glsl[];
extern char datatoc_gpu_shader_material_output_world_glsl[];
extern char datatoc_gpu_shader_material_particle_info_glsl[];
+extern char datatoc_gpu_shader_material_point_info_glsl[];
extern char datatoc_gpu_shader_material_principled_glsl[];
extern char datatoc_gpu_shader_material_refraction_glsl[];
extern char datatoc_gpu_shader_material_rgb_curves_glsl[];
@@ -262,6 +264,11 @@ static GPUMaterialLibrary gpu_shader_material_emission_library = {
.dependencies = {NULL},
};
+static GPUMaterialLibrary gpu_shader_material_float_curve_library = {
+ .code = datatoc_gpu_shader_material_float_curve_glsl,
+ .dependencies = {NULL},
+};
+
static GPUMaterialLibrary gpu_shader_material_fresnel_library = {
.code = datatoc_gpu_shader_material_fresnel_glsl,
.dependencies = {NULL},
@@ -289,7 +296,7 @@ static GPUMaterialLibrary gpu_shader_material_glass_library = {
static GPUMaterialLibrary gpu_shader_material_hair_info_library = {
.code = datatoc_gpu_shader_material_hair_info_glsl,
- .dependencies = {NULL},
+ .dependencies = {&gpu_shader_material_hash_library, NULL},
};
static GPUMaterialLibrary gpu_shader_material_holdout_library = {
@@ -382,6 +389,11 @@ static GPUMaterialLibrary gpu_shader_material_particle_info_library = {
.dependencies = {NULL},
};
+static GPUMaterialLibrary gpu_shader_material_point_info_library = {
+ .code = datatoc_gpu_shader_material_point_info_glsl,
+ .dependencies = {&gpu_shader_material_hash_library, NULL},
+};
+
static GPUMaterialLibrary gpu_shader_material_principled_library = {
.code = datatoc_gpu_shader_material_principled_glsl,
.dependencies = {NULL},
@@ -591,6 +603,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
&gpu_shader_material_color_util_library,
&gpu_shader_material_hash_library,
&gpu_shader_material_noise_library,
+ &gpu_shader_material_float_curve_library,
&gpu_shader_material_fractal_noise_library,
&gpu_shader_material_add_shader_library,
&gpu_shader_material_ambient_occlusion_library,
@@ -637,6 +650,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
&gpu_shader_material_output_material_library,
&gpu_shader_material_output_world_library,
&gpu_shader_material_particle_info_library,
+ &gpu_shader_material_point_info_library,
&gpu_shader_material_principled_library,
&gpu_shader_material_refraction_library,
&gpu_shader_material_rgb_curves_library,
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
index 139f5200f59..d9c56ddd425 100644
--- a/source/blender/gpu/intern/gpu_material_library.h
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -67,7 +67,7 @@ char *gpu_material_library_generate_code(struct GSet *used_libraries);
/* Code Parsing */
const char *gpu_str_skip_token(const char *str, char *token, int max);
-const char *gpu_data_type_to_string(const eGPUType type);
+const char *gpu_data_type_to_string(eGPUType type);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc
index bbcc241f5e3..cf3f7f5e778 100644
--- a/source/blender/gpu/intern/gpu_matrix.cc
+++ b/source/blender/gpu/intern/gpu_matrix.cc
@@ -67,7 +67,7 @@ struct GPUMatrixState {
#define ProjectionStack Context::get()->matrix_state->projection_stack
#define Projection ProjectionStack.stack[ProjectionStack.top]
-GPUMatrixState *GPU_matrix_state_create(void)
+GPUMatrixState *GPU_matrix_state_create()
{
#define MATRIX_4X4_IDENTITY \
{ \
@@ -99,7 +99,7 @@ static void gpu_matrix_state_active_set_dirty(bool value)
state->dirty = value;
}
-void GPU_matrix_reset(void)
+void GPU_matrix_reset()
{
GPUMatrixState *state = Context::get()->matrix_state;
state->model_view_stack.top = 0;
@@ -132,28 +132,28 @@ static void checkmat(cosnt float *m)
#endif
-void GPU_matrix_push(void)
+void GPU_matrix_push()
{
BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH);
ModelViewStack.top++;
copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]);
}
-void GPU_matrix_pop(void)
+void GPU_matrix_pop()
{
BLI_assert(ModelViewStack.top > 0);
ModelViewStack.top--;
gpu_matrix_state_active_set_dirty(true);
}
-void GPU_matrix_push_projection(void)
+void GPU_matrix_push_projection()
{
BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH);
ProjectionStack.top++;
copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]);
}
-void GPU_matrix_pop_projection(void)
+void GPU_matrix_pop_projection()
{
BLI_assert(ProjectionStack.top > 0);
ProjectionStack.top--;
@@ -167,7 +167,7 @@ void GPU_matrix_set(const float m[4][4])
gpu_matrix_state_active_set_dirty(true);
}
-void GPU_matrix_identity_projection_set(void)
+void GPU_matrix_identity_projection_set()
{
unit_m4(Projection);
CHECKMAT(Projection3D);
@@ -181,7 +181,7 @@ void GPU_matrix_projection_set(const float m[4][4])
gpu_matrix_state_active_set_dirty(true);
}
-void GPU_matrix_identity_set(void)
+void GPU_matrix_identity_set()
{
unit_m4(ModelView);
gpu_matrix_state_active_set_dirty(true);
@@ -668,7 +668,7 @@ void GPU_matrix_bind(GPUShader *shader)
gpu_matrix_state_active_set_dirty(false);
}
-bool GPU_matrix_dirty_get(void)
+bool GPU_matrix_dirty_get()
{
GPUMatrixState *state = Context::get()->matrix_state;
return state->dirty;
@@ -677,17 +677,18 @@ bool GPU_matrix_dirty_get(void)
/* -------------------------------------------------------------------- */
/** \name Python API Helpers
* \{ */
+
BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mismatch");
/* Return int since caller is may subtract. */
-int GPU_matrix_stack_level_get_model_view(void)
+int GPU_matrix_stack_level_get_model_view()
{
GPUMatrixState *state = Context::get()->matrix_state;
return (int)state->model_view_stack.top;
}
-int GPU_matrix_stack_level_get_projection(void)
+int GPU_matrix_stack_level_get_projection()
{
GPUMatrixState *state = Context::get()->matrix_state;
return (int)state->projection_stack.top;
@@ -733,9 +734,6 @@ float GPU_polygon_offset_calc(const float (*winmat)[4], float viewdist, float di
return winmat[3][2] * -0.0025f * dist;
}
-/**
- * \note \a viewdist is only for ortho at the moment.
- */
void GPU_polygon_offset(float viewdist, float dist)
{
static float winmat[4][4], offset = 0.0f;
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 7d1bd763a5b..593a89bbf21 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -435,7 +435,10 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
if (tex == NULL) {
tex = MEM_callocN(sizeof(*tex), __func__);
tex->ima = ima;
- tex->iuser = iuser;
+ if (iuser != NULL) {
+ tex->iuser = *iuser;
+ tex->iuser_available = true;
+ }
tex->colorband = colorband;
tex->sampler_state = sampler_state;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
@@ -644,25 +647,27 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
}
va_end(params);
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
BLI_addtail(&graph->nodes, node);
return true;
}
-static bool gpu_stack_link_v(GPUMaterial *material,
- bNode *bnode,
- const char *name,
- GPUNodeStack *in,
- GPUNodeStack *out,
- va_list params)
+bool GPU_stack_link(GPUMaterial *material,
+ bNode *bnode,
+ const char *name,
+ GPUNodeStack *in,
+ GPUNodeStack *out,
+ ...)
{
- GPUNodeGraph *graph = gpu_material_node_graph(material);
+ GSet *used_libraries = gpu_material_used_libraries(material);
GPUNode *node;
GPUFunction *function;
GPUNodeLink *link, **linkptr;
+ va_list params;
int i, totin, totout;
- function = gpu_material_library_use_function(graph->used_libraries, name);
+ function = gpu_material_library_use_function(used_libraries, name);
if (!function) {
fprintf(stderr, "GPU failed to find function %s\n", name);
return false;
@@ -690,6 +695,7 @@ static bool gpu_stack_link_v(GPUMaterial *material,
}
}
+ va_start(params, out);
for (i = 0; i < function->totparam; i++) {
if (function->paramqual[i] != FUNCTION_QUAL_IN) {
if (totout == 0) {
@@ -715,53 +721,14 @@ static bool gpu_stack_link_v(GPUMaterial *material,
}
}
}
+ va_end(params);
+ GPUNodeGraph *graph = gpu_material_node_graph(material);
BLI_addtail(&graph->nodes, node);
return true;
}
-bool GPU_stack_link(GPUMaterial *material,
- bNode *bnode,
- const char *name,
- GPUNodeStack *in,
- GPUNodeStack *out,
- ...)
-{
- va_list params;
- va_start(params, out);
- bool valid = gpu_stack_link_v(material, bnode, name, in, out, params);
- va_end(params);
-
- return valid;
-}
-
-/* This is a special function to call the "*_eval" function of a BSDF node.
- * This must be call right after GPU_stack_link() so that out[0] contains a valid link. */
-bool GPU_stack_eval_link(GPUMaterial *material,
- bNode *bnode,
- const char *name,
- GPUNodeStack *in,
- GPUNodeStack *out,
- ...)
-{
- /* Save the closure link to replace the one created by the eval function call. Avoiding
- * dependency to the eval call before the end of the graph. */
- GPUNodeLink *closure_out = out[0].link;
-
- va_list params;
- va_start(params, out);
- bool valid = gpu_stack_link_v(material, bnode, name, in, out, params);
- va_end(params);
-
- /* Save both nodes for graph amendment. */
- GPU_material_add_closure_eval(material, closure_out, out[0].link);
- /* Restore original link. */
- out[0].link = closure_out;
-
- return valid;
-}
-
GPUNodeLink *GPU_uniformbuf_link_out(GPUMaterial *mat,
bNode *node,
GPUNodeStack *stack,
@@ -815,7 +782,6 @@ static void gpu_node_free(GPUNode *node)
MEM_freeN(node);
}
-/* Free intermediate node graph. */
void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
{
GPUNode *node;
@@ -824,14 +790,9 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
gpu_node_free(node);
}
- BLI_freelistN(&graph->eval_nodes);
- graph->outlink_surface = NULL;
- graph->outlink_volume = NULL;
- graph->outlink_displacement = NULL;
- graph->outlink_thickness = NULL;
+ graph->outlink = NULL;
}
-/* Free both node graph, requested attributes and textures. */
void gpu_node_graph_free(GPUNodeGraph *graph)
{
BLI_freelistN(&graph->outlink_aovs);
@@ -844,32 +805,28 @@ void gpu_node_graph_free(GPUNodeGraph *graph)
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
GPU_uniform_attr_list_free(&graph->uniform_attrs);
-
- if (graph->used_libraries) {
- BLI_gset_free(graph->used_libraries, NULL);
- graph->used_libraries = NULL;
- }
}
/* Prune Unused Nodes */
-static void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag)
+static void gpu_nodes_tag(GPUNodeLink *link)
{
GPUNode *node;
+ GPUInput *input;
- if (!link || !link->output) {
+ if (!link->output) {
return;
}
node = link->output->node;
- if (node->tag & tag) {
+ if (node->tag) {
return;
}
- node->tag |= tag;
- LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
+ node->tag = true;
+ for (input = node->inputs.first; input; input = input->next) {
if (input->link) {
- gpu_nodes_tag(input->link, tag);
+ gpu_nodes_tag(input->link);
}
}
}
@@ -877,30 +834,18 @@ static void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
{
LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
- node->tag = GPU_NODE_TAG_NONE;
+ node->tag = false;
}
- gpu_nodes_tag(graph->outlink_surface, GPU_NODE_TAG_SURFACE);
- gpu_nodes_tag(graph->outlink_volume, GPU_NODE_TAG_VOLUME);
- gpu_nodes_tag(graph->outlink_displacement, GPU_NODE_TAG_DISPLACEMENT);
- gpu_nodes_tag(graph->outlink_thickness, GPU_NODE_TAG_THICKNESS);
-
+ gpu_nodes_tag(graph->outlink);
LISTBASE_FOREACH (GPUNodeGraphOutputLink *, aovlink, &graph->outlink_aovs) {
- gpu_nodes_tag(aovlink->outlink, GPU_NODE_TAG_AOV);
- }
-
- LISTBASE_FOREACH (GPUNodeGraphEvalNode *, node, &graph->eval_nodes) {
- /* Copy weight node tag to avoid pruning of eval node since they are node connected to
- * output. */
- if (node->weight_node->tag != GPU_NODE_TAG_NONE) {
- node->eval_node->tag = GPU_NODE_TAG_EVAL | node->weight_node->tag;
- }
+ gpu_nodes_tag(aovlink->outlink);
}
for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) {
next = node->next;
- if (node->tag == GPU_NODE_TAG_NONE) {
+ if (!node->tag) {
BLI_remlink(&graph->nodes, node);
gpu_node_free(node);
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index b3e9690dd32..9f1a729738b 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -191,12 +191,21 @@ typedef struct GPUNodeGraph {
void gpu_node_graph_prune_unused(GPUNodeGraph *graph);
void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph);
+/**
+ * Free intermediate node graph.
+ */
void gpu_node_graph_free_nodes(GPUNodeGraph *graph);
+/**
+ * Free both node graph and requested attributes and textures.
+ */
void gpu_node_graph_free(GPUNodeGraph *graph);
/* Material calls */
struct GPUNodeGraph *gpu_material_node_graph(struct GPUMaterial *material);
+/**
+ * Returns the address of the future pointer to coba_tex.
+ */
struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat,
int size,
float *pixels,
diff --git a/source/blender/gpu/intern/gpu_platform.cc b/source/blender/gpu/intern/gpu_platform.cc
index 49dde473300..34834a62268 100644
--- a/source/blender/gpu/intern/gpu_platform.cc
+++ b/source/blender/gpu/intern/gpu_platform.cc
@@ -127,37 +127,36 @@ eGPUSupportLevel GPU_platform_support_level()
return GPG.support_level;
}
-const char *GPU_platform_vendor(void)
+const char *GPU_platform_vendor()
{
BLI_assert(GPG.initialized);
return GPG.vendor;
}
-const char *GPU_platform_renderer(void)
+const char *GPU_platform_renderer()
{
BLI_assert(GPG.initialized);
return GPG.renderer;
}
-const char *GPU_platform_version(void)
+const char *GPU_platform_version()
{
BLI_assert(GPG.initialized);
return GPG.version;
}
-const char *GPU_platform_support_level_key(void)
+const char *GPU_platform_support_level_key()
{
BLI_assert(GPG.initialized);
return GPG.support_key;
}
-const char *GPU_platform_gpu_name(void)
+const char *GPU_platform_gpu_name()
{
BLI_assert(GPG.initialized);
return GPG.gpu_name;
}
-/* GPU Types */
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
{
BLI_assert(GPG.initialized);
diff --git a/source/blender/gpu/intern/gpu_platform_private.hh b/source/blender/gpu/intern/gpu_platform_private.hh
index f823269ab54..faae7c48588 100644
--- a/source/blender/gpu/intern/gpu_platform_private.hh
+++ b/source/blender/gpu/intern/gpu_platform_private.hh
@@ -49,7 +49,7 @@ class GPUPlatformGlobal {
const char *renderer_str,
const char *version_str);
- void clear(void);
+ void clear();
};
extern GPUPlatformGlobal GPG;
diff --git a/source/blender/gpu/intern/gpu_query.hh b/source/blender/gpu/intern/gpu_query.hh
index 0356e145b00..a004c355c8f 100644
--- a/source/blender/gpu/intern/gpu_query.hh
+++ b/source/blender/gpu/intern/gpu_query.hh
@@ -45,8 +45,8 @@ class QueryPool {
* Will start and end the query at this index inside the pool.
* The pool will resize automatically.
*/
- virtual void begin_query(void) = 0;
- virtual void end_query(void) = 0;
+ virtual void begin_query() = 0;
+ virtual void end_query() = 0;
/**
* Must be fed with a buffer large enough to contain all the queries issued.
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 88b704a84a1..958aab65b57 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -20,8 +20,8 @@
/** \file
* \ingroup gpu
*
- * Interface for accessing gpu-related methods for selection. The semantics are
- * similar to glRenderMode(GL_SELECT) from older OpenGL versions.
+ * Interface for accessing GPU-related methods for selection. The semantics are
+ * similar to `glRenderMode(GL_SELECT)` from older OpenGL versions.
*/
#include <stdlib.h>
#include <string.h>
@@ -38,6 +38,10 @@
#include "gpu_select_private.h"
+/* -------------------------------------------------------------------- */
+/** \name Internal Types
+ * \{ */
+
/* Internal algorithm used */
enum {
/** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c`
@@ -57,13 +61,25 @@ typedef struct GPUSelectState {
char algorithm;
/* allow GPU_select_begin/end without drawing */
bool use_cache;
+ /**
+ * Signifies that #GPU_select_cache_begin has been called,
+ * future calls to #GPU_select_begin should initialize the cache.
+ *
+ * \note #GPU_select_cache_begin could perform initialization but doesn't as it's inconvenient
+ * for callers making the cache begin/end calls outside lower level selection logic
+ * where the `mode` to pass to #GPU_select_begin yet isn't known.
+ */
+ bool use_cache_needs_init;
} GPUSelectState;
static GPUSelectState g_select_state = {0};
-/**
- * initialize and provide buffer for results
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public API
+ * \{ */
+
void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
@@ -83,9 +99,26 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode,
g_select_state.algorithm = ALGO_GL_QUERY;
}
+ /* This function is called when cache has already been initialized,
+ * so only manipulate cache values when cache is pending. */
+ if (g_select_state.use_cache_needs_init) {
+ g_select_state.use_cache_needs_init = false;
+
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_QUERY: {
+ g_select_state.use_cache = false;
+ break;
+ }
+ default: {
+ g_select_state.use_cache = true;
+ gpu_select_pick_cache_begin();
+ break;
+ }
+ }
+ }
+
switch (g_select_state.algorithm) {
case ALGO_GL_QUERY: {
- g_select_state.use_cache = false;
gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits);
break;
}
@@ -97,14 +130,6 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode,
}
}
-/**
- * loads a new selection id and ends previous query, if any.
- * In second pass of selection it also returns
- * if id has been hit on the first pass already.
- * Thus we can skip drawing un-hit objects.
- *
- * \warning We rely on the order of object rendering on passes to be the same for this to work.
- */
bool GPU_select_load_id(uint id)
{
/* if no selection mode active, ignore */
@@ -123,11 +148,6 @@ bool GPU_select_load_id(uint id)
}
}
-/**
- * Cleanup and flush selection results to buffer.
- * Return number of hits and hits in buffer.
- * if \a dopass is true, we will do a second pass with occlusion queries to get the closest hit.
- */
uint GPU_select_end(void)
{
uint hits = 0;
@@ -149,21 +169,24 @@ uint GPU_select_end(void)
return hits;
}
-/* ----------------------------------------------------------------------------
- * Caching
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Caching
*
* Support multiple begin/end's as long as they are within the initial region.
- * Currently only used by ALGO_GL_PICK.
- */
+ * Currently only used by #ALGO_GL_PICK.
+ * \{ */
void GPU_select_cache_begin(void)
{
- /* validate on GPU_select_begin, clear if not supported */
- BLI_assert(g_select_state.use_cache == false);
- g_select_state.use_cache = true;
- if (g_select_state.algorithm == ALGO_GL_PICK) {
- gpu_select_pick_cache_begin();
- }
+ BLI_assert(g_select_state.select_is_active == false);
+ /* Ensure #GPU_select_cache_end is always called. */
+ BLI_assert(g_select_state.use_cache_needs_init == false);
+
+ /* Signal that cache should be used, instead of calling the algorithms cache-begin function.
+ * This is more convenient as the exact method of selection may not be known by the caller. */
+ g_select_state.use_cache_needs_init = true;
}
void GPU_select_cache_load_id(void)
@@ -177,9 +200,12 @@ void GPU_select_cache_load_id(void)
void GPU_select_cache_end(void)
{
if (g_select_state.algorithm == ALGO_GL_PICK) {
+ BLI_assert(g_select_state.use_cache == true);
gpu_select_pick_cache_end();
}
g_select_state.use_cache = false;
+ /* Paranoid assignment, should already be false. */
+ g_select_state.use_cache_needs_init = false;
}
bool GPU_select_is_cached(void)
@@ -187,16 +213,12 @@ bool GPU_select_is_cached(void)
return g_select_state.use_cache && gpu_select_pick_is_cached();
}
-/* ----------------------------------------------------------------------------
- * Utilities
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
-/**
- * Helper function, nothing special but avoids doing inline since hits aren't sorted by depth
- * and purpose of 4x buffer indices isn't so clear.
- *
- * Note that comparing depth as uint is fine.
- */
const uint *GPU_select_buffer_near(const uint *buffer, int hits)
{
const uint *buffer_near = NULL;
@@ -230,7 +252,6 @@ uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id)
return hits_final;
}
-/* Part of the solution copied from `rect_subregion_stride_calc`. */
void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
{
const int x = dst->xmin - src->xmin;
@@ -269,3 +290,5 @@ void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_
}
memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf));
}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 7fb704c29dd..ddd3dfc6879 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -51,9 +51,9 @@
/* Z-depth of cleared depth buffer */
#define DEPTH_MAX 0xffffffff
-/* ----------------------------------------------------------------------------
- * SubRectStride
- */
+/* -------------------------------------------------------------------- */
+/** \name #SubRectStride
+ * \{ */
/* For looping over a sub-region of a rect, could be moved into 'rct.c'. */
typedef struct SubRectStride {
@@ -99,14 +99,16 @@ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
return (*prev != *curr) && (*curr != DEPTH_MAX);
}
-/* ----------------------------------------------------------------------------
- * DepthBufCache
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #DepthBufCache
*
- * Result of reading glReadPixels,
+ * Result of reading #glReadPixels,
* use for both cache and non-cached storage.
- */
+ * \{ */
-/* store result of glReadPixels */
+/** Store result of #glReadPixels. */
typedef struct DepthBufCache {
struct DepthBufCache *next, *prev;
uint id;
@@ -188,11 +190,13 @@ static bool depth_buf_subrect_depth_any_filled(const DepthBufCache *rect_src,
return false;
}
-/* ----------------------------------------------------------------------------
- * DepthID
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #DepthID
*
* Internal structure for storing hits.
- */
+ * \{ */
typedef struct DepthID {
uint id;
@@ -225,6 +229,12 @@ static int depth_cmp(const void *v1, const void *v2)
return 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Main Selection Begin/End/Load API
+ * \{ */
+
/* depth sorting */
typedef struct GPUPickState {
/* cache on initialization */
@@ -663,7 +673,7 @@ uint gpu_select_pick_end(void)
#endif
/* first 3 are dummy values */
g_pick_state.buffer[hits][0] = 1;
- g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */
+ g_pick_state.buffer[hits][1] = depth_data[i].depth;
g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
g_pick_state.buffer[hits][3] = depth_data[i].id;
hits++;
@@ -691,11 +701,13 @@ uint gpu_select_pick_end(void)
return hits;
}
-/* ----------------------------------------------------------------------------
- * Caching
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Caching
*
* Support multiple begin/end's reusing depth buffers.
- */
+ * \{ */
void gpu_select_pick_cache_begin(void)
{
@@ -718,7 +730,6 @@ void gpu_select_pick_cache_end(void)
BLI_freelistN(&g_pick_state.cache.bufs);
}
-/* is drawing needed? */
bool gpu_select_pick_is_cached(void)
{
return g_pick_state.is_cached;
@@ -749,3 +760,5 @@ void gpu_select_pick_cache_load_id(void)
}
}
}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h
index e49feb3fc50..e5a84a037a6 100644
--- a/source/blender/gpu/intern/gpu_select_private.h
+++ b/source/blender/gpu/intern/gpu_select_private.h
@@ -30,16 +30,21 @@ extern "C" {
#endif
/* gpu_select_pick */
+
void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode);
bool gpu_select_pick_load_id(uint id, bool end);
uint gpu_select_pick_end(void);
void gpu_select_pick_cache_begin(void);
void gpu_select_pick_cache_end(void);
+/**
+ * \return true if drawing is not needed.
+ */
bool gpu_select_pick_is_cached(void);
void gpu_select_pick_cache_load_id(void);
/* gpu_select_sample_query */
+
void gpu_select_query_begin(
uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits);
bool gpu_select_query_load_id(uint id);
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.cc b/source/blender/gpu/intern/gpu_select_sample_query.cc
index 7b9b3020639..a430d4a9d62 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.cc
+++ b/source/blender/gpu/intern/gpu_select_sample_query.cc
@@ -20,8 +20,8 @@
/** \file
* \ingroup gpu
*
- * Interface for accessing gpu-related methods for selection. The semantics will be
- * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility.
+ * Interface for accessing GPU-related methods for selection. The semantics will be
+ * similar to `glRenderMode(GL_SELECT)` since the goal is to maintain compatibility.
*/
#include <cstdlib>
@@ -151,7 +151,7 @@ bool gpu_select_query_load_id(uint id)
return true;
}
-uint gpu_select_query_end(void)
+uint gpu_select_query_end()
{
uint hits = 0;
const uint maxhits = g_query_state.bufsize;
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc
index cab73963620..830e65f69d9 100644
--- a/source/blender/gpu/intern/gpu_shader.cc
+++ b/source/blender/gpu/intern/gpu_shader.cc
@@ -31,10 +31,32 @@
#include "gpu_backend.hh"
#include "gpu_context_private.hh"
+#include "gpu_shader_create_info.hh"
+#include "gpu_shader_create_info_private.hh"
+#include "gpu_shader_dependency_private.h"
#include "gpu_shader_private.hh"
+#include <string>
+
extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
+namespace blender::gpu {
+
+std::string Shader::defines_declare(const shader::ShaderCreateInfo &info) const
+{
+ std::string defines;
+ for (const auto &def : info.defines_) {
+ defines += "#define ";
+ defines += def[0];
+ defines += " ";
+ defines += def[1];
+ defines += "\n";
+ }
+ return defines;
+}
+
+} // namespace blender::gpu
+
using namespace blender;
using namespace blender::gpu;
@@ -59,6 +81,8 @@ static void standard_defines(Vector<const char *> &sources)
BLI_assert(sources.size() == 0);
/* Version needs to be first. Exact values will be added by implementation. */
sources.append("version");
+ /* Define to identify code usage in shading language. */
+ sources.append("#define GPU_SHADER\n");
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
sources.append("#define GPU_ATI\n");
@@ -225,6 +249,188 @@ GPUShader *GPU_shader_create_compute(const char *computecode,
shname);
}
+GPUShader *GPU_shader_create_from_info_name(const char *info_name)
+{
+ using namespace blender::gpu::shader;
+ const GPUShaderCreateInfo *_info = gpu_shader_create_info_get(info_name);
+ const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info);
+ if (!info.do_static_compilation_) {
+ printf("Warning: Trying to compile \"%s\" which was not marked for static compilation.\n",
+ info.name_.c_str());
+ }
+ return GPU_shader_create_from_info(_info);
+}
+
+GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
+{
+ using namespace blender::gpu::shader;
+ const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info);
+
+ const_cast<ShaderCreateInfo &>(info).finalize();
+
+ /* At least a vertex shader and a fragment shader are required, or only a compute shader. */
+ if (info.compute_source_.is_empty()) {
+ if (info.vertex_source_.is_empty()) {
+ printf("Missing vertex shader in %s.\n", info.name_.c_str());
+ }
+ if (info.fragment_source_.is_empty()) {
+ printf("Missing fragment shader in %s.\n", info.name_.c_str());
+ }
+ BLI_assert(!info.vertex_source_.is_empty() && !info.fragment_source_.is_empty());
+ }
+ else {
+ if (!info.vertex_source_.is_empty()) {
+ printf("Compute shader has vertex_source_ shader attached in %s.\n", info.name_.c_str());
+ }
+ if (!info.geometry_source_.is_empty()) {
+ printf("Compute shader has geometry_source_ shader attached in %s.\n", info.name_.c_str());
+ }
+ if (!info.fragment_source_.is_empty()) {
+ printf("Compute shader has fragment_source_ shader attached in %s.\n", info.name_.c_str());
+ }
+ BLI_assert(info.vertex_source_.is_empty() && info.geometry_source_.is_empty() &&
+ info.fragment_source_.is_empty());
+ }
+
+ Shader *shader = GPUBackend::get()->shader_alloc(info.name_.c_str());
+
+ std::string defines = shader->defines_declare(info);
+ std::string resources = shader->resources_declare(info);
+ char *shader_shared_utils = nullptr;
+
+ defines += "#define USE_GPU_SHADER_CREATE_INFO\n";
+
+ Vector<char *> typedefs;
+ for (auto filename : info.typedef_sources_) {
+ typedefs.append(gpu_shader_dependency_get_source(filename.c_str()));
+ }
+ if (!typedefs.is_empty()) {
+ shader_shared_utils = gpu_shader_dependency_get_source("gpu_shader_shared_utils.h");
+ }
+
+ if (!info.vertex_source_.is_empty()) {
+ uint32_t builtins = 0;
+ std::string interface = shader->vertex_interface_declare(info);
+ char *code = gpu_shader_dependency_get_resolved_source(info.vertex_source_.c_str(), &builtins);
+
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_VERTEX_SHADER\n");
+ if (!info.geometry_source_.is_empty()) {
+ sources.append("#define USE_GEOMETRY_SHADER\n");
+ }
+ sources.append(defines.c_str());
+ if (!typedefs.is_empty()) {
+ sources.append(shader_shared_utils);
+ }
+ for (auto *types : typedefs) {
+ sources.append(types);
+ }
+ sources.append(resources.c_str());
+ sources.append(interface.c_str());
+ sources.append(code);
+
+ shader->vertex_shader_from_glsl(sources);
+
+ free(code);
+ }
+
+ if (!info.fragment_source_.is_empty()) {
+ uint32_t builtins = 0;
+ std::string interface = shader->fragment_interface_declare(info);
+ char *code = gpu_shader_dependency_get_resolved_source(info.fragment_source_.c_str(),
+ &builtins);
+
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_FRAGMENT_SHADER\n");
+ if (!info.geometry_source_.is_empty()) {
+ sources.append("#define USE_GEOMETRY_SHADER\n");
+ }
+ sources.append(defines.c_str());
+ if (!typedefs.is_empty()) {
+ sources.append(shader_shared_utils);
+ }
+ for (auto *types : typedefs) {
+ sources.append(types);
+ }
+ sources.append(resources.c_str());
+ sources.append(interface.c_str());
+ sources.append(code);
+
+ shader->fragment_shader_from_glsl(sources);
+
+ free(code);
+ }
+
+ if (!info.geometry_source_.is_empty()) {
+ uint32_t builtins = 0;
+ std::string interface = shader->geometry_interface_declare(info);
+ std::string layout = shader->geometry_layout_declare(info);
+ char *code = gpu_shader_dependency_get_resolved_source(info.geometry_source_.c_str(),
+ &builtins);
+
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_GEOMETRY_SHADER\n");
+ sources.append(defines.c_str());
+ if (!typedefs.is_empty()) {
+ sources.append(shader_shared_utils);
+ }
+ for (auto *types : typedefs) {
+ sources.append(types);
+ }
+ sources.append(resources.c_str());
+ sources.append(layout.c_str());
+ sources.append(interface.c_str());
+ sources.append(code);
+
+ shader->geometry_shader_from_glsl(sources);
+
+ free(code);
+ }
+
+ if (!info.compute_source_.is_empty()) {
+ uint32_t builtins = 0;
+ char *code = gpu_shader_dependency_get_resolved_source(info.compute_source_.c_str(),
+ &builtins);
+ std::string layout = shader->compute_layout_declare(info);
+
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_COMPUTE_SHADER\n");
+ sources.append(defines.c_str());
+ if (!typedefs.is_empty()) {
+ sources.append(shader_shared_utils);
+ }
+ for (auto *types : typedefs) {
+ sources.append(types);
+ }
+ sources.append(resources.c_str());
+ sources.append(layout.c_str());
+ sources.append(code);
+
+ shader->compute_shader_from_glsl(sources);
+
+ free(code);
+ }
+
+ for (auto *types : typedefs) {
+ free(types);
+ }
+
+ if (shader_shared_utils) {
+ free(shader_shared_utils);
+ }
+
+ if (!shader->finalize(&info)) {
+ delete shader;
+ return nullptr;
+ }
+
+ return wrap(shader);
+}
+
GPUShader *GPU_shader_create_from_python(const char *vertcode,
const char *fragcode,
const char *geomcode,
@@ -284,26 +490,6 @@ static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_i
return str_arr[0];
}
-/**
- * Use via #GPU_shader_create_from_arrays macro (avoids passing in param).
- *
- * Similar to #DRW_shader_create_with_lib with the ability to include libs for each type of shader.
- *
- * It has the advantage that each item can be conditionally included
- * without having to build the string inline, then free it.
- *
- * \param params: NULL terminated arrays of strings.
- *
- * Example:
- * \code{.c}
- * sh = GPU_shader_create_from_arrays({
- * .vert = (const char *[]){shader_lib_glsl, shader_vert_glsl, NULL},
- * .geom = (const char *[]){shader_geom_glsl, NULL},
- * .frag = (const char *[]){shader_frag_glsl, NULL},
- * .defs = (const char *[]){"#define DEFINE\n", test ? "#define OTHER_DEFINE\n" : "", NULL},
- * });
- * \endcode
- */
struct GPUShader *GPU_shader_create_from_arrays_impl(
const struct GPU_ShaderCreateFromArray_Params *params, const char *func, int line)
{
@@ -359,7 +545,7 @@ void GPU_shader_bind(GPUShader *gpu_shader)
}
}
-void GPU_shader_unbind(void)
+void GPU_shader_unbind()
{
#ifndef NDEBUG
Context *ctx = Context::get();
@@ -437,7 +623,6 @@ int GPU_shader_get_ssbo(GPUShader *shader, const char *name)
return ssbo ? ssbo->location : -1;
}
-/* DEPRECATED. */
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
{
ShaderInterface *interface = unwrap(shader)->interface;
@@ -472,7 +657,6 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name)
/** \name Getters
* \{ */
-/* DEPRECATED: Kept only because of BGL API */
int GPU_shader_get_program(GPUShader *shader)
{
return unwrap(shader)->program_handle_get();
diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc
new file mode 100644
index 00000000000..334bdb2ec58
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_builder.cc
@@ -0,0 +1,102 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Compile time automation of shader compilation and validation.
+ */
+
+#include <iostream>
+
+#include "GHOST_C-api.h"
+
+#include "GPU_context.h"
+#include "GPU_init_exit.h"
+#include "gpu_shader_create_info_private.hh"
+
+#include "CLG_log.h"
+
+namespace blender::gpu::shader_builder {
+
+class ShaderBuilder {
+ private:
+ GHOST_SystemHandle ghost_system_;
+ GHOST_ContextHandle ghost_context_;
+ GPUContext *gpu_context_ = nullptr;
+
+ public:
+ void init();
+ bool bake_create_infos();
+ void exit();
+};
+
+bool ShaderBuilder::bake_create_infos()
+{
+ return gpu_shader_create_info_compile_all();
+}
+
+void ShaderBuilder::init()
+{
+ CLG_init();
+
+ GHOST_GLSettings glSettings = {0};
+ ghost_system_ = GHOST_CreateSystem();
+ ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings);
+ GHOST_ActivateOpenGLContext(ghost_context_);
+
+ gpu_context_ = GPU_context_create(nullptr);
+ GPU_init();
+}
+
+void ShaderBuilder::exit()
+{
+ GPU_backend_exit();
+ GPU_exit();
+
+ GPU_context_discard(gpu_context_);
+
+ GHOST_DisposeOpenGLContext(ghost_system_, ghost_context_);
+ GHOST_DisposeSystem(ghost_system_);
+
+ CLG_exit();
+}
+
+} // namespace blender::gpu::shader_builder
+
+/** \brief Entry point for the shader_builder. */
+int main(int argc, const char *argv[])
+{
+ if (argc < 2) {
+ printf("Usage: %s <data_file_to>\n", argv[0]);
+ exit(1);
+ }
+
+ int exit_code = 0;
+
+ blender::gpu::shader_builder::ShaderBuilder builder;
+ builder.init();
+ if (!builder.bake_create_infos()) {
+ exit_code = 1;
+ }
+ builder.exit();
+ exit(exit_code);
+
+ return exit_code;
+}
diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
new file mode 100644
index 00000000000..40e54ab4394
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
@@ -0,0 +1,258 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Stubs to reduce linking time for shader_builder.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_node.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_subdiv_ccg.h"
+
+#include "DNA_userdef_types.h"
+
+#include "DRW_engine.h"
+
+#include "bmesh.h"
+
+#include "UI_resources.h"
+
+extern "C" {
+
+Global G;
+UserDef U;
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BLI_imbuf_types.h
+ * \{ */
+
+void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
+{
+ BLI_assert_unreachable();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of UI_resources.h
+ * \{ */
+
+void UI_GetThemeColor4fv(int UNUSED(colorid), float UNUSED(col[4]))
+{
+ BLI_assert_unreachable();
+}
+
+void UI_GetThemeColor3fv(int UNUSED(colorid), float UNUSED(col[3]))
+{
+ BLI_assert_unreachable();
+}
+
+void UI_GetThemeColorShade4fv(int UNUSED(colorid), int UNUSED(offset), float UNUSED(col[4]))
+{
+ BLI_assert_unreachable();
+}
+
+void UI_GetThemeColorShadeAlpha4fv(int UNUSED(colorid),
+ int UNUSED(coloffset),
+ int UNUSED(alphaoffset),
+ float UNUSED(col[4]))
+{
+ BLI_assert_unreachable();
+}
+void UI_GetThemeColorBlendShade4fv(int UNUSED(colorid1),
+ int UNUSED(colorid2),
+ float UNUSED(fac),
+ int UNUSED(offset),
+ float UNUSED(col[4]))
+{
+ BLI_assert_unreachable();
+}
+
+void UI_GetThemeColorBlend3ubv(int UNUSED(colorid1),
+ int UNUSED(colorid2),
+ float UNUSED(fac),
+ unsigned char UNUSED(col[3]))
+{
+ BLI_assert_unreachable();
+}
+
+void UI_GetThemeColorShadeAlpha4ubv(int UNUSED(colorid),
+ int UNUSED(coloffset),
+ int UNUSED(alphaoffset),
+ unsigned char UNUSED(col[4]))
+{
+ BLI_assert_unreachable();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_paint.h
+ * \{ */
+bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt),
+ const struct MVert *UNUSED(mvert),
+ const struct MLoop *UNUSED(mloop))
+{
+ BLI_assert_unreachable();
+ return false;
+}
+
+void BKE_paint_face_set_overlay_color_get(const int UNUSED(face_set),
+ const int UNUSED(seed),
+ uchar UNUSED(r_color[4]))
+{
+ BLI_assert_unreachable();
+}
+
+bool paint_is_grid_face_hidden(const unsigned int *UNUSED(grid_hidden),
+ int UNUSED(gridsize),
+ int UNUSED(x),
+ int UNUSED(y))
+{
+ BLI_assert_unreachable();
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_mesh.h
+ * \{ */
+void BKE_mesh_calc_poly_normal(const struct MPoly *UNUSED(mpoly),
+ const struct MLoop *UNUSED(loopstart),
+ const struct MVert *UNUSED(mvarray),
+ float UNUSED(r_no[3]))
+{
+ BLI_assert_unreachable();
+}
+
+void BKE_mesh_looptri_get_real_edges(const struct Mesh *UNUSED(mesh),
+ const struct MLoopTri *UNUSED(looptri),
+ int UNUSED(r_edges[3]))
+{
+ BLI_assert_unreachable();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_material.h
+ * \{ */
+
+void BKE_material_defaults_free_gpu(void)
+{
+ /* This function is reachable via GPU_exit. */
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_customdata.h
+ * \{ */
+
+int CustomData_get_offset(const struct CustomData *UNUSED(data), int UNUSED(type))
+{
+ BLI_assert_unreachable();
+ return 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_pbvh.h
+ * \{ */
+
+int BKE_pbvh_count_grid_quads(BLI_bitmap **UNUSED(grid_hidden),
+ const int *UNUSED(grid_indices),
+ int UNUSED(totgrid),
+ int UNUSED(gridsize))
+{
+ BLI_assert_unreachable();
+ return 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_subdiv_ccg.h
+ * \{ */
+int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *UNUSED(subdiv_ccg),
+ const int UNUSED(grid_index))
+{
+ BLI_assert_unreachable();
+ return 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of BKE_node.h
+ * \{ */
+void ntreeGPUMaterialNodes(struct bNodeTree *UNUSED(localtree),
+ struct GPUMaterial *UNUSED(mat),
+ bool *UNUSED(has_surface_output),
+ bool *UNUSED(has_volume_output))
+{
+ BLI_assert_unreachable();
+}
+
+struct bNodeTree *ntreeLocalize(struct bNodeTree *UNUSED(ntree))
+{
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
+void ntreeFreeLocalTree(struct bNodeTree *UNUSED(ntree))
+{
+ BLI_assert_unreachable();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of bmesh.h
+ * \{ */
+void BM_face_as_array_vert_tri(BMFace *UNUSED(f), BMVert *UNUSED(r_verts[3]))
+{
+ BLI_assert_unreachable();
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stubs of DRW_engine.h
+ * \{ */
+void DRW_deferred_shader_remove(struct GPUMaterial *UNUSED(mat))
+{
+ BLI_assert_unreachable();
+}
+
+/** \} */
+}
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index 9ea46788f44..6b1163fdc78 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -77,6 +77,7 @@ extern char datatoc_gpu_shader_image_overlays_merge_frag_glsl[];
extern char datatoc_gpu_shader_image_overlays_stereo_merge_frag_glsl[];
extern char datatoc_gpu_shader_image_color_frag_glsl[];
extern char datatoc_gpu_shader_image_desaturate_frag_glsl[];
+extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
@@ -92,28 +93,15 @@ extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[];
-extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[];
-extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
-extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[];
-extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[];
-extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[];
extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[];
-extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[];
-
-extern char datatoc_gpu_shader_2D_edituvs_points_vert_glsl[];
-extern char datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl[];
-extern char datatoc_gpu_shader_2D_edituvs_edges_vert_glsl[];
-extern char datatoc_gpu_shader_2D_edituvs_edges_frag_glsl[];
-extern char datatoc_gpu_shader_2D_edituvs_faces_vert_glsl[];
-extern char datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
@@ -157,133 +145,97 @@ typedef struct {
const char *frag;
/** Optional. */
const char *defs;
+
+ const char *create_info;
+ const char *clipped_create_info;
} GPUShaderStages;
static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
[GPU_SHADER_TEXT] =
{
.name = "GPU_SHADER_TEXT",
- .vert = datatoc_gpu_shader_text_vert_glsl,
- .frag = datatoc_gpu_shader_text_frag_glsl,
+ .create_info = "gpu_shader_text",
},
[GPU_SHADER_KEYFRAME_SHAPE] =
{
.name = "GPU_SHADER_KEYFRAME_SHAPE",
- .vert = datatoc_gpu_shader_keyframe_shape_vert_glsl,
- .frag = datatoc_gpu_shader_keyframe_shape_frag_glsl,
+ .create_info = "gpu_shader_keyframe_shape",
},
[GPU_SHADER_SIMPLE_LIGHTING] =
{
.name = "GPU_SHADER_SIMPLE_LIGHTING",
- .vert = datatoc_gpu_shader_3D_normal_vert_glsl,
- .frag = datatoc_gpu_shader_simple_lighting_frag_glsl,
+ .create_info = "gpu_shader_simple_lighting",
+ },
+ [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] =
+ {
+ .name = "GPU_SHADER_3D_IMAGE_MODULATE_ALPHA",
+ .create_info = "gpu_shader_3D_image_modulate_alpha",
},
-
[GPU_SHADER_2D_CHECKER] =
{
.name = "GPU_SHADER_2D_CHECKER",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_checker_frag_glsl,
+ .create_info = "gpu_shader_2D_checker",
},
[GPU_SHADER_2D_DIAG_STRIPES] =
{
.name = "GPU_SHADER_2D_DIAG_STRIPES",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_diag_stripes_frag_glsl,
+ .create_info = "gpu_shader_2D_diag_stripes",
},
- [GPU_SHADER_2D_UNIFORM_COLOR] =
- {
- .name = "GPU_SHADER_2D_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_uniform_color_frag_glsl,
- },
- [GPU_SHADER_2D_FLAT_COLOR] =
- {
- .name = "GPU_SHADER_2D_FLAT_COLOR",
- .vert = datatoc_gpu_shader_2D_flat_color_vert_glsl,
- .frag = datatoc_gpu_shader_flat_color_frag_glsl,
- },
- [GPU_SHADER_2D_SMOOTH_COLOR] =
- {
- .name = "GPU_SHADER_2D_SMOOTH_COLOR",
- .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl,
- },
+ [GPU_SHADER_2D_UNIFORM_COLOR] = {.name = "GPU_SHADER_2D_UNIFORM_COLOR",
+ .create_info = "gpu_shader_2D_uniform_color"},
+ [GPU_SHADER_2D_FLAT_COLOR] = {.name = "GPU_SHADER_2D_FLAT_COLOR",
+ .create_info = "gpu_shader_2D_flat_color"},
+ [GPU_SHADER_2D_SMOOTH_COLOR] = {.name = "GPU_SHADER_2D_SMOOTH_COLOR",
+ .create_info = "gpu_shader_2D_smooth_color"},
[GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
{
.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
+#ifdef __APPLE__
+ /* GPUShaderCreateInfo is disabled on MacOS due to mismatch with OCIO shader. See
+ * T95052 for more details. */
.vert = datatoc_gpu_shader_2D_image_vert_glsl,
.frag = datatoc_gpu_shader_image_overlays_merge_frag_glsl,
+#else
+ .create_info = "gpu_shader_2D_image_overlays_merge",
+#endif
},
[GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE] =
- {
- .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_overlays_stereo_merge_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE] =
- {
- .name = "GPU_SHADER_2D_IMAGE",
- .vert = datatoc_gpu_shader_2D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE_COLOR] =
- {
- .name = "GPU_SHADER_2D_IMAGE_COLOR",
- .vert = datatoc_gpu_shader_2D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_color_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] =
- {
- .name = "GPU_SHADER_2D_IMAGE_DESATURATE_COLOR",
- .vert = datatoc_gpu_shader_2D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_desaturate_frag_glsl,
- },
+ {.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE",
+ .create_info = "gpu_shader_2D_image_overlays_stereo_merge"},
+ [GPU_SHADER_2D_IMAGE] = {.name = "GPU_SHADER_2D_IMAGE", .create_info = "gpu_shader_2D_image"},
+ [GPU_SHADER_2D_IMAGE_COLOR] = {.name = "GPU_SHADER_2D_IMAGE_COLOR",
+ .create_info = "gpu_shader_2D_image_color"},
+ [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = {.name = "GPU_SHADER_2D_IMAGE_DESATURATE_COLOR",
+ .create_info =
+ "gpu_shader_2D_image_desaturate_color"},
[GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] =
{
.name = "GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR",
- .vert = datatoc_gpu_shader_2D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_shuffle_color_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE_RECT_COLOR] =
- {
- .name = "GPU_SHADER_2D_IMAGE_RECT_COLOR",
- .vert = datatoc_gpu_shader_2D_image_rect_vert_glsl,
- .frag = datatoc_gpu_shader_image_color_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] =
- {
- .name = "GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR",
- .vert = datatoc_gpu_shader_2D_image_multi_rect_vert_glsl,
- .frag = datatoc_gpu_shader_image_varying_color_frag_glsl,
+ .create_info = "gpu_shader_2D_image_shuffle_color",
},
+ [GPU_SHADER_2D_IMAGE_RECT_COLOR] = {.name = "GPU_SHADER_2D_IMAGE_RECT_COLOR",
+ .create_info = "gpu_shader_2D_image_rect_color"},
+ [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = {.name = "GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR",
+ .create_info =
+ "gpu_shader_2D_image_multi_rect_color"},
[GPU_SHADER_3D_UNIFORM_COLOR] =
{
.name = "GPU_SHADER_3D_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_3D_vert_glsl,
- .frag = datatoc_gpu_shader_uniform_color_frag_glsl,
- },
- [GPU_SHADER_3D_FLAT_COLOR] =
- {
- .name = "GPU_SHADER_3D_FLAT_COLOR",
- .vert = datatoc_gpu_shader_3D_flat_color_vert_glsl,
- .frag = datatoc_gpu_shader_flat_color_frag_glsl,
- },
- [GPU_SHADER_3D_SMOOTH_COLOR] =
- {
- .name = "GPU_SHADER_3D_SMOOTH_COLOR",
- .vert = datatoc_gpu_shader_3D_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_3D_smooth_color_frag_glsl,
- },
- [GPU_SHADER_3D_DEPTH_ONLY] =
- {
- .name = "GPU_SHADER_3D_DEPTH_ONLY",
- .vert = datatoc_gpu_shader_3D_vert_glsl,
- .frag = datatoc_gpu_shader_depth_only_frag_glsl,
- },
+ .create_info = "gpu_shader_3D_uniform_color",
+ .clipped_create_info = "gpu_shader_3D_uniform_color_clipped",
+ },
+ [GPU_SHADER_3D_FLAT_COLOR] = {.name = "GPU_SHADER_3D_FLAT_COLOR",
+ .create_info = "gpu_shader_3D_flat_color",
+ .clipped_create_info = "gpu_shader_3D_flat_color_clipped"},
+ [GPU_SHADER_3D_SMOOTH_COLOR] = {.name = "GPU_SHADER_3D_SMOOTH_COLOR",
+ .create_info = "gpu_shader_3D_smooth_color",
+ .clipped_create_info = "gpu_shader_3D_smooth_color_clipped"},
+ [GPU_SHADER_3D_DEPTH_ONLY] = {.name = "GPU_SHADER_3D_DEPTH_ONLY",
+ .create_info = "gpu_shader_3D_depth_only",
+ .clipped_create_info = "gpu_shader_3D_depth_only_clipped"},
[GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] =
{
.name = "GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR",
@@ -338,72 +290,26 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl,
},
- [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
- {
- .name = "GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl,
- },
- [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
- {
- .name = "GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR",
- .vert = datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_frag_glsl,
- },
[GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
{
.name = "GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA",
- .vert = datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl,
+ .create_info = "gpu_shader_2D_point_uniform_size_uniform_color_aa",
},
[GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
{
.name = "GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA",
- .vert = datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl,
- },
- [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] =
- {
- .name = "GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA",
- .vert = datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl,
- },
- [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
- {
- .name = "GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_3D_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl,
+ .create_info = "gpu_shader_2D_point_uniform_size_uniform_color_outline_aa",
},
[GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] =
- {
- .name = "GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR",
- .vert = datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_frag_glsl,
- },
- [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] =
- {
- .name = "GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_3D_point_varying_size_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl,
- },
+ {.name = "GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR",
+ .create_info = "gpu_shader_3D_point_fixed_size_varying_color"},
[GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] =
- {
- .name = "GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR",
- .vert = datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_frag_glsl,
- },
+ {.name = "GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR",
+ .create_info = "gpu_shader_3D_point_varying_size_varying_color"},
[GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
- {
- .name = "GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA",
- .vert = datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl,
- },
- [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
- {
- .name = "GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA",
- .vert = datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl,
- .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl,
- },
+ {.name = "GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA",
+ .create_info = "gpu_shader_3D_point_uniform_size_uniform_color_aa",
+ .clipped_create_info = "gpu_shader_3D_point_uniform_size_uniform_color_aa_clipped"},
[GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
{
@@ -413,12 +319,8 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.defs = "#define UNIFORM_SCALE\n",
},
- [GPU_SHADER_2D_AREA_EDGES] =
- {
- .name = "GPU_SHADER_2D_AREA_EDGES",
- .vert = datatoc_gpu_shader_2D_area_borders_vert_glsl,
- .frag = datatoc_gpu_shader_2D_area_borders_frag_glsl,
- },
+ [GPU_SHADER_2D_AREA_BORDERS] = {.name = "GPU_SHADER_2D_AREA_BORDERS",
+ .create_info = "gpu_shader_2D_area_borders"},
[GPU_SHADER_2D_WIDGET_BASE] =
{
.name = "GPU_SHADER_2D_WIDGET_BASE",
@@ -438,79 +340,14 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_2D_widget_shadow_vert_glsl,
.frag = datatoc_gpu_shader_2D_widget_shadow_frag_glsl,
},
- [GPU_SHADER_2D_NODELINK] =
- {
- .name = "GPU_SHADER_2D_NODELINK",
- .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl,
- .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl,
- },
- [GPU_SHADER_2D_NODELINK_INST] =
- {
- .name = "GPU_SHADER_2D_NODELINK_INST",
- .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl,
- .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl,
- .defs = "#define USE_INSTANCE\n",
- },
+ [GPU_SHADER_2D_NODELINK] = {.name = "GPU_SHADER_2D_NODELINK",
+ .create_info = "gpu_shader_2D_nodelink"},
- [GPU_SHADER_2D_UV_UNIFORM_COLOR] =
- {
- .name = "GPU_SHADER_2D_UV_UNIFORM_COLOR",
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_uniform_color_frag_glsl,
- .defs = "#define UV_POS\n",
- },
- [GPU_SHADER_2D_UV_VERTS] =
- {
- .name = "GPU_SHADER_2D_UV_VERTS",
- .vert = datatoc_gpu_shader_2D_edituvs_points_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl,
- },
- [GPU_SHADER_2D_UV_FACEDOTS] =
- {
- .name = "GPU_SHADER_2D_UV_FACEDOTS",
- .vert = datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl,
- .frag = datatoc_gpu_shader_point_varying_color_frag_glsl,
- },
- [GPU_SHADER_2D_UV_EDGES] =
- {
- .name = "GPU_SHADER_2D_UV_EDGES",
- .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl,
- .frag = datatoc_gpu_shader_2D_edituvs_edges_frag_glsl,
- },
- [GPU_SHADER_2D_UV_EDGES_SMOOTH] =
- {
- .name = "GPU_SHADER_2D_UV_EDGES_SMOOTH",
- .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl,
- .frag = datatoc_gpu_shader_2D_edituvs_edges_frag_glsl,
- .defs = "#define SMOOTH_COLOR\n",
- },
- [GPU_SHADER_2D_UV_FACES] =
- {
- .name = "GPU_SHADER_2D_UV_FACES",
- .vert = datatoc_gpu_shader_2D_edituvs_faces_vert_glsl,
- .frag = datatoc_gpu_shader_flat_color_frag_glsl,
- },
- [GPU_SHADER_2D_UV_FACES_STRETCH_AREA] =
- {
- .name = "GPU_SHADER_2D_UV_FACES_STRETCH_AREA",
- .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl,
- .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl,
- },
- [GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE] =
- {
- .name = "GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE",
- .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl,
- .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl,
- .defs = "#define STRETCH_ANGLE\n",
- },
+ [GPU_SHADER_2D_NODELINK_INST] = {.name = "GPU_SHADER_2D_NODELINK_INST",
+ .create_info = "gpu_shader_2D_nodelink_inst"},
- [GPU_SHADER_GPENCIL_STROKE] =
- {
- .name = "GPU_SHADER_GPENCIL_STROKE",
- .vert = datatoc_gpu_shader_gpencil_stroke_vert_glsl,
- .geom = datatoc_gpu_shader_gpencil_stroke_geom_glsl,
- .frag = datatoc_gpu_shader_gpencil_stroke_frag_glsl,
- },
+ [GPU_SHADER_GPENCIL_STROKE] = {.name = "GPU_SHADER_GPENCIL_STROKE",
+ .create_info = "gpu_shader_gpencil_stroke"},
};
GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
@@ -525,14 +362,20 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
/* common case */
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
- *sh_p = GPU_shader_create_from_arrays_named(
- stages->name,
- {
- .vert = (const char *[]){stages->vert, NULL},
- .geom = (const char *[]){stages->geom, NULL},
- .frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
- .defs = (const char *[]){stages->defs, NULL},
- });
+ if (stages->create_info != NULL) {
+ *sh_p = GPU_shader_create_from_info_name(stages->create_info);
+ }
+ else {
+ *sh_p = GPU_shader_create_from_arrays_named(
+ stages->name,
+ {
+ .vert = (const char *[]){stages->vert, NULL},
+ .geom = (const char *[]){stages->geom, NULL},
+ .frag =
+ (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
+ .defs = (const char *[]){stages->defs, NULL},
+ });
+ }
}
else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
/* Remove eventually, for now ensure support for each shader has been added. */
@@ -541,21 +384,26 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
GPU_SHADER_3D_SMOOTH_COLOR,
GPU_SHADER_3D_DEPTH_ONLY,
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE,
- GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
GPU_SHADER_3D_FLAT_COLOR,
GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR));
- const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl;
- const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n";
/* In rare cases geometry shaders calculate clipping themselves. */
- *sh_p = GPU_shader_create_from_arrays_named(
- stages->name,
- {
- .vert = (const char *[]){world_clip_lib, stages->vert, NULL},
- .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL},
- .frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
- .defs = (const char *[]){world_clip_def, stages->defs, NULL},
- });
+ if (stages->clipped_create_info != NULL) {
+ *sh_p = GPU_shader_create_from_info_name(stages->clipped_create_info);
+ }
+ else {
+ const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl;
+ const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n";
+ *sh_p = GPU_shader_create_from_arrays_named(
+ stages->name,
+ {
+ .vert = (const char *[]){world_clip_lib, stages->vert, NULL},
+ .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL},
+ .frag =
+ (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
+ .defs = (const char *[]){world_clip_def, stages->defs, NULL},
+ });
+ }
}
else {
BLI_assert(0);
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
new file mode 100644
index 00000000000..f7622751726
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -0,0 +1,263 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Descriptor type used to define shader structure, resources and interfaces.
+ */
+
+#include "BLI_map.hh"
+#include "BLI_set.hh"
+#include "BLI_string_ref.hh"
+
+#include "GPU_capabilities.h"
+#include "GPU_platform.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "gpu_shader_create_info.hh"
+#include "gpu_shader_create_info_private.hh"
+
+#undef GPU_SHADER_INTERFACE_INFO
+#undef GPU_SHADER_CREATE_INFO
+
+namespace blender::gpu::shader {
+
+using CreateInfoDictionnary = Map<StringRef, ShaderCreateInfo *>;
+using InterfaceDictionnary = Map<StringRef, StageInterfaceInfo *>;
+
+static CreateInfoDictionnary *g_create_infos = nullptr;
+static InterfaceDictionnary *g_interfaces = nullptr;
+
+void ShaderCreateInfo::finalize()
+{
+ if (finalized_) {
+ return;
+ }
+ finalized_ = true;
+
+ for (auto &info_name : additional_infos_) {
+ const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(
+ gpu_shader_create_info_get(info_name.c_str()));
+
+ /* Recursive. */
+ const_cast<ShaderCreateInfo &>(info).finalize();
+
+#if 0 /* Enabled for debugging merging. TODO(fclem) exception handling and error reporting in \
+ console. */
+ std::cout << "Merging : " << info_name << " > " << name_ << std::endl;
+#endif
+
+ interface_names_size_ += info.interface_names_size_;
+
+ vertex_inputs_.extend(info.vertex_inputs_);
+ fragment_outputs_.extend(info.fragment_outputs_);
+ vertex_out_interfaces_.extend(info.vertex_out_interfaces_);
+ geometry_out_interfaces_.extend(info.geometry_out_interfaces_);
+
+ push_constants_.extend(info.push_constants_);
+ defines_.extend(info.defines_);
+
+ batch_resources_.extend(info.batch_resources_);
+ pass_resources_.extend(info.pass_resources_);
+ typedef_sources_.extend_non_duplicates(info.typedef_sources_);
+
+ validate(info);
+
+ if (info.compute_layout_.local_size_x != -1) {
+ compute_layout_.local_size_x = info.compute_layout_.local_size_x;
+ compute_layout_.local_size_y = info.compute_layout_.local_size_y;
+ compute_layout_.local_size_z = info.compute_layout_.local_size_z;
+ }
+
+ if (!info.vertex_source_.is_empty()) {
+ BLI_assert(vertex_source_.is_empty());
+ vertex_source_ = info.vertex_source_;
+ }
+ if (!info.geometry_source_.is_empty()) {
+ BLI_assert(geometry_source_.is_empty());
+ geometry_source_ = info.geometry_source_;
+ geometry_layout_ = info.geometry_layout_;
+ }
+ if (!info.fragment_source_.is_empty()) {
+ BLI_assert(fragment_source_.is_empty());
+ fragment_source_ = info.fragment_source_;
+ }
+ if (!info.compute_source_.is_empty()) {
+ BLI_assert(compute_source_.is_empty());
+ compute_source_ = info.compute_source_;
+ }
+
+ do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_;
+ }
+}
+
+void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
+{
+ {
+ /* Check same bind-points usage in OGL. */
+ Set<int> images, samplers, ubos, ssbos;
+
+ auto register_resource = [&](const Resource &res) -> bool {
+ switch (res.bind_type) {
+ case Resource::BindType::UNIFORM_BUFFER:
+ return images.add(res.slot);
+ case Resource::BindType::STORAGE_BUFFER:
+ return samplers.add(res.slot);
+ case Resource::BindType::SAMPLER:
+ return ubos.add(res.slot);
+ case Resource::BindType::IMAGE:
+ return ssbos.add(res.slot);
+ default:
+ return false;
+ }
+ };
+
+ auto print_error_msg = [&](const Resource &res) {
+ std::cerr << name_ << ": Validation failed : Overlapping ";
+
+ switch (res.bind_type) {
+ case Resource::BindType::UNIFORM_BUFFER:
+ std::cerr << "Uniform Buffer " << res.uniformbuf.name;
+ break;
+ case Resource::BindType::STORAGE_BUFFER:
+ std::cerr << "Storage Buffer " << res.storagebuf.name;
+ break;
+ case Resource::BindType::SAMPLER:
+ std::cerr << "Sampler " << res.sampler.name;
+ break;
+ case Resource::BindType::IMAGE:
+ std::cerr << "Image " << res.image.name;
+ break;
+ default:
+ std::cerr << "Unknown Type";
+ break;
+ }
+ std::cerr << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
+ };
+
+ for (auto &res : batch_resources_) {
+ if (register_resource(res) == false) {
+ print_error_msg(res);
+ }
+ }
+
+ for (auto &res : pass_resources_) {
+ if (register_resource(res) == false) {
+ print_error_msg(res);
+ }
+ }
+ }
+ {
+ /* TODO(fclem) Push constant validation. */
+ }
+}
+
+} // namespace blender::gpu::shader
+
+using namespace blender::gpu::shader;
+
+void gpu_shader_create_info_init()
+{
+ g_create_infos = new CreateInfoDictionnary();
+ g_interfaces = new InterfaceDictionnary();
+
+#define GPU_SHADER_INTERFACE_INFO(_interface, _inst_name) \
+ auto *ptr_##_interface = new StageInterfaceInfo(#_interface, _inst_name); \
+ auto &_interface = *ptr_##_interface; \
+ g_interfaces->add_new(#_interface, ptr_##_interface); \
+ _interface
+
+#define GPU_SHADER_CREATE_INFO(_info) \
+ auto *ptr_##_info = new ShaderCreateInfo(#_info); \
+ auto &_info = *ptr_##_info; \
+ g_create_infos->add_new(#_info, ptr_##_info); \
+ _info
+
+/* Declare, register and construct the infos. */
+#include "gpu_shader_create_info_list.hh"
+
+/* Baked shader data appended to create infos. */
+/* TODO(jbakker): should call a function with a callback. so we could switch implementations.
+ * We cannot compile bf_gpu twice. */
+#ifdef GPU_RUNTIME
+# include "gpu_shader_baked.hh"
+#endif
+
+ /* WORKAROUND: Replace draw_mesh info with the legacy one for systems that have problems with UBO
+ * indexing. */
+ if (GPU_type_matches(GPU_DEVICE_INTEL | GPU_DEVICE_INTEL_UHD, GPU_OS_ANY, GPU_DRIVER_ANY) ||
+ GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY) || GPU_crappy_amd_driver()) {
+ draw_modelmat = draw_modelmat_legacy;
+ }
+
+ /* TEST */
+ // gpu_shader_create_info_compile_all();
+}
+
+void gpu_shader_create_info_exit()
+{
+ for (auto *value : g_create_infos->values()) {
+ delete value;
+ }
+ delete g_create_infos;
+
+ for (auto *value : g_interfaces->values()) {
+ delete value;
+ }
+ delete g_interfaces;
+}
+
+bool gpu_shader_create_info_compile_all()
+{
+ int success = 0;
+ int total = 0;
+ for (ShaderCreateInfo *info : g_create_infos->values()) {
+ if (info->do_static_compilation_) {
+ total++;
+ GPUShader *shader = GPU_shader_create_from_info(
+ reinterpret_cast<const GPUShaderCreateInfo *>(info));
+ if (shader == nullptr) {
+ printf("Compilation %s Failed\n", info->name_.c_str());
+ }
+ else {
+ success++;
+ }
+ GPU_shader_free(shader);
+ }
+ }
+ printf("===============================\n");
+ printf("Shader Test compilation result: \n");
+ printf("%d Total\n", total);
+ printf("%d Passed\n", success);
+ printf("%d Failed\n", total - success);
+ printf("===============================\n");
+ return success == total;
+}
+
+/* Runtime create infos are not registered in the dictionary and cannot be searched. */
+const GPUShaderCreateInfo *gpu_shader_create_info_get(const char *info_name)
+{
+ if (g_create_infos->contains(info_name) == false) {
+ printf("Error: Cannot find shader create info named \"%s\"\n", info_name);
+ }
+ ShaderCreateInfo *info = g_create_infos->lookup(info_name);
+ return reinterpret_cast<const GPUShaderCreateInfo *>(info);
+}
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
new file mode 100644
index 00000000000..6236e92a226
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -0,0 +1,622 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Descriptor type used to define shader structure, resources and interfaces.
+ *
+ * Some rule of thumb:
+ * - Do not include anything else than this file in each info file.
+ */
+
+#pragma once
+
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
+#include "GPU_texture.h"
+
+namespace blender::gpu::shader {
+
+#ifndef GPU_SHADER_CREATE_INFO
+/* Helps intelisense / auto-completion. */
+# define GPU_SHADER_INTERFACE_INFO(_interface, _inst_name) \
+ StageInterfaceInfo _interface(#_interface, _inst_name); \
+ _interface
+# define GPU_SHADER_CREATE_INFO(_info) \
+ ShaderCreateInfo _info(#_info); \
+ _info
+#endif
+
+enum class Type {
+ FLOAT = 0,
+ VEC2,
+ VEC3,
+ VEC4,
+ MAT3,
+ MAT4,
+ UINT,
+ UVEC2,
+ UVEC3,
+ UVEC4,
+ INT,
+ IVEC2,
+ IVEC3,
+ IVEC4,
+ BOOL,
+};
+
+enum class BuiltinBits {
+ /**
+ * Allow getting barycentric coordinates inside the fragment shader.
+ * \note Emulated on OpenGL.
+ */
+ BARYCENTRIC_COORD = (1 << 0),
+ FRAG_COORD = (1 << 2),
+ FRONT_FACING = (1 << 4),
+ GLOBAL_INVOCATION_ID = (1 << 5),
+ INSTANCE_ID = (1 << 6),
+ LAYER = (1 << 7),
+ LOCAL_INVOCATION_ID = (1 << 8),
+ LOCAL_INVOCATION_INDEX = (1 << 9),
+ NUM_WORK_GROUP = (1 << 10),
+ POINT_COORD = (1 << 11),
+ POINT_SIZE = (1 << 12),
+ PRIMITIVE_ID = (1 << 13),
+ VERTEX_ID = (1 << 14),
+ WORK_GROUP_ID = (1 << 15),
+ WORK_GROUP_SIZE = (1 << 16),
+};
+ENUM_OPERATORS(BuiltinBits, BuiltinBits::WORK_GROUP_SIZE);
+
+/* Samplers & images. */
+enum class ImageType {
+ /** Color samplers/image. */
+ FLOAT_BUFFER = 0,
+ FLOAT_1D,
+ FLOAT_1D_ARRAY,
+ FLOAT_2D,
+ FLOAT_2D_ARRAY,
+ FLOAT_3D,
+ FLOAT_CUBE,
+ FLOAT_CUBE_ARRAY,
+ INT_BUFFER,
+ INT_1D,
+ INT_1D_ARRAY,
+ INT_2D,
+ INT_2D_ARRAY,
+ INT_3D,
+ INT_CUBE,
+ INT_CUBE_ARRAY,
+ UINT_BUFFER,
+ UINT_1D,
+ UINT_1D_ARRAY,
+ UINT_2D,
+ UINT_2D_ARRAY,
+ UINT_3D,
+ UINT_CUBE,
+ UINT_CUBE_ARRAY,
+ /** Depth samplers (not supported as image). */
+ SHADOW_2D,
+ SHADOW_2D_ARRAY,
+ SHADOW_CUBE,
+ SHADOW_CUBE_ARRAY,
+ DEPTH_2D,
+ DEPTH_2D_ARRAY,
+ DEPTH_CUBE,
+ DEPTH_CUBE_ARRAY,
+};
+
+/* Storage qualifiers. */
+enum class Qualifier {
+ RESTRICT = (1 << 0),
+ READ_ONLY = (1 << 1),
+ WRITE_ONLY = (1 << 2),
+ QUALIFIER_MAX = (WRITE_ONLY << 1) - 1,
+};
+ENUM_OPERATORS(Qualifier, Qualifier::QUALIFIER_MAX);
+
+enum class Frequency {
+ BATCH = 0,
+ PASS,
+};
+
+/* Dual Source Blending Index. */
+enum class DualBlend {
+ NONE = 0,
+ SRC_0,
+ SRC_1,
+};
+
+/* Interpolation qualifiers. */
+enum class Interpolation {
+ SMOOTH = 0,
+ FLAT,
+ NO_PERSPECTIVE,
+};
+
+/** Input layout for geometry shader. */
+enum class PrimitiveIn {
+ POINTS = 0,
+ LINES,
+ LINES_ADJACENCY,
+ TRIANGLES,
+ TRIANGLES_ADJACENCY,
+};
+
+/** Output layout for geometry shader. */
+enum class PrimitiveOut {
+ POINTS = 0,
+ LINE_STRIP,
+ TRIANGLE_STRIP,
+};
+
+struct StageInterfaceInfo {
+ struct InOut {
+ Interpolation interp;
+ Type type;
+ StringRefNull name;
+ };
+
+ StringRefNull name;
+ /** Name of the instance of the block (used to access).
+ * Can be empty string (i.e: "") only if not using geometry shader. */
+ StringRefNull instance_name;
+ /** List of all members of the interface. */
+ Vector<InOut> inouts;
+
+ StageInterfaceInfo(const char *name_, const char *instance_name_)
+ : name(name_), instance_name(instance_name_){};
+ ~StageInterfaceInfo(){};
+
+ using Self = StageInterfaceInfo;
+
+ Self &smooth(Type type, StringRefNull _name)
+ {
+ inouts.append({Interpolation::SMOOTH, type, _name});
+ return *(Self *)this;
+ }
+
+ Self &flat(Type type, StringRefNull _name)
+ {
+ inouts.append({Interpolation::FLAT, type, _name});
+ return *(Self *)this;
+ }
+
+ Self &no_perspective(Type type, StringRefNull _name)
+ {
+ inouts.append({Interpolation::NO_PERSPECTIVE, type, _name});
+ return *(Self *)this;
+ }
+};
+
+/**
+ * @brief Describe inputs & outputs, stage interfaces, resources and sources of a shader.
+ * If all data is correctly provided, this is all that is needed to create and compile
+ * a GPUShader.
+ *
+ * IMPORTANT: All strings are references only. Make sure all the strings used by a
+ * ShaderCreateInfo are not freed until it is consumed or deleted.
+ */
+struct ShaderCreateInfo {
+ /** Shader name for debugging. */
+ StringRefNull name_;
+ /** True if the shader is static and can be pre-compiled at compile time. */
+ bool do_static_compilation_ = false;
+ /** If true, all additionally linked create info will be merged into this one. */
+ bool finalized_ = false;
+ /**
+ * Maximum length of all the resource names including each null terminator.
+ * Only for names used by gpu::ShaderInterface.
+ */
+ size_t interface_names_size_ = 0;
+
+ struct VertIn {
+ int index;
+ Type type;
+ StringRefNull name;
+ };
+ Vector<VertIn> vertex_inputs_;
+
+ struct GeometryStageLayout {
+ PrimitiveIn primitive_in;
+ int invocations;
+ PrimitiveOut primitive_out;
+ /** Set to -1 by default to check if used. */
+ int max_vertices = -1;
+ };
+ GeometryStageLayout geometry_layout_;
+
+ struct ComputeStageLayout {
+ int local_size_x = -1;
+ int local_size_y = -1;
+ int local_size_z = -1;
+ };
+
+ ComputeStageLayout compute_layout_;
+
+ struct FragOut {
+ int index;
+ Type type;
+ DualBlend blend;
+ StringRefNull name;
+ };
+ Vector<FragOut> fragment_outputs_;
+
+ struct Sampler {
+ ImageType type;
+ eGPUSamplerState sampler;
+ StringRefNull name;
+ };
+
+ struct Image {
+ eGPUTextureFormat format;
+ ImageType type;
+ Qualifier qualifiers;
+ StringRefNull name;
+ };
+
+ struct UniformBuf {
+ StringRefNull type_name;
+ StringRefNull name;
+ };
+
+ struct StorageBuf {
+ Qualifier qualifiers;
+ StringRefNull type_name;
+ StringRefNull name;
+ };
+
+ struct Resource {
+ enum BindType {
+ UNIFORM_BUFFER = 0,
+ STORAGE_BUFFER,
+ SAMPLER,
+ IMAGE,
+ };
+
+ BindType bind_type;
+ int slot;
+ union {
+ Sampler sampler;
+ Image image;
+ UniformBuf uniformbuf;
+ StorageBuf storagebuf;
+ };
+
+ Resource(BindType type, int _slot) : bind_type(type), slot(_slot){};
+ };
+ /**
+ * Resources are grouped by frequency of change.
+ * Pass resources are meant to be valid for the whole pass.
+ * Batch resources can be changed in a more granular manner (per object/material).
+ * Mis-usage will only produce suboptimal performance.
+ */
+ Vector<Resource> pass_resources_, batch_resources_;
+
+ Vector<StageInterfaceInfo *> vertex_out_interfaces_;
+ Vector<StageInterfaceInfo *> geometry_out_interfaces_;
+
+ struct PushConst {
+ int index;
+ Type type;
+ StringRefNull name;
+ int array_size;
+ };
+
+ Vector<PushConst> push_constants_;
+
+ /* Sources for resources type definitions. */
+ Vector<StringRefNull> typedef_sources_;
+
+ StringRefNull vertex_source_, geometry_source_, fragment_source_, compute_source_;
+
+ Vector<std::array<StringRefNull, 2>> defines_;
+ /**
+ * Name of other infos to recursively merge with this one.
+ * No data slot must overlap otherwise we throw an error.
+ */
+ Vector<StringRefNull> additional_infos_;
+
+ public:
+ ShaderCreateInfo(const char *name) : name_(name){};
+ ~ShaderCreateInfo(){};
+
+ using Self = ShaderCreateInfo;
+
+ /* -------------------------------------------------------------------- */
+ /** \name Shaders in/outs (fixed function pipeline config)
+ * \{ */
+
+ Self &vertex_in(int slot, Type type, StringRefNull name)
+ {
+ vertex_inputs_.append({slot, type, name});
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ Self &vertex_out(StageInterfaceInfo &interface)
+ {
+ vertex_out_interfaces_.append(&interface);
+ return *(Self *)this;
+ }
+
+ /**
+ * IMPORTANT: invocations count is only used if GL_ARB_gpu_shader5 is supported. On
+ * implementations that do not supports it, the max_vertices will be be multiplied by
+ * invocations. Your shader needs to account for this fact. Use `#ifdef GPU_ARB_gpu_shader5`
+ * and make a code path that does not rely on gl_InvocationID.
+ */
+ Self &geometry_layout(PrimitiveIn prim_in,
+ PrimitiveOut prim_out,
+ int max_vertices,
+ int invocations = -1)
+ {
+ geometry_layout_.primitive_in = prim_in;
+ geometry_layout_.primitive_out = prim_out;
+ geometry_layout_.max_vertices = max_vertices;
+ geometry_layout_.invocations = invocations;
+ return *(Self *)this;
+ }
+
+ Self &local_group_size(int local_size_x = -1, int local_size_y = -1, int local_size_z = -1)
+ {
+ compute_layout_.local_size_x = local_size_x;
+ compute_layout_.local_size_y = local_size_y;
+ compute_layout_.local_size_z = local_size_z;
+ return *(Self *)this;
+ }
+
+ /**
+ * Only needed if geometry shader is enabled.
+ * IMPORTANT: Input and output instance name will have respectively "_in" and "_out" suffix
+ * appended in the geometry shader IF AND ONLY IF the vertex_out interface instance name matches
+ * the geometry_out interface instance name.
+ */
+ Self &geometry_out(StageInterfaceInfo &interface)
+ {
+ geometry_out_interfaces_.append(&interface);
+ return *(Self *)this;
+ }
+
+ Self &fragment_out(int slot, Type type, StringRefNull name, DualBlend blend = DualBlend::NONE)
+ {
+ fragment_outputs_.append({slot, type, blend, name});
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Resources bindings points
+ * \{ */
+
+ Self &uniform_buf(int slot,
+ StringRefNull type_name,
+ StringRefNull name,
+ Frequency freq = Frequency::PASS)
+ {
+ Resource res(Resource::BindType::UNIFORM_BUFFER, slot);
+ res.uniformbuf.name = name;
+ res.uniformbuf.type_name = type_name;
+ ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res);
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ Self &storage_buf(int slot,
+ Qualifier qualifiers,
+ StringRefNull type_name,
+ StringRefNull name,
+ Frequency freq = Frequency::PASS)
+ {
+ Resource res(Resource::BindType::STORAGE_BUFFER, slot);
+ res.storagebuf.qualifiers = qualifiers;
+ res.storagebuf.type_name = type_name;
+ res.storagebuf.name = name;
+ ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res);
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ Self &image(int slot,
+ eGPUTextureFormat format,
+ Qualifier qualifiers,
+ ImageType type,
+ StringRefNull name,
+ Frequency freq = Frequency::PASS)
+ {
+ Resource res(Resource::BindType::IMAGE, slot);
+ res.image.format = format;
+ res.image.qualifiers = qualifiers;
+ res.image.type = type;
+ res.image.name = name;
+ ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res);
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ Self &sampler(int slot,
+ ImageType type,
+ StringRefNull name,
+ Frequency freq = Frequency::PASS,
+ eGPUSamplerState sampler = (eGPUSamplerState)-1)
+ {
+ Resource res(Resource::BindType::SAMPLER, slot);
+ res.sampler.type = type;
+ res.sampler.name = name;
+ res.sampler.sampler = sampler;
+ ((freq == Frequency::PASS) ? pass_resources_ : batch_resources_).append(res);
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Shader Source
+ * \{ */
+
+ Self &vertex_source(StringRefNull filename)
+ {
+ vertex_source_ = filename;
+ return *(Self *)this;
+ }
+
+ Self &geometry_source(StringRefNull filename)
+ {
+ geometry_source_ = filename;
+ return *(Self *)this;
+ }
+
+ Self &fragment_source(StringRefNull filename)
+ {
+ fragment_source_ = filename;
+ return *(Self *)this;
+ }
+
+ Self &compute_source(StringRefNull filename)
+ {
+ compute_source_ = filename;
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Push constants
+ *
+ * Data managed by GPUShader. Can be set through uniform functions. Must be less than 128bytes.
+ * One slot represents 4bytes. Each element needs to have enough empty space left after it.
+ * example:
+ * [0] = PUSH_CONSTANT(MAT4, "ModelMatrix"),
+ * ---- 16 slots occupied by ModelMatrix ----
+ * [16] = PUSH_CONSTANT(VEC4, "color"),
+ * ---- 4 slots occupied by color ----
+ * [20] = PUSH_CONSTANT(BOOL, "srgbToggle"),
+ * The maximum slot is 31.
+ * \{ */
+
+ Self &push_constant(int slot, Type type, StringRefNull name, int array_size = 0)
+ {
+ BLI_assert_msg(name.find("[") == -1,
+ "Array syntax is forbidden for push constants."
+ "Use the array_size parameter instead.");
+ push_constants_.append({slot, type, name, array_size});
+ interface_names_size_ += name.size() + 1;
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Defines
+ * \{ */
+
+ Self &define(StringRefNull name, StringRefNull value = "")
+ {
+ defines_.append({name, value});
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Defines
+ * \{ */
+
+ Self &do_static_compilation(bool value)
+ {
+ do_static_compilation_ = value;
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Additional Create Info
+ *
+ * Used to share parts of the infos that are common to many shaders.
+ * \{ */
+
+ Self &additional_info(StringRefNull info_name0,
+ StringRefNull info_name1 = "",
+ StringRefNull info_name2 = "",
+ StringRefNull info_name3 = "",
+ StringRefNull info_name4 = "",
+ StringRefNull info_name5 = "",
+ StringRefNull info_name6 = "")
+ {
+ additional_infos_.append(info_name0);
+ if (!info_name1.is_empty()) {
+ additional_infos_.append(info_name1);
+ }
+ if (!info_name2.is_empty()) {
+ additional_infos_.append(info_name2);
+ }
+ if (!info_name3.is_empty()) {
+ additional_infos_.append(info_name3);
+ }
+ if (!info_name4.is_empty()) {
+ additional_infos_.append(info_name4);
+ }
+ if (!info_name5.is_empty()) {
+ additional_infos_.append(info_name5);
+ }
+ if (!info_name6.is_empty()) {
+ additional_infos_.append(info_name6);
+ }
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Typedef Sources
+ *
+ * Some resource declarations might need some special structure defined.
+ * Adding a file using typedef_source will include it before the resource
+ * and interface definitions.
+ * \{ */
+
+ Self &typedef_source(StringRefNull filename)
+ {
+ typedef_sources_.append(filename);
+ return *(Self *)this;
+ }
+
+ /** \} */
+
+ /* -------------------------------------------------------------------- */
+ /** \name Recursive evaluation.
+ *
+ * Flatten all dependency so that this descriptor contains all the data from the additional
+ * descriptors. This avoids tedious traversal in shader source creation.
+ * \{ */
+
+ /* WARNING: Recursive. */
+ void finalize();
+
+ /** Error detection that some backend compilers do not complain about. */
+ void validate(const ShaderCreateInfo &other_info);
+
+ /** \} */
+};
+
+} // namespace blender::gpu::shader
diff --git a/source/blender/gpu/intern/gpu_shader_create_info_private.hh b/source/blender/gpu/intern/gpu_shader_create_info_private.hh
new file mode 100644
index 00000000000..6d2878377ad
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_create_info_private.hh
@@ -0,0 +1,46 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Descriptor type used to define shader structure, resources and interfaces.
+ *
+ * Some rule of thumb:
+ * - Do not include anything else than this file in each descriptor file.
+ */
+
+#pragma once
+
+#include "GPU_shader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gpu_shader_create_info_init(void);
+void gpu_shader_create_info_exit(void);
+
+bool gpu_shader_create_info_compile_all(void);
+
+const GPUShaderCreateInfo *gpu_shader_create_info_get(const char *info_name);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc
new file mode 100644
index 00000000000..2333590810f
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_dependency.cc
@@ -0,0 +1,388 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Shader source dependency builder that make possible to support #include directive inside the
+ * shader files.
+ */
+
+#include <iostream>
+
+#include "BLI_map.hh"
+#include "BLI_set.hh"
+#include "BLI_string_ref.hh"
+
+#include "gpu_shader_create_info.hh"
+#include "gpu_shader_dependency_private.h"
+
+extern "C" {
+#define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[];
+#include "glsl_draw_source_list.h"
+#include "glsl_gpu_source_list.h"
+#undef SHADER_SOURCE
+}
+
+namespace blender::gpu {
+
+using GPUSourceDictionnary = Map<StringRef, struct GPUSource *>;
+
+struct GPUSource {
+ StringRefNull fullpath;
+ StringRefNull filename;
+ StringRefNull source;
+ Vector<GPUSource *> dependencies;
+ bool dependencies_init = false;
+ shader::BuiltinBits builtins = (shader::BuiltinBits)0;
+ std::string processed_source;
+
+ GPUSource(const char *path, const char *file, const char *datatoc)
+ : fullpath(path), filename(file), source(datatoc)
+ {
+ /* Scan for builtins. */
+ /* FIXME: This can trigger false positive caused by disabled #if blocks. */
+ /* TODO(fclem): Could be made faster by scanning once. */
+ /* TODO(fclem): BARYCENTRIC_COORD. */
+ if (source.find("gl_FragCoord", 0)) {
+ builtins |= shader::BuiltinBits::FRAG_COORD;
+ }
+ if (source.find("gl_FrontFacing", 0)) {
+ builtins |= shader::BuiltinBits::FRONT_FACING;
+ }
+ if (source.find("gl_GlobalInvocationID", 0)) {
+ builtins |= shader::BuiltinBits::GLOBAL_INVOCATION_ID;
+ }
+ if (source.find("gl_InstanceID", 0)) {
+ builtins |= shader::BuiltinBits::INSTANCE_ID;
+ }
+ if (source.find("gl_Layer", 0)) {
+ builtins |= shader::BuiltinBits::LAYER;
+ }
+ if (source.find("gl_LocalInvocationID", 0)) {
+ builtins |= shader::BuiltinBits::LOCAL_INVOCATION_ID;
+ }
+ if (source.find("gl_LocalInvocationIndex", 0)) {
+ builtins |= shader::BuiltinBits::LOCAL_INVOCATION_INDEX;
+ }
+ if (source.find("gl_NumWorkGroup", 0)) {
+ builtins |= shader::BuiltinBits::NUM_WORK_GROUP;
+ }
+ if (source.find("gl_PointCoord", 0)) {
+ builtins |= shader::BuiltinBits::POINT_COORD;
+ }
+ if (source.find("gl_PointSize", 0)) {
+ builtins |= shader::BuiltinBits::POINT_SIZE;
+ }
+ if (source.find("gl_PrimitiveID", 0)) {
+ builtins |= shader::BuiltinBits::PRIMITIVE_ID;
+ }
+ if (source.find("gl_VertexID", 0)) {
+ builtins |= shader::BuiltinBits::VERTEX_ID;
+ }
+ if (source.find("gl_WorkGroupID", 0)) {
+ builtins |= shader::BuiltinBits::WORK_GROUP_ID;
+ }
+ if (source.find("gl_WorkGroupSize", 0)) {
+ builtins |= shader::BuiltinBits::WORK_GROUP_SIZE;
+ }
+
+ /* TODO(fclem): We could do that at compile time. */
+ /* Limit to shared header files to avoid the temptation to use C++ syntax in .glsl files. */
+ if (filename.endswith(".h") || filename.endswith(".hh")) {
+ enum_preprocess();
+ }
+ };
+
+ bool is_in_comment(const StringRef &input, int64_t offset)
+ {
+ return (input.rfind("/*", offset) > input.rfind("*/", offset)) ||
+ (input.rfind("//", offset) > input.rfind("\n", offset));
+ }
+
+ template<bool check_whole_word = true, bool reversed = false, typename T>
+ int64_t find_str(const StringRef &input, const T keyword, int64_t offset = 0)
+ {
+ while (1) {
+ if constexpr (reversed) {
+ offset = input.rfind(keyword, offset);
+ }
+ else {
+ offset = input.find(keyword, offset);
+ }
+ if (offset > 0) {
+ if constexpr (check_whole_word) {
+ /* Fix false positive if something has "enum" as suffix. */
+ char previous_char = input[offset - 1];
+ if (!(ELEM(previous_char, '\n', '\t', ' ', ':'))) {
+ offset += (reversed) ? -1 : 1;
+ continue;
+ }
+ }
+ /* Fix case where the keyword is in a comment. */
+ if (is_in_comment(input, offset)) {
+ offset += (reversed) ? -1 : 1;
+ continue;
+ }
+ }
+ return offset;
+ }
+ }
+
+ void print_error(const StringRef &input, int64_t offset, const StringRef message)
+ {
+ std::cout << " error: " << message << "\n";
+ StringRef sub = input.substr(0, offset);
+ int64_t line_number = std::count(sub.begin(), sub.end(), '\n') + 1;
+ int64_t line_end = input.find("\n", offset);
+ int64_t line_start = input.rfind("\n", offset) + 1;
+ int64_t char_number = offset - line_start + 1;
+ char line_prefix[16] = "";
+ SNPRINTF(line_prefix, "%5ld | ", line_number);
+
+ /* TODO Use clog. */
+
+ std::cout << fullpath << ":" << line_number << ":" << char_number;
+
+ std::cout << " error: " << message << "\n";
+ std::cout << line_prefix << input.substr(line_start, line_end - line_start) << "\n";
+ std::cout << " | ";
+ for (int64_t i = 0; i < char_number - 1; i++) {
+ std::cout << " ";
+ }
+ std::cout << "^\n";
+ }
+
+ /**
+ * Transform C,C++ enum declaration into GLSL compatible defines and constants:
+ *
+ * \code{.cpp}
+ * enum eMyEnum : uint32_t {
+ * ENUM_1 = 0u,
+ * ENUM_2 = 1u,
+ * ENUM_3 = 2u,
+ * };
+ * \endcode
+ *
+ * or
+ *
+ * \code{.c}
+ * enum eMyEnum {
+ * ENUM_1 = 0u,
+ * ENUM_2 = 1u,
+ * ENUM_3 = 2u,
+ * };
+ * \endcode
+ *
+ * becomes
+ *
+ * \code{.glsl}
+ * #define eMyEnum uint
+ * const uint ENUM_1 = 0u, ENUM_2 = 1u, ENUM_3 = 2u;
+ * \endcode
+ *
+ * IMPORTANT: This has some requirements:
+ * - Enums needs to have underlying types specified to uint32_t to make them usable in UBO/SSBO.
+ * - All values needs to be specified using constant literals to avoid compiler differencies.
+ * - All values needs to have the 'u' suffix to avoid GLSL compiler errors.
+ */
+ void enum_preprocess(void)
+ {
+ const StringRefNull input = source;
+ std::string output = "";
+ int64_t cursor = 0;
+ int64_t last_pos = 0;
+ const bool is_cpp = filename.endswith(".hh");
+
+#define find_keyword find_str<true, false>
+#define find_token find_str<false, false>
+#define rfind_token find_str<false, true>
+#define CHECK(test_value, str, ofs, msg) \
+ if ((test_value) == -1) { \
+ print_error(str, ofs, msg); \
+ cursor++; \
+ continue; \
+ }
+
+ while (1) {
+ cursor = find_keyword(input, "enum ", cursor);
+ if (cursor == -1) {
+ break;
+ }
+ /* Output anything between 2 enums blocks. */
+ output += input.substr(last_pos, cursor - last_pos);
+
+ /* Extract enum type name. */
+ int64_t name_start = input.find(" ", cursor);
+
+ int64_t values_start = find_token(input, '{', cursor);
+ CHECK(values_start, input, cursor, "Malformed enum class. Expected \'{\' after typename.");
+
+ StringRef enum_name = input.substr(name_start, values_start - name_start);
+ if (is_cpp) {
+ int64_t name_end = find_token(enum_name, ":");
+ CHECK(name_end, input, name_start, "Expected \':\' after C++ enum name.");
+
+ int64_t underlying_type = find_keyword(enum_name, "uint32_t", name_end);
+ CHECK(underlying_type, input, name_start, "C++ enums needs uint32_t underlying type.");
+
+ enum_name = input.substr(name_start, name_end);
+ }
+
+ output += "#define " + enum_name + " uint\n";
+
+ /* Extract enum values. */
+ int64_t values_end = find_token(input, '}', values_start);
+ CHECK(values_end, input, cursor, "Malformed enum class. Expected \'}\' after values.");
+
+ /* Skip opening brackets. */
+ values_start += 1;
+
+ StringRef enum_values = input.substr(values_start, values_end - values_start);
+
+ /* Really poor check. Could be done better. */
+ int64_t token = find_token(enum_values, '{');
+ int64_t not_found = (token == -1) ? 0 : -1;
+ CHECK(not_found, input, values_start + token, "Unexpected \'{\' token inside enum values.");
+
+ /* Do not capture the comma after the last value (if present). */
+ int64_t last_equal = rfind_token(enum_values, '=', values_end);
+ int64_t last_comma = rfind_token(enum_values, ',', values_end);
+ if (last_comma > last_equal) {
+ enum_values = input.substr(values_start, last_comma);
+ }
+
+ output += "const uint " + enum_values;
+
+ int64_t semicolon_found = (input[values_end + 1] == ';') ? 0 : -1;
+ CHECK(semicolon_found, input, values_end + 1, "Expected \';\' after enum type declaration.");
+
+ /* Skip the curly bracket but not the semicolon. */
+ cursor = last_pos = values_end + 1;
+ }
+ /* If nothing has been changed, do not allocate processed_source. */
+ if (last_pos == 0) {
+ return;
+ }
+
+#undef find_keyword
+#undef find_token
+#undef rfind_token
+
+ if (last_pos != 0) {
+ output += input.substr(last_pos);
+ }
+ processed_source = output;
+ source = processed_source.c_str();
+ };
+
+ void init_dependencies(const GPUSourceDictionnary &dict)
+ {
+ if (dependencies_init) {
+ return;
+ }
+ dependencies_init = true;
+ int64_t pos = 0;
+ while (true) {
+ pos = source.find("pragma BLENDER_REQUIRE(", pos);
+ if (pos == -1) {
+ return;
+ }
+ int64_t start = source.find('(', pos) + 1;
+ int64_t end = source.find(')', pos);
+ if (end == -1) {
+ /* TODO Use clog. */
+ std::cout << "Error: " << filename << " : Malformed BLENDER_REQUIRE: Missing \")\"."
+ << std::endl;
+ return;
+ }
+ StringRef dependency_name = source.substr(start, end - start);
+ GPUSource *dependency_source = dict.lookup_default(dependency_name, nullptr);
+ if (dependency_source == nullptr) {
+ /* TODO Use clog. */
+ std::cout << "Error: " << filename << " : Dependency not found \"" << dependency_name
+ << "\"." << std::endl;
+ return;
+ }
+ /* Recursive. */
+ dependency_source->init_dependencies(dict);
+
+ for (auto *dep : dependency_source->dependencies) {
+ dependencies.append_non_duplicates(dep);
+ }
+ dependencies.append_non_duplicates(dependency_source);
+ pos++;
+ };
+ }
+
+ /* Returns the final string with all includes done. */
+ void build(std::string &str, shader::BuiltinBits &out_builtins)
+ {
+ for (auto *dep : dependencies) {
+ out_builtins |= builtins;
+ str += dep->source;
+ }
+ str += source;
+ }
+};
+
+} // namespace blender::gpu
+
+using namespace blender::gpu;
+
+static GPUSourceDictionnary *g_sources = nullptr;
+
+void gpu_shader_dependency_init()
+{
+ g_sources = new GPUSourceDictionnary();
+
+#define SHADER_SOURCE(datatoc, filename, filepath) \
+ g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc));
+#include "glsl_draw_source_list.h"
+#include "glsl_gpu_source_list.h"
+#undef SHADER_SOURCE
+
+ for (auto *value : g_sources->values()) {
+ value->init_dependencies(*g_sources);
+ }
+}
+
+void gpu_shader_dependency_exit()
+{
+ for (auto *value : g_sources->values()) {
+ delete value;
+ }
+ delete g_sources;
+}
+
+char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name, uint32_t *builtins)
+{
+ GPUSource *source = g_sources->lookup(shader_source_name);
+ std::string str;
+ shader::BuiltinBits out_builtins;
+ source->build(str, out_builtins);
+ *builtins |= (uint32_t)out_builtins;
+ return strdup(str.c_str());
+}
+
+char *gpu_shader_dependency_get_source(const char *shader_source_name)
+{
+ GPUSource *src = g_sources->lookup(shader_source_name);
+ return strdup(src->source.c_str());
+}
diff --git a/source/blender/gpu/intern/gpu_shader_dependency_private.h b/source/blender/gpu/intern/gpu_shader_dependency_private.h
new file mode 100644
index 00000000000..b129ca74a48
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_dependency_private.h
@@ -0,0 +1,44 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Shader source dependency builder that make possible to support #include directive inside the
+ * shader files.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gpu_shader_dependency_init(void);
+
+void gpu_shader_dependency_exit(void);
+
+/* User must free the resulting string using free. */
+char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name,
+ uint32_t *builtins);
+char *gpu_shader_dependency_get_source(const char *shader_source_name);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/gpu/intern/gpu_shader_info_baked.cc b/source/blender/gpu/intern/gpu_shader_info_baked.cc
new file mode 100644
index 00000000000..55115a6d459
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_info_baked.cc
@@ -0,0 +1,24 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Intentionally empty for compiling shader builder.
+ */
diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc
index ae94112b17b..937f49ccaec 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.cc
+++ b/source/blender/gpu/intern/gpu_shader_interface.cc
@@ -65,14 +65,17 @@ static void sort_input_list(MutableSpan<ShaderInput> dst)
}
}
-/* Sorts all inputs inside their respective array.
- * This is to allow fast hash collision detection.
- * See ShaderInterface::input_lookup for more details. */
void ShaderInterface::sort_inputs()
{
+ /* Sorts all inputs inside their respective array.
+ * This is to allow fast hash collision detection.
+ * See `ShaderInterface::input_lookup` for more details. */
+
sort_input_list(MutableSpan<ShaderInput>(inputs_, attr_len_));
sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_, ubo_len_));
sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_ + ubo_len_, uniform_len_));
+ sort_input_list(
+ MutableSpan<ShaderInput>(inputs_ + attr_len_ + ubo_len_ + uniform_len_, ssbo_len_));
}
void ShaderInterface::debug_print()
diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh
index d4060cb80b4..f94006d1407 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.hh
+++ b/source/blender/gpu/intern/gpu_shader_interface.hh
@@ -34,6 +34,7 @@
#include "BLI_utildefines.h"
#include "GPU_shader.h"
+#include "gpu_shader_create_info.hh"
namespace blender::gpu {
@@ -50,6 +51,7 @@ typedef struct ShaderInput {
* Base class which is then specialized for each implementation (GL, VK, ...).
*/
class ShaderInterface {
+ friend shader::ShaderCreateInfo;
/* TODO(fclem): should be protected. */
public:
/** Flat array. In this order: Attributes, Ubos, Uniforms. */
@@ -73,9 +75,10 @@ class ShaderInterface {
public:
ShaderInterface();
+ ShaderInterface(const shader::ShaderCreateInfo &info);
virtual ~ShaderInterface();
- void debug_print(void);
+ void debug_print();
inline const ShaderInput *attr_get(const char *name) const
{
@@ -137,18 +140,24 @@ class ShaderInterface {
static inline const char *builtin_buffer_block_name(GPUBufferBlockBuiltin u);
inline uint32_t set_input_name(ShaderInput *input, char *name, uint32_t name_len) const;
+ inline void copy_input_name(ShaderInput *input,
+ const StringRefNull &name,
+ char *name_buffer,
+ uint32_t &name_buffer_offset) const;
- /* Finalize interface construction by sorting the ShaderInputs for faster lookups. */
- void sort_inputs(void);
+ /**
+ * Finalize interface construction by sorting the #ShaderInputs for faster lookups.
+ */
+ void sort_inputs();
private:
inline const ShaderInput *input_lookup(const ShaderInput *const inputs,
- const uint inputs_len,
+ uint inputs_len,
const char *name) const;
inline const ShaderInput *input_lookup(const ShaderInput *const inputs,
- const uint inputs_len,
- const int binding) const;
+ uint inputs_len,
+ int binding) const;
};
inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u)
@@ -188,11 +197,11 @@ inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u)
case GPU_UNIFORM_COLOR:
return "color";
case GPU_UNIFORM_BASE_INSTANCE:
- return "baseInstance";
+ return "gpu_BaseInstance";
case GPU_UNIFORM_RESOURCE_CHUNK:
- return "resourceChunk";
+ return "drw_resourceChunk";
case GPU_UNIFORM_RESOURCE_ID:
- return "resourceId";
+ return "drw_ResourceID";
case GPU_UNIFORM_SRGB_TRANSFORM:
return "srgbTarget";
@@ -210,6 +219,13 @@ inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBu
return "modelBlock";
case GPU_UNIFORM_BLOCK_INFO:
return "infoBlock";
+
+ case GPU_UNIFORM_BLOCK_DRW_VIEW:
+ return "drw_view";
+ case GPU_UNIFORM_BLOCK_DRW_MODEL:
+ return "drw_matrices";
+ case GPU_UNIFORM_BLOCK_DRW_INFOS:
+ return "drw_infos";
default:
return NULL;
}
@@ -232,8 +248,12 @@ inline uint32_t ShaderInterface::set_input_name(ShaderInput *input,
{
/* remove "[0]" from array name */
if (name[name_len - 1] == ']') {
- name[name_len - 3] = '\0';
- name_len -= 3;
+ for (; name_len > 1; name_len--) {
+ if (name[name_len] == '[') {
+ name[name_len] = '\0';
+ break;
+ }
+ }
}
input->name_offset = (uint32_t)(name - name_buffer_);
@@ -241,6 +261,17 @@ inline uint32_t ShaderInterface::set_input_name(ShaderInput *input,
return name_len + 1; /* include NULL terminator */
}
+inline void ShaderInterface::copy_input_name(ShaderInput *input,
+ const StringRefNull &name,
+ char *name_buffer,
+ uint32_t &name_buffer_offset) const
+{
+ uint32_t name_len = name.size();
+ /* Copy include NULL terminator. */
+ memcpy(name_buffer + name_buffer_offset, name.c_str(), name_len + 1);
+ name_buffer_offset += set_input_name(input, name_buffer + name_buffer_offset, name_len);
+}
+
inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const inputs,
const uint inputs_len,
const char *name) const
diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh
index 65720e457d8..3bfecdefba7 100644
--- a/source/blender/gpu/intern/gpu_shader_private.hh
+++ b/source/blender/gpu/intern/gpu_shader_private.hh
@@ -24,9 +24,12 @@
#include "BLI_string_ref.hh"
#include "GPU_shader.h"
+#include "gpu_shader_create_info.hh"
#include "gpu_shader_interface.hh"
#include "gpu_vertex_buffer_private.hh"
+#include <string>
+
namespace blender {
namespace gpu {
@@ -53,35 +56,40 @@ class Shader {
virtual void geometry_shader_from_glsl(MutableSpan<const char *> sources) = 0;
virtual void fragment_shader_from_glsl(MutableSpan<const char *> sources) = 0;
virtual void compute_shader_from_glsl(MutableSpan<const char *> sources) = 0;
- virtual bool finalize(void) = 0;
+ virtual bool finalize(const shader::ShaderCreateInfo *info = nullptr) = 0;
virtual void transform_feedback_names_set(Span<const char *> name_list,
- const eGPUShaderTFBType geom_type) = 0;
+ eGPUShaderTFBType geom_type) = 0;
virtual bool transform_feedback_enable(GPUVertBuf *) = 0;
- virtual void transform_feedback_disable(void) = 0;
+ virtual void transform_feedback_disable() = 0;
- virtual void bind(void) = 0;
- virtual void unbind(void) = 0;
+ virtual void bind() = 0;
+ virtual void unbind() = 0;
virtual void uniform_float(int location, int comp_len, int array_size, const float *data) = 0;
virtual void uniform_int(int location, int comp_len, int array_size, const int *data) = 0;
virtual void vertformat_from_shader(GPUVertFormat *) const = 0;
+ std::string defines_declare(const shader::ShaderCreateInfo &info) const;
+ virtual std::string resources_declare(const shader::ShaderCreateInfo &info) const = 0;
+ virtual std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const = 0;
+ virtual std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const = 0;
+ virtual std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const = 0;
+ virtual std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const = 0;
+ virtual std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const = 0;
+
/* DEPRECATED: Kept only because of BGL API. */
- virtual int program_handle_get(void) const = 0;
+ virtual int program_handle_get() const = 0;
- inline const char *const name_get(void) const
+ inline const char *const name_get() const
{
return name;
};
protected:
- void print_log(Span<const char *> sources,
- char *log,
- const char *stage,
- const bool error,
- GPULogParser *parser);
+ void print_log(
+ Span<const char *> sources, char *log, const char *stage, bool error, GPULogParser *parser);
};
/* Syntactic sugar. */
@@ -137,4 +145,4 @@ class GPULogParser {
} // namespace blender
/* XXX do not use it. Special hack to use OCIO with batch API. */
-GPUShader *immGetShader(void);
+GPUShader *immGetShader();
diff --git a/source/blender/gpu/intern/gpu_shader_shared_utils.h b/source/blender/gpu/intern/gpu_shader_shared_utils.h
new file mode 100644
index 00000000000..0d283fb1e66
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_shared_utils.h
@@ -0,0 +1,116 @@
+/*
+ * 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) 2022 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Glue definition to make shared declaration of struct & functions work in both C / C++ and GLSL.
+ * We use the same vector and matrix types as Blender C++. Some math functions are defined to use
+ * the float version to match the GLSL syntax.
+ * This file can be used for C & C++ code and the syntax used should follow the same rules.
+ * Some preprocessing is done by the GPU back-end to make it GLSL compatible.
+ *
+ * IMPORTANT:
+ * - Always use `u` suffix for enum values. GLSL do not support implicit cast.
+ * - Define all values. This is in order to simplify custom pre-processor code.
+ * - (C++ only) Always use `uint32_t` as underlying type (`enum eMyEnum : uint32_t`).
+ * - (C only) do NOT use the enum type inside UBO/SSBO structs and use `uint` instead.
+ * - Use float suffix by default for float literals to avoid double promotion in C++.
+ * - Pack one float or int after a vec3/ivec3 to fulfill alignment rules.
+ *
+ * NOTE: Due to alignment restriction and buggy drivers, do not try to use mat3 inside structs.
+ * NOTE: (UBO only) Do not use arrays of float. They are padded to arrays of vec4 and are not worth
+ * it. This does not apply to SSBO.
+ *
+ * IMPORTANT: Do not forget to align mat4, vec3 and vec4 to 16 bytes, and vec2 to 8 bytes.
+ *
+ * NOTE: You can use bool type using bool1 a int boolean type matching the GLSL type.
+ */
+
+#ifdef GPU_SHADER
+# define BLI_STATIC_ASSERT_ALIGN(type_, align_)
+# define BLI_STATIC_ASSERT_SIZE(type_, size_)
+# define static
+# define inline
+# define cosf cos
+# define sinf sin
+# define tanf tan
+# define acosf acos
+# define asinf asin
+# define atanf atan
+# define floorf floor
+# define ceilf ceil
+# define sqrtf sqrt
+
+# define float2 vec2
+# define float3 vec3
+# define float4 vec4
+# define float4x4 mat4
+# define int2 ivec2
+# define int3 ivec3
+# define int4 ivec4
+# define uint2 uvec2
+# define uint3 uvec3
+# define uint4 uvec4
+# define bool1 bool
+# define bool2 bvec2
+# define bool3 bvec3
+# define bool4 bvec4
+
+#else /* C / C++ */
+# pragma once
+
+# include "BLI_assert.h"
+
+# ifdef __cplusplus
+# include "BLI_float4x4.hh"
+# include "BLI_math_vec_types.hh"
+using blender::float2;
+using blender::float3;
+using blender::float4;
+using blender::float4x4;
+using blender::int2;
+using blender::int3;
+using blender::int4;
+using blender::uint2;
+using blender::uint3;
+using blender::uint4;
+using bool1 = int;
+using bool2 = blender::int2;
+using bool3 = blender::int3;
+using bool4 = blender::int4;
+
+# else /* C */
+typedef float float2[2];
+typedef float float3[3];
+typedef float float4[4];
+typedef float float4x4[4][4];
+typedef int int2[2];
+typedef int int3[2];
+typedef int int4[4];
+typedef uint uint2[2];
+typedef uint uint3[3];
+typedef uint uint4[4];
+typedef int bool1;
+typedef int bool2[2];
+typedef int bool3[2];
+typedef int bool4[4];
+# endif
+
+#endif
diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc
index 9ee8a8b8d32..a43ddb09ff8 100644
--- a/source/blender/gpu/intern/gpu_state.cc
+++ b/source/blender/gpu/intern/gpu_state.cc
@@ -165,11 +165,6 @@ void GPU_depth_range(float near, float far)
copy_v2_fl2(state.depth_range, near, far);
}
-/**
- * \note By convention, this is set as needed and not reset back to 1.0.
- * This means code that draws lines must always set the line width beforehand,
- * but is not expected to restore it's previous value.
- */
void GPU_line_width(float width)
{
width = max_ff(1.0f, width * PIXELSIZE);
@@ -184,10 +179,6 @@ void GPU_point_size(float size)
state.point_size = size * ((state.point_size > 0.0) ? 1.0f : -1.0f);
}
-/* Programmable point size
- * - shaders set their own point size when enabled
- * - use GPU_point_size when disabled */
-/* TODO: remove and use program point size everywhere. */
void GPU_program_point_size(bool enable)
{
StateManager *stack = Context::get()->state_manager;
@@ -264,7 +255,6 @@ eGPUStencilTest GPU_stencil_test_get()
return (eGPUStencilTest)state.stencil_test;
}
-/* NOTE: Already premultiplied by U.pixelsize. */
float GPU_line_width_get()
{
const GPUStateMutable &state = Context::get()->state_manager->mutable_state;
@@ -363,7 +353,6 @@ void GPU_bgl_start()
}
}
-/* Just turn off the bgl safeguard system. Can be called even without GPU_bgl_start. */
void GPU_bgl_end()
{
Context *ctx = Context::get();
diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh
index b96b71a7ac4..864b7d0446a 100644
--- a/source/blender/gpu/intern/gpu_state_private.hh
+++ b/source/blender/gpu/intern/gpu_state_private.hh
@@ -62,7 +62,7 @@ union GPUState {
uint32_t polygon_smooth : 1;
uint32_t line_smooth : 1;
};
- /* Here to allow fast bitwise ops. */
+ /* Here to allow fast bit-wise ops. */
uint64_t data;
};
@@ -159,18 +159,18 @@ class StateManager {
StateManager();
virtual ~StateManager(){};
- virtual void apply_state(void) = 0;
- virtual void force_state(void) = 0;
+ virtual void apply_state() = 0;
+ virtual void force_state() = 0;
virtual void issue_barrier(eGPUBarrier barrier_bits) = 0;
virtual void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) = 0;
virtual void texture_unbind(Texture *tex) = 0;
- virtual void texture_unbind_all(void) = 0;
+ virtual void texture_unbind_all() = 0;
virtual void image_bind(Texture *tex, int unit) = 0;
virtual void image_unbind(Texture *tex) = 0;
- virtual void image_unbind_all(void) = 0;
+ virtual void image_unbind_all() = 0;
virtual void texture_unpack_row_length_set(uint len) = 0;
};
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 2744c0c5e17..1b8b28bf04c 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -190,7 +190,7 @@ using namespace blender::gpu;
/* ------ Memory Management ------ */
-uint GPU_texture_memory_usage_get(void)
+uint GPU_texture_memory_usage_get()
{
/* TODO(fclem): Do that inside the new Texture class. */
return 0;
@@ -298,7 +298,6 @@ GPUTexture *GPU_texture_create_cube_array(
name, w, w, d, GPU_TEXTURE_CUBE_ARRAY, mip_len, format, GPU_DATA_FLOAT, data);
}
-/* DDS texture loading. Return NULL if support is not available. */
GPUTexture *GPU_texture_create_compressed_2d(
const char *name, int w, int h, int miplen, eGPUTextureFormat tex_format, const void *data)
{
@@ -337,7 +336,6 @@ GPUTexture *GPU_texture_create_from_vertbuf(const char *name, GPUVertBuf *vert)
return reinterpret_cast<GPUTexture *>(tex);
}
-/* Create an error texture that will bind an invalid texture (pink) at draw time. */
GPUTexture *GPU_texture_create_error(int dimension, bool is_array)
{
float pixel[4] = {1.0f, 0.0f, 1.0f, 1.0f};
@@ -386,27 +384,17 @@ void *GPU_texture_read(GPUTexture *tex_, eGPUDataFormat data_format, int miplvl)
return tex->read(miplvl, data_format);
}
-/**
- * Fills the whole texture with the same data for all pixels.
- * \warning Only work for 2D texture for now.
- * \warning Only clears the mip 0 of the texture.
- * \param data_format: data format of the pixel data.
- * \param data: 1 pixel worth of data to fill the texture with.
- */
void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat data_format, const void *data)
{
BLI_assert(data != nullptr); /* Do not accept NULL as parameter. */
reinterpret_cast<Texture *>(tex)->clear(data_format, data);
}
-/* NOTE: Updates only mip 0. */
void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *data)
{
reinterpret_cast<Texture *>(tex)->update(data_format, data);
}
-/* Makes data interpretation aware of the source layout.
- * Skipping pixels correctly when changing rows when doing partial update. */
void GPU_unpack_row_length_set(uint len)
{
Context::get()->state_manager->texture_unpack_row_length_set(len);
@@ -436,7 +424,7 @@ void GPU_texture_unbind(GPUTexture *tex_)
Context::get()->state_manager->texture_unbind(tex);
}
-void GPU_texture_unbind_all(void)
+void GPU_texture_unbind_all()
{
Context::get()->state_manager->texture_unbind_all();
}
@@ -451,7 +439,7 @@ void GPU_texture_image_unbind(GPUTexture *tex)
Context::get()->state_manager->image_unbind(unwrap(tex));
}
-void GPU_texture_image_unbind_all(void)
+void GPU_texture_image_unbind_all()
{
Context::get()->state_manager->image_unbind_all();
}
@@ -461,7 +449,6 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
reinterpret_cast<Texture *>(tex)->generate_mipmap();
}
-/* Copy a texture content to a similar texture. Only MIP 0 is copied. */
void GPU_texture_copy(GPUTexture *dst_, GPUTexture *src_)
{
Texture *src = reinterpret_cast<Texture *>(src_);
@@ -626,8 +613,7 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *r_size)
* Override texture sampler state for one sampler unit only.
* \{ */
-/* Update user defined sampler states. */
-void GPU_samplers_update(void)
+void GPU_samplers_update()
{
GPUBackend::get()->samplers_update();
}
diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh
index 17c888e4fcd..73b59b9f06f 100644
--- a/source/blender/gpu/intern/gpu_texture_private.hh
+++ b/source/blender/gpu/intern/gpu_texture_private.hh
@@ -66,7 +66,7 @@ ENUM_OPERATORS(eGPUTextureType, GPU_TEXTURE_CUBE_ARRAY)
#endif
/* Maximum number of FBOs a texture can be attached to. */
-#define GPU_TEX_MAX_FBO_ATTACHED 20
+#define GPU_TEX_MAX_FBO_ATTACHED 32
/**
* Implementation of Textures.
@@ -123,7 +123,7 @@ class Texture {
bool init_cubemap(int w, int layers, eGPUTextureFormat format);
bool init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format);
- virtual void generate_mipmap(void) = 0;
+ virtual void generate_mipmap() = 0;
virtual void copy_to(Texture *tex) = 0;
virtual void clear(eGPUDataFormat format, const void *data) = 0;
virtual void swizzle_set(const char swizzle_mask[4]) = 0;
@@ -138,17 +138,17 @@ class Texture {
int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) = 0;
/* TODO(fclem): Legacy. Should be removed at some point. */
- virtual uint gl_bindcode_get(void) const = 0;
+ virtual uint gl_bindcode_get() const = 0;
- int width_get(void) const
+ int width_get() const
{
return w_;
}
- int height_get(void) const
+ int height_get() const
{
return h_;
}
- int depth_get(void) const
+ int depth_get() const
{
return d_;
}
@@ -188,7 +188,7 @@ class Texture {
}
/* Return number of dimension taking the array type into account. */
- int dimensions_count(void) const
+ int dimensions_count() const
{
const int array = (type_ & GPU_TEXTURE_ARRAY) ? 1 : 0;
switch (type_ & ~GPU_TEXTURE_ARRAY) {
@@ -205,7 +205,7 @@ class Texture {
}
}
/* Return number of array layer (or face layer) for texture array or 1 for the others. */
- int layer_count(void) const
+ int layer_count() const
{
switch (type_) {
case GPU_TEXTURE_1D_ARRAY:
@@ -218,15 +218,15 @@ class Texture {
}
}
- eGPUTextureFormat format_get(void) const
+ eGPUTextureFormat format_get() const
{
return format_;
}
- eGPUTextureFormatFlag format_flag_get(void) const
+ eGPUTextureFormatFlag format_flag_get() const
{
return format_flag_;
}
- eGPUTextureType type_get(void) const
+ eGPUTextureType type_get() const
{
return type_;
}
@@ -248,7 +248,7 @@ class Texture {
}
protected:
- virtual bool init_internal(void) = 0;
+ virtual bool init_internal() = 0;
virtual bool init_internal(GPUVertBuf *vbo) = 0;
};
@@ -348,23 +348,12 @@ inline eGPUTextureFormatFlag to_format_flag(eGPUTextureFormat format)
case GPU_DEPTH24_STENCIL8:
case GPU_DEPTH32F_STENCIL8:
return GPU_FORMAT_DEPTH_STENCIL;
- case GPU_R8I:
case GPU_R8UI:
+ case GPU_RG16I:
case GPU_R16I:
+ case GPU_RG16UI:
case GPU_R16UI:
case GPU_R32UI:
- case GPU_RG8I:
- case GPU_RG8UI:
- case GPU_RG16I:
- case GPU_RG16UI:
- case GPU_RG32I:
- case GPU_RG32UI:
- case GPU_RGBA8I:
- case GPU_RGBA8UI:
- case GPU_RGBA16I:
- case GPU_RGBA16UI:
- case GPU_RGBA32I:
- case GPU_RGBA32UI:
return GPU_FORMAT_INTEGER;
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
@@ -381,16 +370,11 @@ inline eGPUTextureFormatFlag to_format_flag(eGPUTextureFormat format)
inline int to_component_len(eGPUTextureFormat format)
{
switch (format) {
- case GPU_RGBA8UI:
- case GPU_RGBA8I:
case GPU_RGBA8:
- case GPU_RGBA32UI:
- case GPU_RGBA32I:
- case GPU_RGBA32F:
- case GPU_RGBA16UI:
- case GPU_RGBA16I:
+ case GPU_RGBA8UI:
case GPU_RGBA16F:
case GPU_RGBA16:
+ case GPU_RGBA32F:
case GPU_SRGB8_A8:
case GPU_RGB10_A2:
return 4;
@@ -444,27 +428,16 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da
case GPU_DEPTH24_STENCIL8:
case GPU_DEPTH32F_STENCIL8:
return data_format == GPU_DATA_UINT_24_8;
+ case GPU_R8UI:
case GPU_R16UI:
- case GPU_R32UI:
case GPU_RG16UI:
- case GPU_RG32UI:
- case GPU_RGBA16UI:
- case GPU_RGBA32UI:
+ case GPU_R32UI:
return data_format == GPU_DATA_UINT;
- case GPU_R16I:
- case GPU_R32I:
- case GPU_R8I:
case GPU_RG16I:
- case GPU_RG32I:
- case GPU_RG8I:
- case GPU_RGBA16I:
- case GPU_RGBA32I:
- case GPU_RGBA8I:
+ case GPU_R16I:
return data_format == GPU_DATA_INT;
case GPU_R8:
- case GPU_R8UI:
case GPU_RG8:
- case GPU_RG8UI:
case GPU_RGBA8:
case GPU_RGBA8UI:
case GPU_SRGB8_A8:
@@ -489,27 +462,16 @@ inline eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
case GPU_DEPTH24_STENCIL8:
case GPU_DEPTH32F_STENCIL8:
return GPU_DATA_UINT_24_8;
+ case GPU_R8UI:
case GPU_R16UI:
- case GPU_R32UI:
case GPU_RG16UI:
- case GPU_RG32UI:
- case GPU_RGBA16UI:
- case GPU_RGBA32UI:
+ case GPU_R32UI:
return GPU_DATA_UINT;
- case GPU_R16I:
- case GPU_R32I:
- case GPU_R8I:
case GPU_RG16I:
- case GPU_RG32I:
- case GPU_RG8I:
- case GPU_RGBA16I:
- case GPU_RGBA32I:
- case GPU_RGBA8I:
+ case GPU_R16I:
return GPU_DATA_INT;
case GPU_R8:
- case GPU_R8UI:
case GPU_RG8:
- case GPU_RG8UI:
case GPU_RGBA8:
case GPU_RGBA8UI:
case GPU_SRGB8_A8:
diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc
index 3a9269d1753..332875ba81f 100644
--- a/source/blender/gpu/intern/gpu_uniform_buffer.cc
+++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc
@@ -201,12 +201,6 @@ GPUUniformBuf *GPU_uniformbuf_create_ex(size_t size, const void *data, const cha
return wrap(ubo);
}
-/**
- * Create UBO from inputs list.
- * Return NULL if failed to create or if \param inputs: is empty.
- *
- * \param inputs: ListBase of #BLI_genericNodeN(#GPUInput).
- */
GPUUniformBuf *GPU_uniformbuf_create_from_list(ListBase *inputs, const char *name)
{
/* There is no point on creating an UBO if there is no arguments. */
@@ -245,7 +239,7 @@ void GPU_uniformbuf_unbind(GPUUniformBuf *ubo)
unwrap(ubo)->unbind();
}
-void GPU_uniformbuf_unbind_all(void)
+void GPU_uniformbuf_unbind_all()
{
/* FIXME */
}
diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh
index e8fc1343eaf..018b85c865e 100644
--- a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh
+++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh
@@ -54,7 +54,7 @@ class UniformBuf {
virtual void update(const void *data) = 0;
virtual void bind(int slot) = 0;
- virtual void unbind(void) = 0;
+ virtual void unbind() = 0;
/** Used to defer data upload at drawing time.
* This is useful if the thread has no context bound.
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc
index 956d89ff832..dba31f501f2 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.cc
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc
@@ -144,6 +144,12 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts_,
unwrap(verts_)->init(format, usage);
}
+void GPU_vertbuf_init_build_on_device(GPUVertBuf *verts, GPUVertFormat *format, uint v_len)
+{
+ GPU_vertbuf_init_with_format_ex(verts, format, GPU_USAGE_DEVICE_ONLY);
+ GPU_vertbuf_data_alloc(verts, v_len);
+}
+
GPUVertBuf *GPU_vertbuf_duplicate(GPUVertBuf *verts_)
{
return wrap(unwrap(verts_)->duplicate());
@@ -159,7 +165,6 @@ void *GPU_vertbuf_unmap(const GPUVertBuf *verts, const void *mapped_data)
return unwrap(verts)->unmap(mapped_data);
}
-/** Same as discard but does not free. */
void GPU_vertbuf_clear(GPUVertBuf *verts)
{
unwrap(verts)->clear();
@@ -183,21 +188,16 @@ void GPU_vertbuf_handle_ref_remove(GPUVertBuf *verts)
/* -------- Data update -------- */
-/* create a new allocation, discarding any existing data */
void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len)
{
unwrap(verts)->allocate(v_len);
}
-/* resize buffer keeping existing data */
void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len)
{
unwrap(verts)->resize(v_len);
}
-/* Set vertex count but does not change allocation.
- * Only this many verts will be uploaded to the GPU and rendered.
- * This is useful for streaming data. */
void GPU_vertbuf_data_len_set(GPUVertBuf *verts_, uint v_len)
{
VertBuf *verts = unwrap(verts_);
@@ -229,7 +229,6 @@ void GPU_vertbuf_attr_fill(GPUVertBuf *verts_, uint a_idx, const void *data)
GPU_vertbuf_attr_fill_stride(verts_, a_idx, stride, data);
}
-/** Fills a whole vertex (all attributes). Data must match packed layout. */
void GPU_vertbuf_vert_set(GPUVertBuf *verts_, uint v_idx, const void *data)
{
VertBuf *verts = unwrap(verts_);
@@ -284,17 +283,12 @@ void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts_, uint a_idx, GPUVertBufRaw
/* -------- Getters -------- */
-/* NOTE: Be careful when using this. The data needs to match the expected format. */
-void *GPU_vertbuf_get_data(GPUVertBuf *verts_)
+void *GPU_vertbuf_get_data(const GPUVertBuf *verts)
{
/* TODO: Assert that the format has no padding. */
- VertBuf *verts = unwrap(verts_);
- verts->flag |= GPU_VERTBUF_DATA_DIRTY;
- return verts->data;
+ return unwrap(verts)->data;
}
-/* Returns the data buffer and set it to null internally to avoid freeing.
- * NOTE: Be careful when using this. The data needs to match the expected format. */
void *GPU_vertbuf_steal_data(GPUVertBuf *verts_)
{
VertBuf *verts = unwrap(verts_);
@@ -325,25 +319,32 @@ GPUVertBufStatus GPU_vertbuf_get_status(const GPUVertBuf *verts)
return unwrap(verts)->flag;
}
+void GPU_vertbuf_tag_dirty(GPUVertBuf *verts)
+{
+ unwrap(verts)->flag |= GPU_VERTBUF_DATA_DIRTY;
+}
+
uint GPU_vertbuf_get_memory_usage()
{
return VertBuf::memory_usage;
}
-/* Should be rename to GPU_vertbuf_data_upload */
void GPU_vertbuf_use(GPUVertBuf *verts)
{
unwrap(verts)->upload();
}
+void GPU_vertbuf_wrap_handle(GPUVertBuf *verts, uint64_t handle)
+{
+ unwrap(verts)->wrap_handle(handle);
+}
+
void GPU_vertbuf_bind_as_ssbo(struct GPUVertBuf *verts, int binding)
{
unwrap(verts)->bind_as_ssbo(binding);
}
-/* XXX this is just a wrapper for the use of the Hair refine workaround.
- * To be used with GPU_vertbuf_use(). */
-void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, void *data)
+void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, const void *data)
{
unwrap(verts)->update_sub(start, len, data);
}
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
index 9531c2c1a5f..97514b382b1 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
+++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
@@ -60,34 +60,36 @@ class VertBuf {
virtual ~VertBuf();
void init(const GPUVertFormat *format, GPUUsageType usage);
- void clear(void);
+ void clear();
/* Data management. */
void allocate(uint vert_len);
void resize(uint vert_len);
- void upload(void);
+ void upload();
virtual void bind_as_ssbo(uint binding) = 0;
- VertBuf *duplicate(void);
+ virtual void wrap_handle(uint64_t handle) = 0;
+
+ VertBuf *duplicate();
/* Size of the data allocated. */
- size_t size_alloc_get(void) const
+ size_t size_alloc_get() const
{
BLI_assert(format.packed);
return vertex_alloc * format.stride;
}
/* Size of the data uploaded to the GPU. */
- size_t size_used_get(void) const
+ size_t size_used_get() const
{
BLI_assert(format.packed);
return vertex_len * format.stride;
}
- void reference_add(void)
+ void reference_add()
{
handle_refcount_++;
}
- void reference_remove(void)
+ void reference_remove()
{
BLI_assert(handle_refcount_ > 0);
handle_refcount_--;
@@ -96,15 +98,15 @@ class VertBuf {
}
}
- virtual void update_sub(uint start, uint len, void *data) = 0;
+ virtual void update_sub(uint start, uint len, const void *data) = 0;
virtual const void *read() const = 0;
virtual void *unmap(const void *mapped_data) const = 0;
protected:
- virtual void acquire_data(void) = 0;
- virtual void resize_data(void) = 0;
- virtual void release_data(void) = 0;
- virtual void upload_data(void) = 0;
+ virtual void acquire_data() = 0;
+ virtual void resize_data() = 0;
+ virtual void release_data() = 0;
+ virtual void upload_data() = 0;
virtual void duplicate_data(VertBuf *dst) = 0;
};
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index 78a119bcec8..ad45f2a4d7b 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -190,17 +190,6 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
attr->names[attr->name_len++] = copy_attr_name(format, alias);
}
-/**
- * Makes vertex attribute from the next vertices to be accessible in the vertex shader.
- * For an attribute named "attr" you can access the next nth vertex using "attr{number}".
- * Use this function after specifying all the attributes in the format.
- *
- * NOTE: This does NOT work when using indexed rendering.
- * NOTE: Only works for first attribute name. (this limitation can be changed if needed)
- *
- * WARNING: this function creates a lot of aliases/attributes, make sure to keep the attribute
- * name short to avoid overflowing the name-buffer.
- */
void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count)
{
/* Sanity check. Maximum can be upgraded if needed. */
@@ -271,8 +260,6 @@ static void safe_bytes(char out[11], const char data[8])
}
}
-/* Warning: Always add a prefix to the result of this function as
- * the generated string can start with a number and not be a valid attribute name. */
void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint UNUSED(max_len))
{
char data[8] = {0};
@@ -306,20 +293,6 @@ void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uin
#endif
}
-/**
- * Make attribute layout non-interleaved.
- * Warning! This does not change data layout!
- * Use direct buffer access to fill the data.
- * This is for advanced usage.
- *
- * De-interleaved data means all attribute data for each attribute
- * is stored continuously like this:
- * 000011112222
- * instead of:
- * 012012012012
- *
- * \note This is per attribute de-interleaving, NOT per component.
- */
void GPU_vertformat_deinterleave(GPUVertFormat *format)
{
/* Ideally we should change the stride and offset here. This would allow
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index ccd9a4c061b..6d8ff8e7088 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -137,19 +137,25 @@ struct DRWData **GPU_viewport_data_get(GPUViewport *viewport)
static void gpu_viewport_textures_create(GPUViewport *viewport)
{
int *size = viewport->size;
+ float empty_pixel_fl[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ uchar empty_pixel_u[4] = {0, 0, 0, 0};
if (viewport->color_render_tx[0] == NULL) {
viewport->color_render_tx[0] = GPU_texture_create_2d(
"dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL);
+ GPU_texture_clear(viewport->color_render_tx[0], GPU_DATA_FLOAT, empty_pixel_fl);
viewport->color_overlay_tx[0] = GPU_texture_create_2d(
"dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL);
+ GPU_texture_clear(viewport->color_overlay_tx[0], GPU_DATA_UBYTE, empty_pixel_u);
}
if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0 && viewport->color_render_tx[1] == NULL) {
viewport->color_render_tx[1] = GPU_texture_create_2d(
"dtxl_color_stereo", UNPACK2(size), 1, GPU_RGBA16F, NULL);
+ GPU_texture_clear(viewport->color_render_tx[1], GPU_DATA_FLOAT, empty_pixel_fl);
viewport->color_overlay_tx[1] = GPU_texture_create_2d(
"dtxl_color_overlay_stereo", UNPACK2(size), 1, GPU_SRGB8_A8, NULL);
+ GPU_texture_clear(viewport->color_overlay_tx[1], GPU_DATA_UBYTE, empty_pixel_u);
}
/* Can be shared with GPUOffscreen. */
@@ -194,7 +200,6 @@ void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
viewport->active_view = view;
}
-/* Should be called from DRW after DRW_opengl_context_enable. */
void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs)
{
GPUTexture *color, *depth;
@@ -258,7 +263,6 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
viewport->do_color_management = true;
}
-/* Merge the stereo textures. `color` and `overlay` texture will be modified. */
void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format)
{
if (!ELEM(stereo_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
@@ -452,10 +456,6 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
}
}
-/**
- * Version of #GPU_viewport_draw_to_screen() that lets caller decide if display colorspace
- * transform should be performed.
- */
void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
int view,
const rcti *rect,
@@ -508,21 +508,11 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
viewport, view, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge);
}
-/**
- * Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
- * color transform to display space.
- *
- * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done
- * with inversed axis coordinates (upside down or sideways).
- */
void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
{
GPU_viewport_draw_to_screen_ex(viewport, view, rect, true, true);
}
-/**
- * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`.
- */
void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport,
struct GPUOffScreen *ofs,
bool display_colorspace,
@@ -587,18 +577,17 @@ GPUTexture *GPU_viewport_depth_texture(GPUViewport *viewport)
return viewport->depth_tx;
}
-/* Overlay framebuffer for drawing outside of DRW module. */
GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport)
{
- GPU_framebuffer_ensure_config(&viewport->overlay_fb,
- {
- GPU_ATTACHMENT_TEXTURE(viewport->depth_tx),
- GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[0]),
- });
+ GPU_framebuffer_ensure_config(
+ &viewport->overlay_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(viewport->depth_tx),
+ GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[viewport->active_view]),
+ });
return viewport->overlay_fb;
}
-/* Must be executed inside Draw-manager OpenGL Context. */
void GPU_viewport_free(GPUViewport *viewport)
{
if (viewport->draw_data) {