diff options
author | Julian Eisel <julian@blender.org> | 2022-11-10 15:17:42 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2022-11-10 15:17:42 +0300 |
commit | 7246c387435769a169ac24c91434c615df6434b4 (patch) | |
tree | 61842e3e0ce85e80720fdd7476d44d2e629f59fd /source/blender/gpu/intern | |
parent | c5f55d17096d373791363e46004176e3f7f7ae52 (diff) | |
parent | 0b4bd3ddc016298e868169a541cf6c132b10c587 (diff) |
Merge branch 'master' into asset-browser-grid-viewasset-browser-grid-view
Diffstat (limited to 'source/blender/gpu/intern')
30 files changed, 495 insertions, 1656 deletions
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh index d2890efee72..2a545c8114e 100644 --- a/source/blender/gpu/intern/gpu_backend.hh +++ b/source/blender/gpu/intern/gpu_backend.hh @@ -38,7 +38,7 @@ class GPUBackend { virtual void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) = 0; virtual void compute_dispatch_indirect(StorageBuf *indirect_buf) = 0; - virtual Context *context_alloc(void *ghost_window) = 0; + virtual Context *context_alloc(void *ghost_window, void *ghost_context) = 0; virtual Batch *batch_alloc() = 0; virtual DrawList *drawlist_alloc(int list_length) = 0; diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index c871004deac..e1876f6d8ac 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -56,7 +56,6 @@ void GPU_batch_init_ex(GPUBatch *batch, GPUIndexBuf *elem, eGPUBatchFlag owns_flag) { - BLI_assert(verts != nullptr); /* Do not pass any other flag */ BLI_assert((owns_flag & ~(GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX)) == 0); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c deleted file mode 100644 index 78f595cbff2..00000000000 --- a/source/blender/gpu/intern/gpu_buffers.c +++ /dev/null @@ -1,1475 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2005 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup gpu - * - * Mesh drawing using OpenGL VBO (Vertex Buffer Objects) - */ - -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_bitmap.h" -#include "BLI_ghash.h" -#include "BLI_math_color.h" -#include "BLI_utildefines.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BKE_DerivedMesh.h" -#include "BKE_attribute.h" -#include "BKE_ccg.h" -#include "BKE_customdata.h" -#include "BKE_mesh.h" -#include "BKE_paint.h" -#include "BKE_pbvh.h" -#include "BKE_subdiv_ccg.h" - -#include "GPU_batch.h" -#include "GPU_buffers.h" - -#include "DRW_engine.h" - -#include "gpu_private.h" - -#include "bmesh.h" - -struct GPU_PBVH_Buffers { - GPUIndexBuf *index_buf, *index_buf_fast; - GPUIndexBuf *index_lines_buf, *index_lines_buf_fast; - GPUVertBuf *vert_buf; - - GPUBatch *lines; - GPUBatch *lines_fast; - GPUBatch *triangles; - GPUBatch *triangles_fast; - - /* mesh pointers in case buffer allocation fails */ - const MPoly *mpoly; - const MLoop *mloop; - const MLoopTri *looptri; - const MVert *mvert; - - const int *face_indices; - int face_indices_len; - - /* grid pointers */ - CCGKey gridkey; - CCGElem **grids; - const DMFlagMat *grid_flag_mats; - BLI_bitmap *const *grid_hidden; - const int *grid_indices; - int totgrid; - - bool use_bmesh; - bool clear_bmesh_on_flush; - - uint tot_tri, tot_quad; - - short material_index; - - /* The PBVH ensures that either all faces in the node are - * smooth-shaded or all faces are flat-shaded */ - bool smooth; - - bool show_overlay; -}; - -typedef struct GPUAttrRef { - uchar domain, type; - ushort cd_offset; - int layer_idx; -} GPUAttrRef; - -#define MAX_GPU_ATTR 256 - -typedef struct PBVHGPUFormat { - GPUVertFormat format; - uint pos, nor, msk, fset; - uint col[MAX_GPU_ATTR]; - uint uv[MAX_GPU_ATTR]; - int totcol, totuv; - - /* Upload only the active color and UV attributes, - * used for workbench mode. */ - bool active_attrs_only; -} PBVHGPUFormat; - -PBVHGPUFormat *GPU_pbvh_make_format(void) -{ - PBVHGPUFormat *vbo_id = MEM_callocN(sizeof(PBVHGPUFormat), "PBVHGPUFormat"); - - GPU_pbvh_attribute_names_update(PBVH_FACES, vbo_id, NULL, NULL, false); - - return vbo_id; -} - -void GPU_pbvh_free_format(PBVHGPUFormat *vbo_id) -{ - MEM_SAFE_FREE(vbo_id); -} - -static int gpu_pbvh_make_attr_offs(eAttrDomainMask domain_mask, - eCustomDataMask type_mask, - const CustomData *vdata, - const CustomData *edata, - const CustomData *ldata, - const CustomData *pdata, - GPUAttrRef r_cd_attrs[MAX_GPU_ATTR], - bool active_only, - int active_type, - int active_domain, - const CustomDataLayer *active_layer, - const CustomDataLayer *render_layer); - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name PBVH Utils - * \{ */ - -void gpu_pbvh_init() -{ -} - -void gpu_pbvh_exit() -{ - /* Nothing to do. */ -} - -static CustomDataLayer *get_active_layer(const CustomData *cdata, int type) -{ - int idx = CustomData_get_active_layer_index(cdata, type); - return idx != -1 ? cdata->layers + idx : NULL; -} - -static CustomDataLayer *get_render_layer(const CustomData *cdata, int type) -{ - int idx = CustomData_get_render_layer_index(cdata, type); - return idx != -1 ? cdata->layers + idx : NULL; -} - -/* Allocates a non-initialized buffer to be sent to GPU. - * Return is false it indicates that the memory map failed. */ -static bool gpu_pbvh_vert_buf_data_set(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - uint vert_len) -{ - /* Keep so we can test #GPU_USAGE_DYNAMIC buffer use. - * Not that format initialization match in both blocks. - * Do this to keep braces balanced - otherwise indentation breaks. */ - - if (buffers->vert_buf == NULL) { - /* Initialize vertex buffer (match 'VertexBufferFormat'). */ - buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&vbo_id->format, GPU_USAGE_STATIC); - } - if (GPU_vertbuf_get_data(buffers->vert_buf) == NULL || - GPU_vertbuf_get_vertex_len(buffers->vert_buf) != vert_len) { - /* Allocate buffer if not allocated yet or size changed. */ - GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); - } - - return GPU_vertbuf_get_data(buffers->vert_buf) != NULL; -} - -static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) -{ - if (buffers->triangles == NULL) { - buffers->triangles = GPU_batch_create(prim, - buffers->vert_buf, - /* can be NULL if buffer is empty */ - buffers->index_buf); - } - - if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { - buffers->triangles_fast = GPU_batch_create(prim, buffers->vert_buf, buffers->index_buf_fast); - } - - if (buffers->lines == NULL) { - buffers->lines = GPU_batch_create(GPU_PRIM_LINES, - buffers->vert_buf, - /* can be NULL if buffer is empty */ - buffers->index_lines_buf); - } - - if ((buffers->lines_fast == NULL) && buffers->index_lines_buf_fast) { - buffers->lines_fast = GPU_batch_create( - GPU_PRIM_LINES, buffers->vert_buf, buffers->index_lines_buf_fast); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Mesh PBVH - * \{ */ - -static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, const bool *hide_poly) -{ - return !paint_is_face_hidden(lt, hide_poly); -} - -void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - const Mesh *mesh, - const MVert *mvert, - const float *vmask, - const int *sculpt_face_sets, - int face_sets_color_seed, - int face_sets_color_default, - int update_flags, - const float (*vert_normals)[3]) -{ - GPUAttrRef vcol_refs[MAX_GPU_ATTR]; - GPUAttrRef cd_uvs[MAX_GPU_ATTR]; - - const bool *hide_poly = (const bool *)CustomData_get_layer_named( - &mesh->pdata, CD_PROP_BOOL, ".hide_poly"); - const int *material_indices = (const int *)CustomData_get_layer_named( - &mesh->pdata, CD_PROP_INT32, "material_index"); - - const CustomDataLayer *actcol = BKE_id_attributes_active_color_get(&mesh->id); - eAttrDomain actcol_domain = actcol ? BKE_id_attribute_domain(&mesh->id, actcol) : - ATTR_DOMAIN_AUTO; - - const CustomDataLayer *rendercol = BKE_id_attributes_render_color_get(&mesh->id); - - int totcol; - - if (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) { - totcol = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_COLOR, - CD_MASK_COLOR_ALL, - &mesh->vdata, - NULL, - &mesh->ldata, - NULL, - vcol_refs, - vbo_id->active_attrs_only, - actcol ? actcol->type : 0, - actcol_domain, - actcol, - rendercol); - } - else { - totcol = 0; - } - - int totuv = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_CORNER, - CD_MASK_MLOOPUV, - NULL, - NULL, - &mesh->ldata, - NULL, - cd_uvs, - vbo_id->active_attrs_only, - CD_MLOOPUV, - ATTR_DOMAIN_CORNER, - get_active_layer(&mesh->ldata, CD_MLOOPUV), - get_render_layer(&mesh->ldata, CD_MLOOPUV)); - - const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_face_sets = sculpt_face_sets && - (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; - bool empty_mask = true; - bool default_face_set = true; - - { - const int totelem = buffers->tot_tri * 3; - - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(vbo_id, buffers, totelem)) { - GPUVertBufRaw pos_step = {0}; - GPUVertBufRaw nor_step = {0}; - GPUVertBufRaw msk_step = {0}; - GPUVertBufRaw fset_step = {0}; - GPUVertBufRaw col_step = {0}; - GPUVertBufRaw uv_step = {0}; - - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->pos, &pos_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->nor, &nor_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->msk, &msk_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->fset, &fset_step); - - /* calculate normal for each polygon only once */ - uint mpoly_prev = UINT_MAX; - short no[3] = {0, 0, 0}; - - if (totuv > 0) { - for (int uv_i = 0; uv_i < totuv; uv_i++) { - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->uv[uv_i], &uv_step); - - GPUAttrRef *ref = cd_uvs + uv_i; - CustomDataLayer *layer = mesh->ldata.layers + ref->layer_idx; - MLoopUV *muv = layer->data; - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - - if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) { - continue; - } - - for (uint j = 0; j < 3; j++) { - MLoopUV *muv2 = muv + lt->tri[j]; - - memcpy(GPU_vertbuf_raw_step(&uv_step), muv2->uv, sizeof(muv2->uv)); - } - } - } - } - - for (int col_i = 0; col_i < totcol; col_i++) { - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->col[col_i], &col_step); - - const MPropCol *pcol = NULL; - const MLoopCol *mcol = NULL; - - GPUAttrRef *ref = vcol_refs + col_i; - const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? &mesh->vdata : &mesh->ldata; - const CustomDataLayer *layer = cdata->layers + ref->layer_idx; - - bool color_loops = ref->domain == ATTR_DOMAIN_CORNER; - - if (layer->type == CD_PROP_COLOR) { - pcol = (const MPropCol *)layer->data; - } - else { - mcol = (const MLoopCol *)layer->data; - } - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const uint vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; - - if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) { - continue; - } - - for (uint j = 0; j < 3; j++) { - /* Vertex Colors. */ - const uint loop_index = lt->tri[j]; - - ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - - if (pcol) { - const MPropCol *pcol2 = pcol + (color_loops ? loop_index : vtri[j]); - - scol[0] = unit_float_to_ushort_clamp(pcol2->color[0]); - scol[1] = unit_float_to_ushort_clamp(pcol2->color[1]); - scol[2] = unit_float_to_ushort_clamp(pcol2->color[2]); - scol[3] = unit_float_to_ushort_clamp(pcol2->color[3]); - } - else { - const MLoopCol *mcol2 = mcol + (color_loops ? loop_index : vtri[j]); - - scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->r]); - scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->g]); - scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->b]); - scol[3] = unit_float_to_ushort_clamp(mcol2->a * (1.0f / 255.0f)); - } - - memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol)); - } - } - } - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const uint vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; - - if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) { - continue; - } - - /* Face normal and mask */ - if (lt->poly != mpoly_prev && !buffers->smooth) { - const MPoly *mp = &buffers->mpoly[lt->poly]; - float fno[3]; - BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno); - normal_float_to_short_v3(no, fno); - mpoly_prev = lt->poly; - } - - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - if (show_face_sets) { - const int fset = abs(sculpt_face_sets[lt->poly]); - /* Skip for the default color Face Set to render it white. */ - if (fset != face_sets_color_default) { - BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); - default_face_set = false; - } - } - - float fmask = 0.0f; - uchar cmask = 0; - if (show_mask && !buffers->smooth) { - fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; - cmask = (uchar)(fmask * 255); - } - - for (uint j = 0; j < 3; j++) { - const MVert *v = &mvert[vtri[j]]; - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co); - - if (buffers->smooth) { - normal_float_to_short_v3(no, vert_normals[vtri[j]]); - } - copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no); - - if (show_mask && buffers->smooth) { - cmask = (uchar)(vmask[vtri[j]] * 255); - } - - *(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask; - empty_mask = empty_mask && (cmask == 0); - /* Face Sets. */ - memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3])); - } - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - - /* Get material index from the first face of this buffer. */ - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; - buffers->material_index = material_indices ? material_indices[lt->poly] : 0; - - buffers->show_overlay = !empty_mask || !default_face_set; - buffers->mvert = mvert; -} - -GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh, - const MLoopTri *looptri, - const int *face_indices, - const int face_indices_len) -{ - GPU_PBVH_Buffers *buffers; - int i, tottri; - int tot_real_edges = 0; - - const MPoly *polys = BKE_mesh_polys(mesh); - const MLoop *loops = BKE_mesh_loops(mesh); - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - - const bool *hide_poly = (bool *)CustomData_get_layer_named( - &mesh->pdata, CD_PROP_BOOL, ".hide_poly"); - - /* smooth or flat for all */ - buffers->smooth = polys[looptri[face_indices[0]].poly].flag & ME_SMOOTH; - - buffers->show_overlay = false; - - /* Count the number of visible triangles */ - for (i = 0, tottri = 0; i < face_indices_len; i++) { - const MLoopTri *lt = &looptri[face_indices[i]]; - if (gpu_pbvh_is_looptri_visible(lt, hide_poly)) { - int r_edges[3]; - BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges); - for (int j = 0; j < 3; j++) { - if (r_edges[j] != -1) { - tot_real_edges++; - } - } - tottri++; - } - } - - if (tottri == 0) { - buffers->tot_tri = 0; - - buffers->mpoly = polys; - buffers->mloop = loops; - buffers->looptri = looptri; - buffers->face_indices = face_indices; - buffers->face_indices_len = 0; - - return buffers; - } - - /* Fill the only the line buffer. */ - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX); - int vert_idx = 0; - - for (i = 0; i < face_indices_len; i++) { - const MLoopTri *lt = &looptri[face_indices[i]]; - - /* Skip hidden faces */ - if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) { - continue; - } - - int r_edges[3]; - BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges); - if (r_edges[0] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1); - } - if (r_edges[1] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2); - } - if (r_edges[2] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0); - } - - vert_idx++; - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - - buffers->tot_tri = tottri; - - buffers->mpoly = polys; - buffers->mloop = loops; - buffers->looptri = looptri; - - buffers->face_indices = face_indices; - buffers->face_indices_len = face_indices_len; - - return buffers; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Grid PBVH - * \{ */ - -static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers, - SubdivCCG *UNUSED(subdiv_ccg), - const int *UNUSED(face_sets), - const int *grid_indices, - uint visible_quad_len, - int totgrid, - int gridsize) -{ - GPUIndexBufBuilder elb, elb_lines; - GPUIndexBufBuilder elb_fast, elb_lines_fast; - - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX); - GPU_indexbuf_init(&elb_fast, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX); - GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); - - if (buffers->smooth) { - uint offset = 0; - const uint grid_vert_len = gridsize * gridsize; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - uint v0, v1, v2, v3; - bool grid_visible = false; - - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - for (int j = 0; j < gridsize - 1; j++) { - for (int k = 0; k < gridsize - 1; k++) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { - continue; - } - /* Indices in a Clockwise QUAD disposition. */ - v0 = offset + j * gridsize + k; - v1 = v0 + 1; - v2 = v1 + gridsize; - v3 = v2 - 1; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - - if (grid_visible) { - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + gridsize - 1; - v2 = offset + grid_vert_len - 1; - v3 = offset + grid_vert_len - gridsize; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - else { - uint offset = 0; - const uint grid_vert_len = square_uint(gridsize - 1) * 4; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - bool grid_visible = false; - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - uint v0, v1, v2, v3; - for (int j = 0; j < gridsize - 1; j++) { - for (int k = 0; k < gridsize - 1; k++) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { - continue; - } - /* VBO data are in a Clockwise QUAD disposition. */ - v0 = offset + (j * (gridsize - 1) + k) * 4; - v1 = v0 + 1; - v2 = v0 + 2; - v3 = v0 + 3; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - - if (grid_visible) { - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + (gridsize - 1) * 4 - 3; - v2 = offset + grid_vert_len - 2; - v3 = offset + grid_vert_len - (gridsize - 1) * 4 + 3; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - - buffers->index_buf = GPU_indexbuf_build(&elb); - buffers->index_buf_fast = GPU_indexbuf_build(&elb_fast); - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast); -} - -void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers, - const struct DMFlagMat *grid_flag_mats, - const int *grid_indices) -{ - const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; - - if (buffers->smooth != smooth) { - buffers->smooth = smooth; - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - } -} - -void GPU_pbvh_grid_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - SubdivCCG *subdiv_ccg, - CCGElem **grids, - const struct DMFlagMat *grid_flag_mats, - int *grid_indices, - int totgrid, - const int *sculpt_face_sets, - const int face_sets_color_seed, - const int face_sets_color_default, - const struct CCGKey *key, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; - const bool show_face_sets = sculpt_face_sets && - (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; - bool empty_mask = true; - bool default_face_set = true; - - int i, j, k, x, y; - - /* Build VBO */ - const int has_mask = key->has_mask; - - uint vert_per_grid = (buffers->smooth) ? key->grid_area : (square_i(key->grid_size - 1) * 4); - uint vert_count = totgrid * vert_per_grid; - - if (buffers->index_buf == NULL) { - uint visible_quad_len = BKE_pbvh_count_grid_quads( - (BLI_bitmap **)buffers->grid_hidden, grid_indices, totgrid, key->grid_size); - - /* totally hidden node, return here to avoid BufferData with zero below. */ - if (visible_quad_len == 0) { - return; - } - - gpu_pbvh_grid_fill_index_buffers(buffers, - subdiv_ccg, - sculpt_face_sets, - grid_indices, - visible_quad_len, - totgrid, - key->grid_size); - } - - uint vbo_index_offset = 0; - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(vbo_id, buffers, vert_count)) { - GPUIndexBufBuilder elb_lines; - - if (buffers->index_lines_buf == NULL) { - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); - } - - for (i = 0; i < totgrid; i++) { - const int grid_index = grid_indices[i]; - CCGElem *grid = grids[grid_index]; - int vbo_index = vbo_index_offset; - - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - - if (show_face_sets && subdiv_ccg && sculpt_face_sets) { - const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid_index); - - const int fset = abs(sculpt_face_sets[face_index]); - /* Skip for the default color Face Set to render it white. */ - if (fset != face_sets_color_default) { - BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); - default_face_set = false; - } - } - - if (buffers->smooth) { - for (y = 0; y < key->grid_size; y++) { - for (x = 0; x < key->grid_size; x++) { - CCGElem *elem = CCG_grid_elem(key, grid, x, y); - GPU_vertbuf_attr_set( - buffers->vert_buf, vbo_id->pos, vbo_index, CCG_elem_co(key, elem)); - - short no_short[3]; - normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index, no_short); - - if (has_mask && show_mask) { - float fmask = *CCG_elem_mask(key, elem); - uchar cmask = (uchar)(fmask * 255); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index, &cmask); - empty_mask = empty_mask && (cmask == 0); - } - - if (show_vcol) { - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index, &vcol); - } - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index, &face_set_color); - - vbo_index += 1; - } - } - vbo_index_offset += key->grid_area; - } - else { - for (j = 0; j < key->grid_size - 1; j++) { - for (k = 0; k < key->grid_size - 1; k++) { - CCGElem *elems[4] = { - CCG_grid_elem(key, grid, k, j), - CCG_grid_elem(key, grid, k + 1, j), - CCG_grid_elem(key, grid, k + 1, j + 1), - CCG_grid_elem(key, grid, k, j + 1), - }; - float *co[4] = { - CCG_elem_co(key, elems[0]), - CCG_elem_co(key, elems[1]), - CCG_elem_co(key, elems[2]), - CCG_elem_co(key, elems[3]), - }; - - float fno[3]; - short no_short[3]; - /* NOTE: Clockwise indices ordering, that's why we invert order here. */ - normal_quad_v3(fno, co[3], co[2], co[1], co[0]); - normal_float_to_short_v3(no_short, fno); - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 0, co[0]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 0, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 1, co[1]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 1, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 2, co[2]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 2, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 3, co[3]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 3, no_short); - - if (has_mask && show_mask) { - float fmask = (*CCG_elem_mask(key, elems[0]) + *CCG_elem_mask(key, elems[1]) + - *CCG_elem_mask(key, elems[2]) + *CCG_elem_mask(key, elems[3])) * - 0.25f; - uchar cmask = (uchar)(fmask * 255); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 0, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 1, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 2, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 3, &cmask); - empty_mask = empty_mask && (cmask == 0); - } - - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 0, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 1, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 2, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 3, &vcol); - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 0, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 1, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 2, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 3, &face_set_color); - - vbo_index += 4; - } - } - vbo_index_offset += square_i(key->grid_size - 1) * 4; - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - - /* Get material index from the first face of this buffer. */ - buffers->material_index = grid_flag_mats[grid_indices[0]].mat_nr; - - buffers->grids = grids; - buffers->grid_indices = grid_indices; - buffers->totgrid = totgrid; - buffers->grid_flag_mats = grid_flag_mats; - buffers->gridkey = *key; - buffers->show_overlay = !empty_mask || !default_face_set; -} - -GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden, bool smooth) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->grid_hidden = grid_hidden; - buffers->totgrid = totgrid; - buffers->smooth = smooth; - - buffers->show_overlay = false; - - return buffers; -} - -#undef FILL_QUAD_BUFFER - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name BMesh PBVH - * \{ */ - -/* Output a BMVert into a VertexBufferFormat array at v_index. */ -static void gpu_bmesh_vert_to_buffer_copy(PBVHGPUFormat *vbo_id, - BMVert *v, - GPUVertBuf *vert_buf, - int v_index, - const float fno[3], - const float *fmask, - const int cd_vert_mask_offset, - const bool show_mask, - const bool show_vcol, - bool *empty_mask) -{ - /* Vertex should always be visible if it's used by a visible face. */ - BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN)); - - /* Set coord, normal, and mask */ - GPU_vertbuf_attr_set(vert_buf, vbo_id->pos, v_index, v->co); - - short no_short[3]; - normal_float_to_short_v3(no_short, fno ? fno : v->no); - GPU_vertbuf_attr_set(vert_buf, vbo_id->nor, v_index, no_short); - - if (show_mask) { - float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - uchar cmask = (uchar)(effective_mask * 255); - GPU_vertbuf_attr_set(vert_buf, vbo_id->msk, v_index, &cmask); - *empty_mask = *empty_mask && (cmask == 0); - } - - if (show_vcol) { - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(vert_buf, vbo_id->col[0], v_index, &vcol); - } - - /* Add default face sets color to avoid artifacts. */ - const uchar face_set[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - GPU_vertbuf_attr_set(vert_buf, vbo_id->fset, v_index, &face_set); -} - -/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */ -static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts, GSet *bm_other_verts) -{ - GSetIterator gs_iter; - int totvert = 0; - - GSET_ITER (gs_iter, bm_unique_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - totvert++; - } - } - GSET_ITER (gs_iter, bm_other_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - totvert++; - } - } - - return totvert; -} - -/* Return the total number of visible faces */ -static int gpu_bmesh_face_visible_count(GSet *bm_faces) -{ - GSetIterator gh_iter; - int totface = 0; - - GSET_ITER (gh_iter, bm_faces) { - BMFace *f = BLI_gsetIterator_getKey(&gh_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - totface++; - } - } - - return totface; -} - -void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers) -{ - if (buffers->smooth) { - /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */ - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - } - else { - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - } -} - -void GPU_pbvh_bmesh_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - BMesh *bm, - GSet *bm_faces, - GSet *bm_unique_verts, - GSet *bm_other_verts, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; - int tottri, totvert; - bool empty_mask = true; - BMFace *f = NULL; - - /* Count visible triangles */ - tottri = gpu_bmesh_face_visible_count(bm_faces); - - if (buffers->smooth) { - /* Count visible vertices */ - totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts); - } - else { - totvert = tottri * 3; - } - - if (!tottri) { - if (BLI_gset_len(bm_faces) != 0) { - /* Node is just hidden. */ - } - else { - buffers->clear_bmesh_on_flush = true; - } - buffers->tot_tri = 0; - return; - } - - /* TODO: make mask layer optional for bmesh buffer. */ - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - - /* Fill vertex buffer */ - if (!gpu_pbvh_vert_buf_data_set(vbo_id, buffers, totvert)) { - /* Memory map failed */ - return; - } - - int v_index = 0; - - if (buffers->smooth) { - /* Fill the vertex and triangle buffer in one pass over faces. */ - GPUIndexBufBuilder elb, elb_lines; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); - - GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert); - - GSetIterator gs_iter; - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - BM_face_as_array_vert_tri(f, v); - - uint idx[3]; - for (int i = 0; i < 3; i++) { - void **idx_p; - if (!BLI_ghash_ensure_p(bm_vert_to_index, v[i], &idx_p)) { - /* Add vertex to the vertex buffer each time a new one is encountered */ - *idx_p = POINTER_FROM_UINT(v_index); - - gpu_bmesh_vert_to_buffer_copy(vbo_id, - v[i], - buffers->vert_buf, - v_index, - NULL, - NULL, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - - idx[i] = v_index; - v_index++; - } - else { - /* Vertex already in the vertex buffer, just get the index. */ - idx[i] = POINTER_AS_UINT(*idx_p); - } - } - - GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); - - GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); - } - } - - BLI_ghash_free(bm_vert_to_index, NULL, NULL); - - buffers->tot_tri = tottri; - if (buffers->index_buf == NULL) { - buffers->index_buf = GPU_indexbuf_build(&elb); - } - else { - GPU_indexbuf_build_in_place(&elb, buffers->index_buf); - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - } - else { - GSetIterator gs_iter; - - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3); - - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); - - BLI_assert(f->len == 3); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - float fmask = 0.0f; - int i; - - BM_face_as_array_vert_tri(f, v); - - /* Average mask value */ - for (i = 0; i < 3; i++) { - fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); - } - fmask /= 3.0f; - - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); - - for (i = 0; i < 3; i++) { - gpu_bmesh_vert_to_buffer_copy(vbo_id, - v[i], - buffers->vert_buf, - v_index++, - f->no, - &fmask, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - } - } - } - - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->tot_tri = tottri; - } - - /* Get material index from the last face we iterated on. */ - buffers->material_index = (f) ? f->mat_nr : 0; - - buffers->show_overlay = !empty_mask; - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Generic - * \{ */ - -GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->use_bmesh = true; - buffers->smooth = smooth_shading; - buffers->show_overlay = true; - - return buffers; -} - -/** - * Builds a list of attributes from a set of domains and a set of - * customdata types. - * - * \param active_only: Returns only one item, a #GPUAttrRef to active_layer. - * \param active_layer: #CustomDataLayer to use for the active layer. - * \param active_layer: #CustomDataLayer to use for the render layer. - */ -static int gpu_pbvh_make_attr_offs(eAttrDomainMask domain_mask, - eCustomDataMask type_mask, - const CustomData *vdata, - const CustomData *edata, - const CustomData *ldata, - const CustomData *pdata, - GPUAttrRef r_cd_attrs[MAX_GPU_ATTR], - bool active_only, - int active_type, - int active_domain, - const CustomDataLayer *active_layer, - const CustomDataLayer *render_layer) -{ - const CustomData *cdata_active = active_domain == ATTR_DOMAIN_POINT ? vdata : ldata; - - if (!cdata_active) { - return 0; - } - - if (active_only) { - int idx = active_layer ? active_layer - cdata_active->layers : -1; - - if (idx >= 0 && idx < cdata_active->totlayer) { - r_cd_attrs[0].cd_offset = cdata_active->layers[idx].offset; - r_cd_attrs[0].domain = active_domain; - r_cd_attrs[0].type = active_type; - r_cd_attrs[0].layer_idx = idx; - - return 1; - } - - return 0; - } - - const CustomData *datas[4] = {vdata, edata, pdata, ldata}; - - int count = 0; - for (eAttrDomain domain = 0; domain < 4; domain++) { - const CustomData *cdata = datas[domain]; - - if (!cdata || !((1 << domain) & domain_mask)) { - continue; - } - - const CustomDataLayer *cl = cdata->layers; - - for (int i = 0; count < MAX_GPU_ATTR && i < cdata->totlayer; i++, cl++) { - if ((CD_TYPE_AS_MASK(cl->type) & type_mask) && !(cl->flag & CD_FLAG_TEMPORARY)) { - GPUAttrRef *ref = r_cd_attrs + count; - - ref->cd_offset = cl->offset; - ref->type = cl->type; - ref->layer_idx = i; - ref->domain = domain; - - count++; - } - } - } - - /* Ensure render layer is last, draw cache code seems to need this. */ - - for (int i = 0; i < count; i++) { - GPUAttrRef *ref = r_cd_attrs + i; - const CustomData *cdata = datas[ref->domain]; - - if (cdata->layers + ref->layer_idx == render_layer) { - SWAP(GPUAttrRef, r_cd_attrs[i], r_cd_attrs[count - 1]); - break; - } - } - - return count; -} - -static bool gpu_pbvh_format_equals(PBVHGPUFormat *a, PBVHGPUFormat *b) -{ - bool bad = false; - - bad |= a->active_attrs_only != b->active_attrs_only; - - bad |= a->pos != b->pos; - bad |= a->fset != b->fset; - bad |= a->msk != b->msk; - bad |= a->nor != b->nor; - - for (int i = 0; i < MIN2(a->totuv, b->totuv); i++) { - bad |= a->uv[i] != b->uv[i]; - } - - for (int i = 0; i < MIN2(a->totcol, b->totcol); i++) { - bad |= a->col[i] != b->col[i]; - } - - bad |= a->totuv != b->totuv; - bad |= a->totcol != b->totcol; - - return !bad; -} - -bool GPU_pbvh_attribute_names_update(PBVHType pbvh_type, - PBVHGPUFormat *vbo_id, - const CustomData *vdata, - const CustomData *ldata, - bool active_attrs_only) -{ - const bool active_only = active_attrs_only; - PBVHGPUFormat old_format = *vbo_id; - - GPU_vertformat_clear(&vbo_id->format); - - vbo_id->active_attrs_only = active_attrs_only; - - if (vbo_id->format.attr_len == 0) { - vbo_id->pos = GPU_vertformat_attr_add( - &vbo_id->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - vbo_id->nor = GPU_vertformat_attr_add( - &vbo_id->format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - - /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */ - vbo_id->msk = GPU_vertformat_attr_add( - &vbo_id->format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - - vbo_id->totcol = 0; - if (pbvh_type == PBVH_FACES) { - int ci = 0; - - Mesh me_query; - - BKE_id_attribute_copy_domains_temp(ID_ME, vdata, NULL, ldata, NULL, NULL, &me_query.id); - - const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me_query.id); - const CustomDataLayer *render_color_layer = BKE_id_attributes_render_color_get(&me_query.id); - eAttrDomain active_color_domain = active_color_layer ? - BKE_id_attribute_domain(&me_query.id, - active_color_layer) : - ATTR_DOMAIN_POINT; - - GPUAttrRef vcol_layers[MAX_GPU_ATTR]; - int totlayer = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_COLOR, - CD_MASK_COLOR_ALL, - vdata, - NULL, - ldata, - NULL, - vcol_layers, - active_only, - active_color_layer ? active_color_layer->type : -1, - active_color_domain, - active_color_layer, - render_color_layer); - - for (int i = 0; i < totlayer; i++) { - GPUAttrRef *ref = vcol_layers + i; - const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata; - - const CustomDataLayer *layer = cdata->layers + ref->layer_idx; - - if (vbo_id->totcol < MAX_GPU_ATTR) { - vbo_id->col[ci++] = GPU_vertformat_attr_add( - &vbo_id->format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - vbo_id->totcol++; - - bool is_render = render_color_layer == layer; - bool is_active = active_color_layer == layer; - - DRW_cdlayer_attr_aliases_add(&vbo_id->format, "c", cdata, layer, is_render, is_active); - } - } - } - - /* ensure at least one vertex color layer */ - if (vbo_id->totcol == 0) { - vbo_id->col[0] = GPU_vertformat_attr_add( - &vbo_id->format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - vbo_id->totcol = 1; - - GPU_vertformat_alias_add(&vbo_id->format, "ac"); - } - - vbo_id->fset = GPU_vertformat_attr_add( - &vbo_id->format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - - vbo_id->totuv = 0; - if (pbvh_type == PBVH_FACES && ldata && CustomData_has_layer(ldata, CD_MLOOPUV)) { - GPUAttrRef uv_layers[MAX_GPU_ATTR]; - const CustomDataLayer *active = NULL, *render = NULL; - - active = get_active_layer(ldata, CD_MLOOPUV); - render = get_render_layer(ldata, CD_MLOOPUV); - - int totlayer = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_CORNER, - CD_MASK_MLOOPUV, - NULL, - NULL, - ldata, - NULL, - uv_layers, - active_only, - CD_MLOOPUV, - ATTR_DOMAIN_CORNER, - active, - render); - - vbo_id->totuv = totlayer; - - for (int i = 0; i < totlayer; i++) { - GPUAttrRef *ref = uv_layers + i; - - vbo_id->uv[i] = GPU_vertformat_attr_add( - &vbo_id->format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - const CustomDataLayer *cl = ldata->layers + ref->layer_idx; - bool is_active = ref->layer_idx == CustomData_get_active_layer_index(ldata, CD_MLOOPUV); - - DRW_cdlayer_attr_aliases_add(&vbo_id->format, "u", ldata, cl, cl == render, is_active); - - /* Apparently the render attribute is 'a' while active is 'au', - * at least going by the draw cache extractor code. - */ - if (cl == render) { - GPU_vertformat_alias_add(&vbo_id->format, "a"); - } - } - } - } - - if (!gpu_pbvh_format_equals(&old_format, vbo_id)) { - return true; - } - - return false; -} - -GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires) -{ - if (wires) { - return (fast && buffers->lines_fast) ? buffers->lines_fast : buffers->lines; - } - - return (fast && buffers->triangles_fast) ? buffers->triangles_fast : buffers->triangles; -} - -bool GPU_pbvh_buffers_has_overlays(GPU_PBVH_Buffers *buffers) -{ - return buffers->show_overlay; -} - -short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers) -{ - return buffers->material_index; -} - -static void gpu_pbvh_buffers_clear(GPU_PBVH_Buffers *buffers) -{ - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); -} - -void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers) -{ - /* Free empty bmesh node buffers. */ - if (buffers->clear_bmesh_on_flush) { - gpu_pbvh_buffers_clear(buffers); - buffers->clear_bmesh_on_flush = false; - } - - /* Force flushing to the GPU. */ - if (buffers->vert_buf && GPU_vertbuf_get_data(buffers->vert_buf)) { - GPU_vertbuf_use(buffers->vert_buf); - } -} - -void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) -{ - if (buffers) { - gpu_pbvh_buffers_clear(buffers); - MEM_freeN(buffers); - } -} - -/** \} */ diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 75e148e0a8f..4adeac1b49a 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -183,6 +183,8 @@ static std::ostream &operator<<(std::ostream &stream, const GPUInput *input) return stream << "var_attrs.v" << input->attr->id; case GPU_SOURCE_UNIFORM_ATTR: return stream << "unf_attrs[resource_id].attr" << input->uniform_attr->id; + case GPU_SOURCE_LAYER_ATTR: + return stream << "attr_load_layer(" << input->layer_attr->hash_code << ")"; case GPU_SOURCE_STRUCT: return stream << "strct" << input->id; case GPU_SOURCE_TEX: @@ -386,6 +388,10 @@ void GPUCodegen::generate_resources() const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); info.sampler(slot++, ImageType::FLOAT_1D_ARRAY, name, Frequency::BATCH); } + else if (tex->sky) { + const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); + info.sampler(0, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH); + } else if (tex->tiled_mapping_name[0] != '\0') { const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); info.sampler(slot++, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH); @@ -428,6 +434,10 @@ void GPUCodegen::generate_resources() info.uniform_buf(2, "UniformAttrs", GPU_ATTRIBUTE_UBO_BLOCK_NAME "[512]", Frequency::BATCH); } + if (!BLI_listbase_is_empty(&graph.layer_attrs)) { + info.additional_info("draw_layer_attributes"); + } + info.typedef_source_generated = ss.str(); } @@ -807,7 +817,7 @@ void GPU_pass_cache_garbage_collect(void) { static int lasttime = 0; const int shadercollectrate = 60; /* hardcoded for now. */ - int ctime = (int)PIL_check_seconds_timer(); + int ctime = int(PIL_check_seconds_timer()); if (ctime < shadercollectrate + lasttime) { return; diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index bcc418169b7..7e94538892a 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -33,6 +33,9 @@ # include "gl_backend.hh" # include "gl_context.hh" #endif +#ifdef WITH_VULKAN_BACKEND +# include "vk_backend.hh" +#endif #ifdef WITH_METAL_BACKEND # include "mtl_backend.hh" #endif @@ -94,7 +97,7 @@ Context *Context::get() /* -------------------------------------------------------------------- */ -GPUContext *GPU_context_create(void *ghost_window) +GPUContext *GPU_context_create(void *ghost_window, void *ghost_context) { { std::scoped_lock lock(backend_users_mutex); @@ -105,7 +108,7 @@ GPUContext *GPU_context_create(void *ghost_window) num_backend_users++; } - Context *ctx = GPUBackend::get()->context_alloc(ghost_window); + Context *ctx = GPUBackend::get()->context_alloc(ghost_window, ghost_context); GPU_context_active_set(wrap(ctx)); return wrap(ctx); @@ -195,7 +198,11 @@ void GPU_render_begin() { GPUBackend *backend = GPUBackend::get(); BLI_assert(backend); - backend->render_begin(); + /* WORKAROUND: Currently a band-aid for the heist production. Has no side effect for GL backend + * but should be fixed for Metal. */ + if (backend) { + backend->render_begin(); + } } void GPU_render_end() { @@ -216,9 +223,22 @@ void GPU_render_step() /** \name Backend selection * \{ */ -static const eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; +/* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`. + * Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL: + * `m_useMetalForRendering = true`. */ +static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; static GPUBackend *g_backend = nullptr; +void GPU_backend_type_selection_set(const eGPUBackendType backend) +{ + g_backend_type = backend; +} + +eGPUBackendType GPU_backend_type_selection_get() +{ + return g_backend_type; +} + bool GPU_backend_supported(void) { switch (g_backend_type) { @@ -228,6 +248,12 @@ bool GPU_backend_supported(void) #else return false; #endif + case GPU_BACKEND_VULKAN: +#ifdef WITH_VULKAN_BACKEND + return true; +#else + return false; +#endif case GPU_BACKEND_METAL: #ifdef WITH_METAL_BACKEND return MTLBackend::metal_is_supported(); @@ -251,6 +277,11 @@ static void gpu_backend_create() g_backend = new GLBackend; break; #endif +#ifdef WITH_VULKAN_BACKEND + case GPU_BACKEND_VULKAN: + g_backend = new VKBackend; + break; +#endif #ifdef WITH_METAL_BACKEND case GPU_BACKEND_METAL: g_backend = new MTLBackend; diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 8d93e49d588..5b50fd66196 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -148,9 +148,9 @@ void FrameBuffer::load_store_config_array(const GPULoadStore *load_store_actions } } -unsigned int FrameBuffer::get_bits_per_pixel() +uint FrameBuffer::get_bits_per_pixel() { - unsigned int total_bits = 0; + uint total_bits = 0; for (GPUAttachment &attachment : attachments_) { Texture *tex = reinterpret_cast<Texture *>(attachment.tex); if (tex != nullptr) { @@ -179,7 +179,7 @@ void FrameBuffer::recursive_downsample(int max_lvl, /* Some Intel HDXXX have issue with rendering to a mipmap that is below * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */ - int mip_max = (GPU_mip_render_workaround()) ? mip_lvl : (mip_lvl - 1); + int mip_max = GPU_mip_render_workaround() ? mip_lvl : (mip_lvl - 1); /* Restrict fetches only to previous level. */ tex->mip_range_set(mip_lvl - 1, mip_max); /* Bind next level. */ @@ -238,6 +238,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb) delete unwrap(gpu_fb); } +const char *GPU_framebuffer_get_name(GPUFrameBuffer *gpu_fb) +{ + return unwrap(gpu_fb)->name_get(); +} + /* ---------- Binding ----------- */ void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb) @@ -368,6 +373,11 @@ void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb, } } +void GPU_framebuffer_default_size(GPUFrameBuffer *gpu_fb, int width, int height) +{ + unwrap(gpu_fb)->size_set(width, height); +} + /* ---------- Viewport & Scissor Region ----------- */ void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int width, int height) @@ -668,7 +678,7 @@ void GPU_offscreen_bind(GPUOffScreen *ofs, bool save) unwrap(gpu_offscreen_fb_get(ofs))->bind(false); } -void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore) +void GPU_offscreen_unbind(GPUOffScreen * /*ofs*/, bool restore) { GPUFrameBuffer *fb = nullptr; if (restore) { diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 8cecc6b8b15..cb7fd62445c 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -40,12 +40,12 @@ typedef enum GPUAttachmentType : int { inline constexpr GPUAttachmentType operator-(GPUAttachmentType a, int b) { - return static_cast<GPUAttachmentType>(static_cast<int>(a) - b); + return static_cast<GPUAttachmentType>(int(a) - b); } inline constexpr GPUAttachmentType operator+(GPUAttachmentType a, int b) { - return static_cast<GPUAttachmentType>(static_cast<int>(a) + b); + return static_cast<GPUAttachmentType>(int(a) + b); } inline GPUAttachmentType &operator++(GPUAttachmentType &a) @@ -74,9 +74,9 @@ class FrameBuffer { /** Set of texture attachments to render to. DEPTH and DEPTH_STENCIL are mutually exclusive. */ GPUAttachment attachments_[GPU_FB_MAX_ATTACHMENT]; /** Is true if internal representation need to be updated. */ - bool dirty_attachments_; + bool dirty_attachments_ = true; /** Size of attachment textures. */ - int width_, height_; + int width_ = 0, height_ = 0; /** Debug name. */ char name_[DEBUG_NAME_LEN]; /** Frame-buffer state. */ @@ -95,11 +95,6 @@ class FrameBuffer { #endif public: - /* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer. - * Points to #BPyGPUFrameBuffer::fb */ - void **ref = nullptr; - - public: FrameBuffer(const char *name); virtual ~FrameBuffer(); @@ -209,6 +204,11 @@ class FrameBuffer { { return attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; }; + + inline const char *const name_get() const + { + return name_; + }; }; /* Syntactic sugar. */ diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index 3b4accf9cc5..81c0a65bb7c 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -45,7 +45,7 @@ void immBindShader(GPUShader *shader) BLI_assert(imm->shader == nullptr); imm->shader = shader; - imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */ + imm->builtin_shader_bound = std::nullopt; if (!imm->vertex_format.packed) { VertexFormat_pack(&imm->vertex_format); @@ -125,9 +125,12 @@ static void wide_line_workaround_start(GPUPrimType prim_type) /* No need to change the shader. */ return; } + if (!imm->builtin_shader_bound) { + return; + } eGPUBuiltinShader polyline_sh; - switch (imm->builtin_shader_bound) { + switch (*imm->builtin_shader_bound) { case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR: polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR; break; @@ -180,8 +183,8 @@ static void wide_line_workaround_end() } immUnbindProgram(); - immBindBuiltinProgram(imm->prev_builtin_shader); - imm->prev_builtin_shader = GPU_SHADER_TEXT; + immBindBuiltinProgram(*imm->prev_builtin_shader); + imm->prev_builtin_shader = std::nullopt; } } diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh index 74ebbdc7ae3..c4e11e7082b 100644 --- a/source/blender/gpu/intern/gpu_immediate_private.hh +++ b/source/blender/gpu/intern/gpu_immediate_private.hh @@ -9,6 +9,8 @@ #pragma once +#include <optional> + #include "GPU_batch.h" #include "GPU_primitive.h" #include "GPU_shader.h" @@ -42,9 +44,9 @@ class Immediate { /** Wide Line workaround. */ /** Previously bound shader to restore after drawing. */ - eGPUBuiltinShader prev_builtin_shader = GPU_SHADER_TEXT; - /** Builtin shader index. Used to test if the workaround can be done. */ - eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT; + std::optional<eGPUBuiltinShader> prev_builtin_shader; + /** Builtin shader index. Used to test if the line width workaround can be done. */ + std::optional<eGPUBuiltinShader> builtin_shader_bound; /** Uniform color: Kept here to update the wide-line shader just before #immBegin. */ float uniform_color[4]; diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index 743bc058b45..39b5a6a93c0 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -195,7 +195,7 @@ static void imm_draw_circle_partial(GPUPrimType prim_type, float sweep) { /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; + const float angle_start = -DEG2RADF(start) + (float)M_PI_2; const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments); @@ -219,7 +219,7 @@ static void imm_draw_circle_partial_3d(GPUPrimType prim_type, float sweep) { /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_start = -DEG2RADF(start) + (float)(M_PI / 2); const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments); @@ -259,7 +259,7 @@ static void imm_draw_disk_partial(GPUPrimType prim_type, CLAMP(sweep, -max_angle, max_angle); /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; + const float angle_start = -DEG2RADF(start) + (float)M_PI_2; const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments * 2); @@ -289,7 +289,7 @@ static void imm_draw_disk_partial_3d(GPUPrimType prim_type, CLAMP(sweep, -max_angle, max_angle); /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; + const float angle_start = -DEG2RADF(start) + (float)M_PI_2; const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments * 2); diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc index 3a66f547403..99e47f5452a 100644 --- a/source/blender/gpu/intern/gpu_index_buffer.cc +++ b/source/blender/gpu/intern/gpu_index_buffer.cc @@ -76,7 +76,7 @@ void GPU_indexbuf_init(GPUIndexBufBuilder *builder, #if TRUST_NO_ONE assert(verts_per_prim != -1); #endif - GPU_indexbuf_init_ex(builder, prim_type, prim_len * (uint)verts_per_prim, vertex_len); + GPU_indexbuf_init_ex(builder, prim_type, prim_len * uint(verts_per_prim), vertex_len); } GPUIndexBuf *GPU_indexbuf_build_on_device(uint index_len) @@ -388,13 +388,13 @@ void IndexBuf::squeeze_indices_short(uint min_idx, 0xFFFFu : (max_idx - min_idx); for (uint i = 0; i < index_len_; i++) { - ushort_idx[i] = (uint16_t)MIN2(clamp_max_idx, uint_idx[i] - min_idx); + ushort_idx[i] = uint16_t(MIN2(clamp_max_idx, uint_idx[i] - min_idx)); } } else { index_base_ = 0; for (uint i = 0; i < index_len_; i++) { - ushort_idx[i] = (uint16_t)(uint_idx[i]); + ushort_idx[i] = uint16_t(uint_idx[i]); } } } diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 34b355eefaf..2dbb4b215bb 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -36,18 +36,10 @@ void GPU_init(void) gpu_codegen_init(); gpu_batch_init(); - -#ifndef GPU_STANDALONE - gpu_pbvh_init(); -#endif } void GPU_exit(void) { -#ifndef GPU_STANDALONE - gpu_pbvh_exit(); -#endif - gpu_batch_exit(); gpu_codegen_exit(); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 75066b21e7b..ca2a9f5cf28 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -41,15 +41,21 @@ /* Structs */ #define MAX_COLOR_BAND 128 +#define MAX_GPU_SKIES 8 typedef struct GPUColorBandBuilder { float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4]; int current_layer; } GPUColorBandBuilder; +typedef struct GPUSkyBuilder { + float pixels[MAX_GPU_SKIES][GPU_SKY_WIDTH * GPU_SKY_HEIGHT][4]; + int current_layer; +} GPUSkyBuilder; + struct GPUMaterial { - /* Contains GPUShader and source code for deferred compilation. - * Can be shared between similar material (i.e: sharing same nodetree topology). */ + /* Contains #GPUShader and source code for deferred compilation. + * Can be shared between similar material (i.e: sharing same node-tree topology). */ GPUPass *pass; /** UBOs for this material parameters. */ GPUUniformBuf *ubo; @@ -73,6 +79,10 @@ struct GPUMaterial { GPUTexture *coba_tex; /** Builder for coba_tex. */ GPUColorBandBuilder *coba_builder; + /** 2D Texture array containing all sky textures. */ + GPUTexture *sky_tex; + /** Builder for sky_tex. */ + GPUSkyBuilder *sky_builder; /* Low level node graph(s). Also contains resources needed by the material. */ GPUNodeGraph graph; @@ -98,6 +108,35 @@ struct GPUMaterial { /* Functions */ +GPUTexture **gpu_material_sky_texture_layer_set( + GPUMaterial *mat, int width, int height, const float *pixels, float *row) +{ + /* In order to put all sky textures into one 2D array texture, + * we need them to be the same size. */ + BLI_assert(width == GPU_SKY_WIDTH); + BLI_assert(height == GPU_SKY_HEIGHT); + UNUSED_VARS_NDEBUG(width, height); + + if (mat->sky_builder == NULL) { + mat->sky_builder = MEM_mallocN(sizeof(GPUSkyBuilder), "GPUSkyBuilder"); + mat->sky_builder->current_layer = 0; + } + + int layer = mat->sky_builder->current_layer; + *row = (float)layer; + + if (*row == MAX_GPU_SKIES) { + printf("Too many sky textures in shader!\n"); + } + else { + float *dst = (float *)mat->sky_builder->pixels[layer]; + memcpy(dst, pixels, sizeof(float) * GPU_SKY_WIDTH * GPU_SKY_HEIGHT * 4); + mat->sky_builder->current_layer += 1; + } + + return &mat->sky_tex; +} + GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, @@ -143,6 +182,24 @@ static void gpu_material_ramp_texture_build(GPUMaterial *mat) mat->coba_builder = NULL; } +static void gpu_material_sky_texture_build(GPUMaterial *mat) +{ + if (mat->sky_builder == NULL) { + return; + } + + mat->sky_tex = GPU_texture_create_2d_array("mat_sky", + GPU_SKY_WIDTH, + GPU_SKY_HEIGHT, + mat->sky_builder->current_layer, + 1, + GPU_RGBA32F, + (float *)mat->sky_builder->pixels); + + MEM_freeN(mat->sky_builder); + mat->sky_builder = NULL; +} + void GPU_material_free_single(GPUMaterial *material) { bool do_free = atomic_sub_and_fetch_uint32(&material->refcount, 1) == 0; @@ -161,6 +218,9 @@ void GPU_material_free_single(GPUMaterial *material) if (material->coba_tex != NULL) { GPU_texture_free(material->coba_tex); } + if (material->sky_tex != NULL) { + GPU_texture_free(material->sky_tex); + } if (material->sss_profile != NULL) { GPU_uniformbuf_free(material->sss_profile); } @@ -231,6 +291,12 @@ const GPUUniformAttrList *GPU_material_uniform_attributes(const GPUMaterial *mat return attrs->count > 0 ? attrs : NULL; } +const ListBase *GPU_material_layer_attributes(const GPUMaterial *material) +{ + const ListBase *attrs = &material->graph.layer_attrs; + return !BLI_listbase_is_empty(attrs) ? attrs : NULL; +} + #if 1 /* End of life code. */ /* Eevee Subsurface scattering. */ /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */ @@ -684,6 +750,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, ntreeGPUMaterialNodes(localtree, mat); gpu_material_ramp_texture_build(mat); + gpu_material_sky_texture_build(mat); { /* Create source code and search pass cache for an already compiled version. */ diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index 94fd44f832b..b46860cf0f4 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -429,7 +429,7 @@ void GPU_matrix_frustum_set( void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far) { - float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near; + float half_height = tanf(fovy * float(M_PI / 360.0)) * near; float half_width = half_height * aspect; GPU_matrix_frustum_set(-half_width, +half_width, -half_height, +half_height, near, far); } @@ -669,13 +669,13 @@ BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mis int GPU_matrix_stack_level_get_model_view() { GPUMatrixState *state = Context::get()->matrix_state; - return (int)state->model_view_stack.top; + return int(state->model_view_stack.top); } int GPU_matrix_stack_level_get_projection() { GPUMatrixState *state = Context::get()->matrix_state; - return (int)state->projection_stack.top; + return int(state->projection_stack.top); } /** \} */ @@ -700,7 +700,7 @@ float GPU_polygon_offset_calc(const float (*winmat)[4], float viewdist, float di if (depth_fac == 0.0f) { /* Hard-code for 24 bit precision. */ int depthbits = 24; - depth_fac = 1.0f / (float)((1 << depthbits) - 1); + depth_fac = 1.0f / float((1 << depthbits) - 1); } ofs = (-1.0 / winmat[2][2]) * dist * depth_fac; diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index f82af7538b5..c72e7097b33 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -83,6 +83,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType case GPU_SOURCE_UNIFORM_ATTR: input->uniform_attr->users++; break; + case GPU_SOURCE_LAYER_ATTR: + input->layer_attr->users++; + break; case GPU_SOURCE_TEX: case GPU_SOURCE_TEX_TILED_MAPPING: input->texture->users++; @@ -112,6 +115,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType break; case GPU_NODE_LINK_IMAGE: case GPU_NODE_LINK_IMAGE_TILED: + case GPU_NODE_LINK_IMAGE_SKY: case GPU_NODE_LINK_COLORBAND: input->source = GPU_SOURCE_TEX; input->texture = link->texture; @@ -132,6 +136,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType input->source = GPU_SOURCE_UNIFORM_ATTR; input->uniform_attr = link->uniform_attr; break; + case GPU_NODE_LINK_LAYER_ATTR: + input->source = GPU_SOURCE_LAYER_ATTR; + input->layer_attr = link->layer_attr; + break; case GPU_NODE_LINK_CONSTANT: input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT; break; @@ -262,7 +270,7 @@ static int uniform_attr_sort_cmp(const void *a, const void *b) return (attr_a->use_dupli && !attr_b->use_dupli); } -static unsigned int uniform_attr_list_hash(const void *key) +static uint uniform_attr_list_hash(const void *key) { const GPUUniformAttrList *attrs = key; return attrs->hash_code; @@ -415,11 +423,6 @@ static GPUUniformAttr *gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph, if (attr == NULL && attrs->count < GPU_MAX_UNIFORM_ATTR) { attr = MEM_callocN(sizeof(*attr), __func__); STRNCPY(attr->name, name); - { - char attr_name_esc[sizeof(attr->name) * 2]; - BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc)); - SNPRINTF(attr->name_id_prop, "[\"%s\"]", attr_name_esc); - } attr->use_dupli = use_dupli; attr->hash_code = BLI_ghashutil_strhash_p(attr->name) << 1 | (attr->use_dupli ? 0 : 1); attr->id = -1; @@ -434,10 +437,39 @@ static GPUUniformAttr *gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph, return attr; } +/** Add a new uniform attribute of given type and name. Returns NULL if out of slots. */ +static GPULayerAttr *gpu_node_graph_add_layer_attribute(GPUNodeGraph *graph, const char *name) +{ + /* Find existing attribute. */ + ListBase *attrs = &graph->layer_attrs; + GPULayerAttr *attr = attrs->first; + + for (; attr; attr = attr->next) { + if (STREQ(attr->name, name)) { + break; + } + } + + /* Add new requested attribute to the list. */ + if (attr == NULL) { + attr = MEM_callocN(sizeof(*attr), __func__); + STRNCPY(attr->name, name); + attr->hash_code = BLI_ghashutil_strhash_p(attr->name); + BLI_addtail(attrs, attr); + } + + if (attr != NULL) { + attr->users++; + } + + return attr; +} + static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, Image *ima, ImageUser *iuser, struct GPUTexture **colorband, + struct GPUTexture **sky, GPUNodeLinkType link_type, eGPUSamplerState sampler_state) { @@ -445,7 +477,8 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, int num_textures = 0; GPUMaterialTexture *tex = graph->textures.first; for (; tex; tex = tex->next) { - if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) { + if (tex->ima == ima && tex->colorband == colorband && tex->sky == sky && + tex->sampler_state == sampler_state) { break; } num_textures++; @@ -460,6 +493,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, tex->iuser_available = true; } tex->colorband = colorband; + tex->sky = sky; tex->sampler_state = sampler_state; BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures); if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) { @@ -547,6 +581,17 @@ GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat, return link; } +GPUNodeLink *GPU_layer_attribute(GPUMaterial *mat, const char *name) +{ + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPULayerAttr *attr = gpu_node_graph_add_layer_attribute(graph, name); + + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_LAYER_ATTR; + link->layer_attr = attr; + return link; +} + GPUNodeLink *GPU_constant(const float *num) { GPUNodeLink *link = gpu_node_link_create(); @@ -580,7 +625,24 @@ GPUNodeLink *GPU_image(GPUMaterial *mat, GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, link->link_type, sampler_state); + graph, ima, iuser, NULL, NULL, link->link_type, sampler_state); + return link; +} + +GPUNodeLink *GPU_image_sky(GPUMaterial *mat, + int width, + int height, + const float *pixels, + float *layer, + eGPUSamplerState sampler_state) +{ + struct GPUTexture **sky = gpu_material_sky_texture_layer_set(mat, width, height, pixels, layer); + + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_IMAGE_SKY; + link->texture = gpu_node_graph_add_texture( + graph, NULL, NULL, NULL, sky, link->link_type, sampler_state); return link; } @@ -593,7 +655,7 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, link->link_type, sampler_state); + graph, ima, iuser, NULL, NULL, link->link_type, sampler_state); return link; } @@ -603,7 +665,7 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX); + graph, ima, iuser, NULL, NULL, link->link_type, GPU_SAMPLER_MAX); return link; } @@ -616,7 +678,7 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_COLORBAND; link->texture = gpu_node_graph_add_texture( - graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX); + graph, NULL, NULL, colorband, NULL, link->link_type, GPU_SAMPLER_MAX); return link; } @@ -751,14 +813,22 @@ static void gpu_inputs_free(ListBase *inputs) GPUInput *input; for (input = inputs->first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR) { - input->attr->users--; - } - else if (input->source == GPU_SOURCE_UNIFORM_ATTR) { - input->uniform_attr->users--; - } - else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) { - input->texture->users--; + switch (input->source) { + case GPU_SOURCE_ATTR: + input->attr->users--; + break; + case GPU_SOURCE_UNIFORM_ATTR: + input->uniform_attr->users--; + break; + case GPU_SOURCE_LAYER_ATTR: + input->layer_attr->users--; + break; + case GPU_SOURCE_TEX: + case GPU_SOURCE_TEX_TILED_MAPPING: + input->texture->users--; + break; + default: + break; } if (input->link) { @@ -810,6 +880,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph) BLI_freelistN(&graph->textures); BLI_freelistN(&graph->attributes); GPU_uniform_attr_list_free(&graph->uniform_attrs); + BLI_freelistN(&graph->layer_attrs); if (graph->used_libraries) { BLI_gset_free(graph->used_libraries, NULL); @@ -892,4 +963,10 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph) uattrs->count--; } } + + LISTBASE_FOREACH_MUTABLE (GPULayerAttr *, attr, &graph->layer_attrs) { + if (attr->users == 0) { + BLI_freelinkN(&graph->layer_attrs, attr); + } + } } diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index 74afb721a1c..de0a0687b13 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -31,6 +31,7 @@ typedef enum eGPUDataSource { GPU_SOURCE_UNIFORM, GPU_SOURCE_ATTR, GPU_SOURCE_UNIFORM_ATTR, + GPU_SOURCE_LAYER_ATTR, GPU_SOURCE_STRUCT, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING, @@ -42,11 +43,13 @@ typedef enum { GPU_NODE_LINK_NONE = 0, GPU_NODE_LINK_ATTR, GPU_NODE_LINK_UNIFORM_ATTR, + GPU_NODE_LINK_LAYER_ATTR, GPU_NODE_LINK_COLORBAND, GPU_NODE_LINK_CONSTANT, GPU_NODE_LINK_IMAGE, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING, + GPU_NODE_LINK_IMAGE_SKY, GPU_NODE_LINK_OUTPUT, GPU_NODE_LINK_UNIFORM, GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN, @@ -94,6 +97,8 @@ struct GPUNodeLink { struct GPUMaterialAttribute *attr; /* GPU_NODE_LINK_UNIFORM_ATTR */ struct GPUUniformAttr *uniform_attr; + /* GPU_NODE_LINK_LAYER_ATTR */ + struct GPULayerAttr *layer_attr; /* GPU_NODE_LINK_IMAGE_BLENDER */ struct GPUMaterialTexture *texture; /* GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN */ @@ -130,6 +135,8 @@ typedef struct GPUInput { struct GPUMaterialAttribute *attr; /* GPU_SOURCE_UNIFORM_ATTR */ struct GPUUniformAttr *uniform_attr; + /* GPU_SOURCE_LAYER_ATTR */ + struct GPULayerAttr *layer_attr; /* GPU_SOURCE_FUNCTION_CALL */ char function_call[64]; }; @@ -170,6 +177,9 @@ typedef struct GPUNodeGraph { /* The list of uniform attributes. */ GPUUniformAttrList uniform_attrs; + /* The list of layer attributes. */ + ListBase layer_attrs; + /** Set of all the GLSL lib code blocks . */ GSet *used_libraries; } GPUNodeGraph; @@ -178,6 +188,7 @@ typedef struct GPUNodeGraph { void gpu_node_graph_prune_unused(GPUNodeGraph *graph); void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph); + /** * Free intermediate node graph. */ @@ -197,6 +208,11 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat, int size, float *pixels, float *row); +/** + * Returns the address of the future pointer to sky_tex + */ +struct GPUTexture **gpu_material_sky_texture_layer_set( + struct GPUMaterial *mat, int width, int height, const float *pixels, float *layer); #ifdef __cplusplus } diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc index 9b699c60126..96e3eacd6f5 100644 --- a/source/blender/gpu/intern/gpu_shader_builder.cc +++ b/source/blender/gpu/intern/gpu_shader_builder.cc @@ -15,6 +15,8 @@ #include "GPU_init_exit.h" #include "gpu_shader_create_info_private.hh" +#include "BLI_vector.hh" + #include "CLG_log.h" namespace blender::gpu::shader_builder { @@ -41,11 +43,27 @@ void ShaderBuilder::init() CLG_init(); GHOST_GLSettings glSettings = {0}; - ghost_system_ = GHOST_CreateSystem(); + switch (GPU_backend_type_selection_get()) { + case GPU_BACKEND_OPENGL: + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; + break; + +#ifdef WITH_METAL_BACKEND + case GPU_BACKEND_METAL: + glSettings.context_type = GHOST_kDrawingContextTypeMetal; + break; +#endif + + default: + BLI_assert_unreachable(); + break; + } + + ghost_system_ = GHOST_CreateSystemBackground(); ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings); GHOST_ActivateOpenGLContext(ghost_context_); - gpu_context_ = GPU_context_create(nullptr); + gpu_context_ = GPU_context_create(nullptr, ghost_context_); GPU_init(); } @@ -73,13 +91,32 @@ int main(int argc, const char *argv[]) int exit_code = 0; - blender::gpu::shader_builder::ShaderBuilder builder; - builder.init(); - if (!builder.bake_create_infos()) { - exit_code = 1; + struct NamedBackend { + std::string name; + eGPUBackendType backend; + }; + + blender::Vector<NamedBackend> backends_to_validate; + backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL}); +#ifdef WITH_METAL_BACKEND + backends_to_validate.append({"Metal", GPU_BACKEND_METAL}); +#endif + for (NamedBackend &backend : backends_to_validate) { + GPU_backend_type_selection_set(backend.backend); + if (!GPU_backend_supported()) { + printf("%s isn't supported on this platform. Shader compilation is skipped\n", + backend.name.c_str()); + continue; + } + blender::gpu::shader_builder::ShaderBuilder builder; + builder.init(); + if (!builder.bake_create_infos()) { + printf("Shader compilation failed for %s backend\n", backend.name.c_str()); + exit_code = 1; + } + builder.exit(); } - builder.exit(); - exit(exit_code); + 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 index db14d7fbeb9..65bda7ba858 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -41,60 +41,66 @@ UserDef U; /** \name Stubs of BLI_imbuf_types.h * \{ */ -void IMB_freeImBuf(ImBuf *UNUSED(ibuf)) +void IMB_freeImBuf(ImBuf * /*ibuf*/) { BLI_assert_unreachable(); } +struct ImBuf *IMB_allocImBuf(unsigned int /*x*/, + unsigned int /*y*/, + unsigned char /*planes*/, + unsigned int /*flags*/) +{ + BLI_assert_unreachable(); + return nullptr; +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Stubs of UI_resources.h * \{ */ -void UI_GetThemeColor4fv(int UNUSED(colorid), float UNUSED(col[4])) +void UI_GetThemeColor4fv(int /*colorid*/, float UNUSED(col[4])) { BLI_assert_unreachable(); } -void UI_GetThemeColor3fv(int UNUSED(colorid), float UNUSED(col[3])) +void UI_GetThemeColor3fv(int /*colorid*/, float UNUSED(col[3])) { BLI_assert_unreachable(); } -void UI_GetThemeColorShade4fv(int UNUSED(colorid), int UNUSED(offset), float UNUSED(col[4])) +void UI_GetThemeColorShade4fv(int /*colorid*/, int /*offset*/, float UNUSED(col[4])) { BLI_assert_unreachable(); } -void UI_GetThemeColorShadeAlpha4fv(int UNUSED(colorid), - int UNUSED(coloffset), - int UNUSED(alphaoffset), +void UI_GetThemeColorShadeAlpha4fv(int /*colorid*/, + int /*coloffset*/, + int /*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])) +void UI_GetThemeColorBlendShade4fv( + int /*colorid1*/, int /*colorid2*/, float /*fac*/, int /*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])) +void UI_GetThemeColorBlend3ubv(int /*colorid1*/, + int /*colorid2*/, + float /*fac*/, + uchar UNUSED(col[3])) { BLI_assert_unreachable(); } -void UI_GetThemeColorShadeAlpha4ubv(int UNUSED(colorid), - int UNUSED(coloffset), - int UNUSED(alphaoffset), - unsigned char UNUSED(col[4])) +void UI_GetThemeColorShadeAlpha4ubv(int /*colorid*/, + int /*coloffset*/, + int /*alphaoffset*/, + uchar UNUSED(col[4])) { BLI_assert_unreachable(); } @@ -105,28 +111,28 @@ void UI_GetThemeColorShadeAlpha4ubv(int UNUSED(colorid), /** \name Stubs of BKE_attribute.h * \{ */ -void BKE_id_attribute_copy_domains_temp(short UNUSED(id_type), - const struct CustomData *UNUSED(vdata), - const struct CustomData *UNUSED(edata), - const struct CustomData *UNUSED(ldata), - const struct CustomData *UNUSED(pdata), - const struct CustomData *UNUSED(cdata), - struct ID *UNUSED(r_id)) +void BKE_id_attribute_copy_domains_temp(short /*id_type*/, + const struct CustomData * /*vdata*/, + const struct CustomData * /*edata*/, + const struct CustomData * /*ldata*/, + const struct CustomData * /*pdata*/, + const struct CustomData * /*cdata*/, + struct ID * /*r_id*/) { } -struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID *UNUSED(id)) +struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID * /*id*/) { return nullptr; } -struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID *UNUSED(id)) +struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID * /*id*/) { return nullptr; } -eAttrDomain BKE_id_attribute_domain(const struct ID *UNUSED(id), - const struct CustomDataLayer *UNUSED(layer)) +eAttrDomain BKE_id_attribute_domain(const struct ID * /*id*/, + const struct CustomDataLayer * /*layer*/) { return ATTR_DOMAIN_AUTO; } @@ -136,23 +142,23 @@ eAttrDomain BKE_id_attribute_domain(const struct ID *UNUSED(id), /* -------------------------------------------------------------------- */ /** \name Stubs of BKE_paint.h * \{ */ -bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt), const bool *UNUSED(hide_poly)) +bool paint_is_face_hidden(const struct MLoopTri * /*lt*/, const bool * /*hide_poly*/) { BLI_assert_unreachable(); return false; } -void BKE_paint_face_set_overlay_color_get(const int UNUSED(face_set), - const int UNUSED(seed), +void BKE_paint_face_set_overlay_color_get(const int /*face_set*/, + const int /*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)) +bool paint_is_grid_face_hidden(const uint * /*grid_hidden*/, + int /*gridsize*/, + int /*x*/, + int /*y*/) { BLI_assert_unreachable(); return false; @@ -163,16 +169,16 @@ bool paint_is_grid_face_hidden(const unsigned int *UNUSED(grid_hidden), /* -------------------------------------------------------------------- */ /** \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), +void BKE_mesh_calc_poly_normal(const struct MPoly * /*mpoly*/, + const struct MLoop * /*loopstart*/, + const struct MVert * /*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), +void BKE_mesh_looptri_get_real_edges(const struct Mesh * /*mesh*/, + const struct MLoopTri * /*looptri*/, int UNUSED(r_edges[3])) { BLI_assert_unreachable(); @@ -195,42 +201,42 @@ void BKE_material_defaults_free_gpu() /** \name Stubs of BKE_customdata.h * \{ */ -int CustomData_get_offset(const struct CustomData *UNUSED(data), int UNUSED(type)) +int CustomData_get_offset(const struct CustomData * /*data*/, int /*type*/) { BLI_assert_unreachable(); return 0; } -int CustomData_get_named_layer_index(const struct CustomData *UNUSED(data), - int UNUSED(type), - const char *UNUSED(name)) +int CustomData_get_named_layer_index(const struct CustomData * /*data*/, + int /*type*/, + const char * /*name*/) { return -1; } -int CustomData_get_active_layer_index(const struct CustomData *UNUSED(data), int UNUSED(type)) +int CustomData_get_active_layer_index(const struct CustomData * /*data*/, int /*type*/) { return -1; } -int CustomData_get_render_layer_index(const struct CustomData *UNUSED(data), int UNUSED(type)) +int CustomData_get_render_layer_index(const struct CustomData * /*data*/, int /*type*/) { return -1; } -bool CustomData_has_layer(const struct CustomData *UNUSED(data), int UNUSED(type)) +bool CustomData_has_layer(const struct CustomData * /*data*/, int /*type*/) { return false; } -void *CustomData_get_layer_named(const struct CustomData *UNUSED(data), - int UNUSED(type), - const char *UNUSED(name)) +void *CustomData_get_layer_named(const struct CustomData * /*data*/, + int /*type*/, + const char * /*name*/) { return nullptr; } -void *CustomData_get_layer(const struct CustomData *UNUSED(data), int UNUSED(type)) +void *CustomData_get_layer(const struct CustomData * /*data*/, int /*type*/) { return nullptr; } @@ -241,10 +247,10 @@ void *CustomData_get_layer(const struct CustomData *UNUSED(data), int UNUSED(typ /** \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)) +int BKE_pbvh_count_grid_quads(BLI_bitmap ** /*grid_hidden*/, + const int * /*grid_indices*/, + int /*totgrid*/, + int /*gridsize*/) { BLI_assert_unreachable(); return 0; @@ -255,8 +261,7 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **UNUSED(grid_hidden), /* -------------------------------------------------------------------- */ /** \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)) +int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG * /*subdiv_ccg*/, const int /*grid_index*/) { BLI_assert_unreachable(); return 0; @@ -267,18 +272,18 @@ int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *UNUSED(subdiv_ccg), /* -------------------------------------------------------------------- */ /** \name Stubs of BKE_node.h * \{ */ -void ntreeGPUMaterialNodes(struct bNodeTree *UNUSED(localtree), struct GPUMaterial *UNUSED(mat)) +void ntreeGPUMaterialNodes(struct bNodeTree * /*localtree*/, struct GPUMaterial * /*mat*/) { BLI_assert_unreachable(); } -struct bNodeTree *ntreeLocalize(struct bNodeTree *UNUSED(ntree)) +struct bNodeTree *ntreeLocalize(struct bNodeTree * /*ntree*/) { BLI_assert_unreachable(); return nullptr; } -void ntreeFreeLocalTree(struct bNodeTree *UNUSED(ntree)) +void ntreeFreeLocalTree(struct bNodeTree * /*ntree*/) { BLI_assert_unreachable(); } @@ -288,7 +293,7 @@ void ntreeFreeLocalTree(struct bNodeTree *UNUSED(ntree)) /* -------------------------------------------------------------------- */ /** \name Stubs of bmesh.h * \{ */ -void BM_face_as_array_vert_tri(BMFace *UNUSED(f), BMVert *UNUSED(r_verts[3])) +void BM_face_as_array_vert_tri(BMFace * /*f*/, BMVert *UNUSED(r_verts[3])) { BLI_assert_unreachable(); } @@ -297,17 +302,17 @@ void BM_face_as_array_vert_tri(BMFace *UNUSED(f), BMVert *UNUSED(r_verts[3])) /* -------------------------------------------------------------------- */ /** \name Stubs of DRW_engine.h * \{ */ -void DRW_deferred_shader_remove(struct GPUMaterial *UNUSED(mat)) +void DRW_deferred_shader_remove(struct GPUMaterial * /*mat*/) { BLI_assert_unreachable(); } -void DRW_cdlayer_attr_aliases_add(struct GPUVertFormat *UNUSED(format), - const char *UNUSED(base_name), - const struct CustomData *UNUSED(data), - const struct CustomDataLayer *UNUSED(cl), - bool UNUSED(is_active_render), - bool UNUSED(is_active_layer)) +void DRW_cdlayer_attr_aliases_add(struct GPUVertFormat * /*format*/, + const char * /*base_name*/, + const struct CustomData * /*data*/, + const struct CustomDataLayer * /*cl*/, + bool /*is_active_render*/, + bool /*is_active_layer*/) { } diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c index 8a6586e06f6..470643ba863 100644 --- a/source/blender/gpu/intern/gpu_shader_builtin.c +++ b/source/blender/gpu/intern/gpu_shader_builtin.c @@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .create_info = "gpu_shader_2D_diag_stripes", }, + [GPU_SHADER_ICON] = + { + .name = "GPU_SHADER_ICON", + .create_info = "gpu_shader_icon", + }, [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = { .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE", diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc index a18fdcd32df..ebbddccbe47 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.cc +++ b/source/blender/gpu/intern/gpu_shader_create_info.cc @@ -284,6 +284,7 @@ void gpu_shader_create_info_init() _info /* Declare, register and construct the infos. */ +#include "compositor_shader_create_info_list.hh" #include "gpu_shader_create_info_list.hh" /* Baked shader data appended to create infos. */ @@ -305,6 +306,31 @@ void gpu_shader_create_info_init() draw_resource_id_new = draw_resource_id_fallback; } + /* Metal-specific alternatives for Geometry shaders. */ + if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_METAL)) { + + /* 3D polyline. */ + gpu_shader_3D_polyline_uniform_color = gpu_shader_3D_polyline_uniform_color_no_geom; + gpu_shader_3D_polyline_flat_color = gpu_shader_3D_polyline_flat_color_no_geom; + gpu_shader_3D_polyline_smooth_color = gpu_shader_3D_polyline_smooth_color_no_geom; + gpu_shader_3D_polyline_uniform_color_clipped = + gpu_shader_3D_polyline_uniform_color_clipped_no_geom; + + /* Overlay Edit Mesh. */ + overlay_edit_mesh_edge = overlay_edit_mesh_edge_no_geom; + overlay_edit_mesh_edge_flat = overlay_edit_mesh_edge_flat_no_geom; + overlay_edit_mesh_edge_clipped = overlay_edit_mesh_edge_clipped_no_geom; + overlay_edit_mesh_edge_flat_clipped = overlay_edit_mesh_edge_flat_clipped_no_geom; + + /* Overlay Armature Shape outline. */ + overlay_armature_shape_outline = overlay_armature_shape_outline_no_geom; + overlay_armature_shape_outline_clipped = overlay_armature_shape_outline_clipped_no_geom; + + /* Overlay Motion Path Line. */ + overlay_motion_path_line = overlay_motion_path_line_no_geom; + overlay_motion_path_line_clipped = overlay_motion_path_line_clipped_no_geom; + } + for (ShaderCreateInfo *info : g_create_infos->values()) { if (info->do_static_compilation_) { info->builtins_ |= gpu_shader_dependency_get_builtins(info->vertex_source_); diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc index 2c59cb6e501..7d5b8c891b9 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency.cc +++ b/source/blender/gpu/intern/gpu_shader_dependency.cc @@ -24,6 +24,7 @@ extern "C" { #define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[]; +#include "glsl_compositor_source_list.h" #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" #ifdef WITH_OCIO @@ -109,8 +110,7 @@ struct GPUSource { } if ((source.find("drw_debug_") != StringRef::not_found) && /* Avoid these two files where it makes no sense to add the dependency. */ - (filename != "common_debug_draw_lib.glsl" && - filename != "draw_debug_draw_display_vert.glsl")) { + !ELEM(filename, "common_debug_draw_lib.glsl", "draw_debug_draw_display_vert.glsl")) { builtins |= shader::BuiltinBits::USE_DEBUG_DRAW; } check_no_quotes(); @@ -141,7 +141,7 @@ struct GPUSource { 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', ' ', ':', '(', ','))) { + if (!ELEM(previous_char, '\n', '\t', ' ', ':', '(', ',')) { offset += (reversed) ? -1 : 1; continue; } @@ -846,6 +846,7 @@ void gpu_shader_dependency_init() #define SHADER_SOURCE(datatoc, filename, filepath) \ g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc, g_functions)); +#include "glsl_compositor_source_list.h" #include "glsl_draw_source_list.h" #include "glsl_gpu_source_list.h" #ifdef WITH_OCIO diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc index 6f43b379d31..d9e5e066fea 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.cc +++ b/source/blender/gpu/intern/gpu_shader_interface.cc @@ -22,8 +22,8 @@ ShaderInterface::ShaderInterface() = default; ShaderInterface::~ShaderInterface() { /* Free memory used by name_buffer. */ - MEM_freeN(name_buffer_); - MEM_freeN(inputs_); + MEM_SAFE_FREE(name_buffer_); + MEM_SAFE_FREE(inputs_); } static void sort_input_list(MutableSpan<ShaderInput> dst) diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh index 41e06569bdc..d223daa4a61 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.hh +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -228,6 +228,8 @@ inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBu return "drw_matrices"; case GPU_UNIFORM_BLOCK_DRW_INFOS: return "drw_infos"; + case GPU_UNIFORM_BLOCK_DRW_CLIPPING: + return "drw_clipping"; default: return nullptr; } diff --git a/source/blender/gpu/intern/gpu_shader_log.cc b/source/blender/gpu/intern/gpu_shader_log.cc index dbc36c5afd0..e593c4fa508 100644 --- a/source/blender/gpu/intern/gpu_shader_log.cc +++ b/source/blender/gpu/intern/gpu_shader_log.cc @@ -93,10 +93,10 @@ void Shader::print_log(Span<const char *> sources, } /* Silence not useful lines. */ - StringRef logref = StringRefNull(log_line).substr(0, (size_t)line_end - (size_t)log_line); + StringRef logref = StringRefNull(log_line).substr(0, size_t(line_end) - size_t(log_line)); if (logref.endswith(" shader failed to compile with the following errors:") || logref.endswith(" No code generated")) { - log_line += (size_t)line_end - (size_t)log_line; + log_line += size_t(line_end) - size_t(log_line); continue; } @@ -291,7 +291,7 @@ bool GPULogParser::at_any(const char *log_line, const StringRef chars) const int GPULogParser::parse_number(const char *log_line, char **r_new_position) const { - return (int)strtol(log_line, r_new_position, 10); + return int(strtol(log_line, r_new_position, 10)); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index a1e0b8867a0..8e9d5cb3184 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -97,10 +97,10 @@ void GPU_color_mask(bool r, bool g, bool b, bool a) StateManager *stack = Context::get()->state_manager; auto &state = stack->state; uint32_t write_mask = state.write_mask; - SET_FLAG_FROM_TEST(write_mask, r, (uint32_t)GPU_WRITE_RED); - SET_FLAG_FROM_TEST(write_mask, g, (uint32_t)GPU_WRITE_GREEN); - SET_FLAG_FROM_TEST(write_mask, b, (uint32_t)GPU_WRITE_BLUE); - SET_FLAG_FROM_TEST(write_mask, a, (uint32_t)GPU_WRITE_ALPHA); + SET_FLAG_FROM_TEST(write_mask, r, uint32_t(GPU_WRITE_RED)); + SET_FLAG_FROM_TEST(write_mask, g, uint32_t(GPU_WRITE_GREEN)); + SET_FLAG_FROM_TEST(write_mask, b, uint32_t(GPU_WRITE_BLUE)); + SET_FLAG_FROM_TEST(write_mask, a, uint32_t(GPU_WRITE_ALPHA)); state.write_mask = write_mask; } @@ -109,7 +109,7 @@ void GPU_depth_mask(bool depth) StateManager *stack = Context::get()->state_manager; auto &state = stack->state; uint32_t write_mask = state.write_mask; - SET_FLAG_FROM_TEST(write_mask, depth, (uint32_t)GPU_WRITE_DEPTH); + SET_FLAG_FROM_TEST(write_mask, depth, uint32_t(GPU_WRITE_DEPTH)); state.write_mask = write_mask; } @@ -133,13 +133,13 @@ void GPU_state_set(eGPUWriteMask write_mask, { StateManager *stack = Context::get()->state_manager; auto &state = stack->state; - state.write_mask = (uint32_t)write_mask; - state.blend = (uint32_t)blend; - state.culling_test = (uint32_t)culling_test; - state.depth_test = (uint32_t)depth_test; - state.stencil_test = (uint32_t)stencil_test; - state.stencil_op = (uint32_t)stencil_op; - state.provoking_vert = (uint32_t)provoking_vert; + state.write_mask = uint32_t(write_mask); + state.blend = uint32_t(blend); + state.culling_test = uint32_t(culling_test); + state.depth_test = uint32_t(depth_test); + state.stencil_test = uint32_t(stencil_test); + state.stencil_op = uint32_t(stencil_op); + state.provoking_vert = uint32_t(provoking_vert); } /** \} */ @@ -196,17 +196,17 @@ void GPU_viewport(int x, int y, int width, int height) void GPU_stencil_reference_set(uint reference) { - SET_MUTABLE_STATE(stencil_reference, (uint8_t)reference); + SET_MUTABLE_STATE(stencil_reference, uint8_t(reference)); } void GPU_stencil_write_mask_set(uint write_mask) { - SET_MUTABLE_STATE(stencil_write_mask, (uint8_t)write_mask); + SET_MUTABLE_STATE(stencil_write_mask, uint8_t(write_mask)); } void GPU_stencil_compare_mask_set(uint compare_mask) { - SET_MUTABLE_STATE(stencil_compare_mask, (uint8_t)compare_mask); + SET_MUTABLE_STATE(stencil_compare_mask, uint8_t(compare_mask)); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index bec8b8a0df3..cd1f8bf582c 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -132,6 +132,7 @@ bool Texture::init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format) bool Texture::init_view(const GPUTexture *src_, eGPUTextureFormat format, + eGPUTextureType type, int mip_start, int mip_len, int layer_start, @@ -144,7 +145,7 @@ bool Texture::init_view(const GPUTexture *src_, d_ = src->d_; layer_start = min_ii(layer_start, src->layer_count() - 1); layer_len = min_ii(layer_len, (src->layer_count() - layer_start)); - switch (src->type_) { + switch (type) { case GPU_TEXTURE_1D_ARRAY: h_ = layer_len; break; @@ -163,8 +164,7 @@ bool Texture::init_view(const GPUTexture *src_, mipmaps_ = mip_len; format_ = format; format_flag_ = to_format_flag(format); - /* For now always copy the target. Target aliasing could be exposed later. */ - type_ = src->type_; + type_ = type; if (cube_as_array) { BLI_assert(type_ & GPU_TEXTURE_CUBE); type_ = (type_ & ~GPU_TEXTURE_CUBE) | GPU_TEXTURE_2D_ARRAY; @@ -404,7 +404,26 @@ GPUTexture *GPU_texture_create_view(const char *name, BLI_assert(mip_len > 0); BLI_assert(layer_len > 0); Texture *view = GPUBackend::get()->texture_alloc(name); - view->init_view(src, format, mip_start, mip_len, layer_start, layer_len, cube_as_array); + view->init_view(src, + format, + unwrap(src)->type_get(), + mip_start, + mip_len, + layer_start, + layer_len, + cube_as_array); + return wrap(view); +} + +GPUTexture *GPU_texture_create_single_layer_view(const char *name, const GPUTexture *src) +{ + eGPUTextureFormat format = unwrap(src)->format_get(); + eGPUTextureType type = unwrap(src)->type_get(); + BLI_assert(ELEM(type, GPU_TEXTURE_1D, GPU_TEXTURE_2D, GPU_TEXTURE_CUBE)); + type |= GPU_TEXTURE_ARRAY; + + Texture *view = GPUBackend::get()->texture_alloc(name); + view->init_view(src, format, type, 0, 9999, 0, 1, false); return wrap(view); } @@ -463,7 +482,7 @@ void GPU_unpack_row_length_set(uint len) void GPU_texture_bind_ex(GPUTexture *tex_, eGPUSamplerState state, int unit, - const bool UNUSED(set_number)) + const bool /*set_number*/) { Texture *tex = reinterpret_cast<Texture *>(tex_); state = (state >= GPU_SAMPLER_MAX) ? tex->sampler_state : state; diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 8521b0fd77f..124b1751b96 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -108,6 +108,7 @@ class Texture { bool init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format); bool init_view(const GPUTexture *src, eGPUTextureFormat format, + eGPUTextureType type, int mip_start, int mip_len, int layer_start, @@ -430,15 +431,16 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da case GPU_DEPTH_COMPONENT24: case GPU_DEPTH_COMPONENT16: case GPU_DEPTH_COMPONENT32F: - return data_format == GPU_DATA_FLOAT; + return ELEM(data_format, GPU_DATA_FLOAT, GPU_DATA_UINT); case GPU_DEPTH24_STENCIL8: case GPU_DEPTH32F_STENCIL8: - return data_format == GPU_DATA_UINT_24_8; + return ELEM(data_format, GPU_DATA_UINT_24_8, GPU_DATA_UINT); case GPU_R8UI: case GPU_R16UI: case GPU_RG16UI: case GPU_R32UI: return data_format == GPU_DATA_UINT; + case GPU_R32I: case GPU_RG16I: case GPU_R16I: return data_format == GPU_DATA_INT; @@ -452,6 +454,8 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da return ELEM(data_format, GPU_DATA_2_10_10_10_REV, GPU_DATA_FLOAT); case GPU_R11F_G11F_B10F: return ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT); + case GPU_RGBA16F: + return ELEM(data_format, GPU_DATA_HALF_FLOAT, GPU_DATA_FLOAT); default: return data_format == GPU_DATA_FLOAT; } @@ -584,7 +588,7 @@ inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format) static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format) { - if (format->attr_len > 1 || format->attr_len == 0) { + if (format->attr_len == 0) { BLI_assert_msg(0, "Incorrect vertex format for buffer texture"); return GPU_DEPTH_COMPONENT24; } diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index a441cfe2fb8..abf5d2dc4c0 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -278,7 +278,7 @@ void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts_, uint a_idx, GPUVertBufRaw access->data = (uchar *)verts->data + a->offset; access->data_init = access->data; #ifdef DEBUG - access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride); + access->_data_end = access->data_init + size_t(verts->vertex_alloc * format->stride); #endif } diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index 897e80293bf..76d95ac1b55 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -251,7 +251,7 @@ static void safe_bytes(char out[11], const char data[8]) } } -void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint UNUSED(max_len)) +void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint /*max_len*/) { char data[8] = {0}; uint len = strlen(attr_name); @@ -361,8 +361,12 @@ void VertexFormat_texture_buffer_pack(GPUVertFormat *format) * minimum per-vertex stride, which mandates 4-byte alignment in Metal. * This additional alignment padding caused smaller data types, e.g. U16, * to mis-align. */ - BLI_assert_msg(format->attr_len == 1, - "Texture buffer mode should only use a single vertex attribute."); + for (int i = 0; i < format->attr_len; i++) { + /* The buffer texture setup uses the first attribute for type and size. + * Make sure all attributes use the same size. */ + BLI_assert_msg(format->attrs[i].size == format->attrs[0].size, + "Texture buffer mode should only use a attributes with the same size."); + } /* Pack vertex format without minimum stride, as this is not required by texture buffers. */ VertexFormat_pack_impl(format, 1); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 71bdf9e336b..e267d5a2f12 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -147,6 +147,10 @@ static void gpu_viewport_textures_create(GPUViewport *viewport) if (viewport->depth_tx == NULL) { viewport->depth_tx = GPU_texture_create_2d( "dtxl_depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL); + if (GPU_clear_viewport_workaround()) { + static int depth_clear = 0; + GPU_texture_clear(viewport->depth_tx, GPU_DATA_UINT_24_8, &depth_clear); + } } if (!viewport->depth_tx || !viewport->color_render_tx[0] || !viewport->color_overlay_tx[0]) { |