1
1

Compare commits

...

57 Commits

Author SHA1 Message Date
ea8eb348c3 DRW: Resource Handle: Use manual bitmasks and bitsifts
This is in order to avoid implementation dependant behavior.
2019-08-17 14:48:49 +02:00
3cde5f1f59 DRW: Fix regression when rendering using index ranges 2019-08-17 14:48:49 +02:00
19999c6ffb GPU: Fix USE_MULTI_DRAW_INDIRECT macro
Now uses GPU_arb_base_instance_is_supported properly.
2019-08-17 14:48:49 +02:00
b10c14d143 Workbench: Fix dark mesh when no material applied 2019-08-17 14:48:49 +02:00
40771fb8c8 BLI_memblock: Remove ATTR_MALLOC flags
This is made to do some optimization but this is creating unwanted behavior.
2019-08-17 14:48:49 +02:00
e62ab0086a DRW: Fix and improve DRW_pass_sort_shgroup_z
Now sorting only compare and does not compute Z distance for each
comparisson. It also keeps the order of shgroups with the same distances.
2019-08-17 14:48:49 +02:00
4e1b09f122 DRW: Move Shading Group Extra DRWState to own DRWCommand 2019-08-17 14:48:49 +02:00
bd2a41c30a DRW: Use a DRWResourceHandle to reference the parent DRWPass ...
... inside a DRWShadingGroup
2019-08-17 14:48:49 +02:00
ef87957799 Cleanup: DRW: Add draw_call_batching_flush for easier code understanding 2019-08-17 14:48:49 +02:00
64aafef5ba DRW: Move DRWUniformChunk length and used counter to the struct itself.
This is better for code simplicity. Memory usage is not that much of a
concern for uniforms.
2019-08-17 14:48:49 +02:00
673742001a DRW: Add DRWCommandSetStencil
Now multiple stencils can be set inside a shgroup.

Should not change the previous behavior as all usage of
DRW_shgroup_stencil_mask was done at shgroup creation.
2019-08-17 14:48:49 +02:00
8d0713e8d2 DRW: Refactor replacing DRWCall by DRWCommand
DRWCall was fat and not very flexible. DRWCommand is very small and makes
it possible to have many kind of DRWCommand making the DRWManager more
extensible. Like adding the possibility of changing the stencil mask or
clear framebuffers in between drawcalls.

This commit breaks shgroup z sorting.
2019-08-17 14:48:48 +02:00
b363113c2d Workbench: Fix Shader compilation 2019-08-17 14:48:48 +02:00
d78a6369ad GPencil: Use custom obmat instead of common_view_lib 2019-08-17 14:48:48 +02:00
2b2e120126 DRW: Put Transform Feedback buffer into DRWUniform
Since the transform feedback must be the same for the whole SHgroup, and
since it is optional, put it in DRWUniform to make things cleaner.
2019-08-17 14:48:48 +02:00
af48712d88 Cleanup: DRW: Make drawcall render control flow a more easier to follow. 2019-08-17 14:48:48 +02:00
0e6dcde771 GPU: Fix flush range and uninitialized buffer_id 2019-08-17 14:48:48 +02:00
ff18606235 DRW: Fix Batch key bitshifting
63 is 0b111111.
2019-08-17 14:48:48 +02:00
e2d8f99013 Workbench: Simplify / Speedup Material Hash
This is negligeable speedup.
2019-08-17 14:48:48 +02:00
d9a7ec3947 DRW: Use new GPUDrawList to speedup instancing
This improves the performances of random instancing even further.
Test 30K objects:
42 fps -> 52 fps
24 ms  -> 19 ms
2019-08-17 14:48:48 +02:00
6fabca487a GPU: Add API to use multidrawindirect using GPUbatch
This new API record a list of command that use the same batch and submit
it to the GPU in one call.
2019-08-17 14:48:48 +02:00
15a4171e2d DRW: Add draw call sorting
This makes rendering lots of similar objects much faster (with lower CPU
overhead).

29 fps -> 38 fps
34 ms  -> 26 ms
In my test case with 30K instances of 4 different meshes
2019-08-17 14:48:48 +02:00
0e6d17edfe Workbench: Remove object_id and optimize material hash generation
This greatly reduce shgroup count when rendering with outlines.
In my testcase (30K suzanes with random instancing, 5 materials) it went
from 27 to 39 fps (playback performance, no update).
2019-08-17 14:48:48 +02:00
f3a1080f33 Workbench: Use resource_id instead of own index
This only modifies the shader and should not create real improvement.
However, this makes it possible to reduce shgroups count drastically
when outline rendering is enabled.
2019-08-17 14:48:48 +02:00
4269a8504f DRW: Make workaround for drivers with broken gl_InstanceID 2019-08-17 14:48:48 +02:00
0f5d15eddb Cleanup: GPUBatch: rename arguments 2019-08-17 14:48:48 +02:00
08ac184ef0 Edit Curve: Fix curve normals 2019-08-17 14:48:48 +02:00
4649deaab7 DRW: Remove common_view_lib uniform default values
Thoses default values makes the uniform never disabled so they
are updated even if not used.
2019-08-17 14:48:48 +02:00
405460c8ca DRW: Use int instead of uint for DRWCall
This let us tag non-instancing calls by tagging them with -1
2019-08-17 14:48:48 +02:00
0e7b07221e Object Mode: Add back lightprobe selection outlines 2019-08-17 14:48:48 +02:00
dd4276844e DRW: Add builtin uniform to get full DRWResourceHandle from shader
This solves the issue with loosing outline around meshes that have
the same ID. Now it needs to have 16K objects in the scene for that to
happen.
2019-08-17 14:48:48 +02:00
7e7c9d4e17 Object Mode: Outlines: Rewrite id pass generation
This makes the ID pass for outline detection use the new
resource_id in order to differenciate drawcalls.

Since the drawcalls have IDs in the range of [0..511] this means objects
with the same id will have their outlines merges. This will be fixed in
next commit.

Lightprobes have their outlines disabled for now.
2019-08-17 14:48:48 +02:00
70892ec1e1 DRW: Refactor to support draw call batching
This refactor improve draw structures CPU/Memory efficiency and lower the
driver overhead of doing many drawcalls.

- Model Matrix is now part of big UBOs that contain 1024 matrices.
- Object Infos follow the same improvement.
- Matrices are indexed by gl_BaseInstanceARB or a fallback uniform.
- All these resources are using a single 32bit identifier (DRWResourceHandle).
- DRWUniform & DRWCall are alloced in chunks to improve cache coherence & memory usage.
- DRWUniform now support up to vec4_copy.
- Draw calls are batch together if their resource id are consecutive.

This has a great impact on CPU usage when using lots of instances. Even if the biggest
bottleneck in these situations is the depsgraph iteration, the driver overhead when doing
thousands of drawcalls is still high.

This only improve situations where the CPU is the bottleneck: small geometry, lots of
instances.

The next step is to sort the drawcall inside a DRWCallChunk to improve the batching process
when instancing order is pretty random.

Reviewers: brecht, antoniov

Differential Revision: https://developer.blender.org/D4997
2019-08-17 14:48:48 +02:00
11e6de7187 BLI_memblock: Use aligned memory blocks
This is because we upload certain chunks directly as UBO data and
AMD suggests to use aligned block to speedup memcpy.

However, this implies the driver is also doing an aligned allocation
which seems not to be the case on linux_x64 + radeon + mesa.
2019-08-17 14:48:48 +02:00
8cf4795212 Cleanup: DRW: Break rendering loop into smaller functions 2019-08-17 14:48:48 +02:00
3a72860c3d Cleanup: DRW: move DRWShadingGroup uniform locations to DRWUniform 2019-08-17 14:48:48 +02:00
80e199cf4d GPU: Make Eevee shader pass resourceID to the fragment shader
this way we don't need a fallback uniform and the overcome the
impossibility to do draw call merging with these shaders.
2019-08-17 14:48:48 +02:00
4d7fba508d DRW: Put DRWCalls into DRWCallChunks
This is in order to improve cache coherence and make it possible
to sort and merge drawcalls in the future.
2019-08-17 14:48:48 +02:00
f404edda61 Cleanup: Wireframe: Use vec3_copy and remove unused code 2019-08-17 14:48:48 +02:00
94cc12e11e GPUBatch: Bypass empty drawcalls
These should be taken care of at a higher level but it's not
always possible. So it's still nice for cleaning up
captures in renderdoc.
2019-08-17 14:48:48 +02:00
7076121175 Cleanup: GPU: Avoid implicit matrix multiplication 2019-08-17 14:48:48 +02:00
a2a539a61d Object Mode: Fix/Cleanup LightGrid overlays 2019-08-17 14:48:48 +02:00
f2c223f44d DRW: Add DRW_shgroup_uniform_vec3/4_copy
This will allow to remove a lot of temporary storage.
2019-08-17 14:48:48 +02:00
542d51881a DRW: Replace single DRWUniform alloc by DRWUniformChunk
This is in order to improve cache coherence and lower memory
usage.

The savings in memory are used to be able to do vec4_copy
uniforms.
2019-08-17 14:48:48 +02:00
31ff2fd530 Cleanup: DRW: Remove unused vars and reduce size of DRWUniform 2019-08-17 14:48:48 +02:00
b400cb1828 DRW: Port Workbench to use DRWObjectInfos ubos 2019-08-17 14:48:48 +02:00
05e04588b5 DRW: Port Eevee to use DRWObjectInfos ubos 2019-08-17 14:48:48 +02:00
516cb160de DRW: Remove DRWCallSate in favor of DRWResourceHandle 2019-08-17 14:48:48 +02:00
1112b6cd73 DRW: Fix Eevee rendering broken due to recent changes 2019-08-17 14:48:48 +02:00
4bb6be01ed DRW: Fix eevee shaders and promote DRAW_ID to builtin uniform
Also rename DRAWID to BASE_INSTANCE

The Base instance uniform is necessary because fragment shaders
does not have the gl_BaseInstance builtin input variable.

So we need a workaround for those
2019-08-17 14:48:48 +02:00
fb940758a9 DRW: Replace DRW_CALL_OBINFOS by a boolean in DRWManager
This is to remove the use of keeping a shared flag per drawcall.
2019-08-17 14:48:48 +02:00
6c051273f0 DRW: Make DRWCullingState referenced by DRWResourceHandle 2019-08-17 14:48:48 +02:00
b9af19ec76 DRW: Use ARB_shader_draw_parameters when available
This is to pass the offset of the object data to the shader
without a uniform call.
2019-08-17 14:48:48 +02:00
d2e9e2713a DRW: Use Model Matrix UBO blocks when possible
This bind the correct UBO block and pass the id inside the block
using a single int uniform.

There is still a legacy path for shader not using the modelBlock
2019-08-17 14:48:48 +02:00
1814ea80bf DRW: Make DRWCall use resource handle 2019-08-17 14:48:48 +02:00
184b01c509 DRW: Upload model matrices via UBO
The UBO is still not used so nothing should fail for now.
2019-08-17 14:48:48 +02:00
b5890e9672 DRW: Make Call matrices and object infos into their own containers
This is in preparation of some bigger refactor that will put all
object matrices and infos into UBOs.

So this commit introduce a bit of performance penalty but it will
be claimed back!
2019-08-17 14:48:48 +02:00
54 changed files with 2165 additions and 1141 deletions

View File

@@ -30,16 +30,20 @@ extern "C" {
#include "BLI_compiler_attrs.h"
#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */
struct BLI_memblock;
typedef struct BLI_memblock BLI_memblock;
typedef void (*MemblockValFreeFP)(void *val);
BLI_memblock *BLI_memblock_create(uint elem_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size) ATTR_WARN_UNUSED_RESULT;
void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1);
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1);
#define BLI_memblock_create(elem_size) BLI_memblock_create_ex(elem_size, BLI_MEM_BLOCK_CHUNK_SIZE)
typedef struct BLI_memblock_iter {
void **chunk_list;
int cur_index;
@@ -53,6 +57,9 @@ typedef struct BLI_memblock_iter {
void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL();
void *BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
#ifdef __cplusplus
}
#endif

View File

@@ -37,7 +37,6 @@
#include "BLI_strict_flags.h" /* keep last */
#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */
#define CHUNK_LIST_SIZE 16
struct BLI_memblock {
@@ -61,18 +60,19 @@ struct BLI_memblock {
int chunk_len;
};
BLI_memblock *BLI_memblock_create(uint elem_size)
BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size)
{
BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
BLI_assert(elem_size < chunk_size);
BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
mblk->elem_size = (int)elem_size;
mblk->elem_next = 0;
mblk->elem_last = -1;
mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE;
mblk->chunk_size = (int)chunk_size;
mblk->chunk_len = CHUNK_LIST_SIZE;
mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list");
mblk->chunk_list[0] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk");
mblk->chunk_list[0] = MEM_mallocN_aligned((uint)mblk->chunk_size, 32, "BLI_memblock chunk");
memset(mblk->chunk_list[0], 0x0, (uint)mblk->chunk_size);
mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size;
mblk->elem_next_ofs = 0;
mblk->chunk_next = 0;
@@ -143,8 +143,9 @@ void *BLI_memblock_alloc(BLI_memblock *mblk)
}
if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == NULL)) {
mblk->chunk_list[mblk->chunk_next] = MEM_callocN((uint)mblk->chunk_size,
"BLI_memblock chunk");
mblk->chunk_list[mblk->chunk_next] = MEM_mallocN_aligned(
(uint)mblk->chunk_size, 32, "BLI_memblock chunk");
memset(mblk->chunk_list[mblk->chunk_next], 0x0, (uint)mblk->chunk_size);
}
}
return ptr;
@@ -180,3 +181,11 @@ void *BLI_memblock_iterstep(BLI_memblock_iter *iter)
}
return ptr;
}
/* Direct access. elem is element index inside the chosen chunk. */
void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
{
BLI_assert(chunk < mblk->chunk_len);
BLI_assert(elem < (mblk->chunk_size / mblk->elem_size));
return (char *)(mblk->chunk_list[chunk]) + mblk->elem_size * elem;
}

View File

@@ -48,6 +48,9 @@ static struct {
char *frag_shader_lib;
char *vert_shader_str;
char *vert_shadow_shader_str;
char *vert_background_shader_str;
char *vert_volume_shader_str;
char *geom_volume_shader_str;
char *volume_shader_lib;
struct GPUShader *default_prepass_sh;
@@ -602,6 +605,15 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
e_data.vert_shadow_shader_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_background_vert_glsl);
e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_volumetric_vert_glsl);
e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_volumetric_geom_glsl);
e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
NULL,
datatoc_default_world_frag_glsl,
@@ -675,7 +687,7 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
wo,
engine,
options,
datatoc_background_vert_glsl,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
SHADER_DEFINES "#define PROBE_CAPTURE\n",
@@ -695,7 +707,7 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
wo,
engine,
options,
datatoc_background_vert_glsl,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
SHADER_DEFINES "#define WORLD_BACKGROUND\n",
@@ -718,8 +730,8 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
wo,
engine,
options,
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
defines,
true);
@@ -786,8 +798,8 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
ma,
engine,
options,
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
defines,
true);
@@ -1411,6 +1423,24 @@ static void material_transparent(Material *ma,
const float *spec_p = &ma->spec;
const float *rough_p = &ma->roughness;
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState cur_state;
DRWState all_state = (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK |
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
/* Depth prepass */
if (use_prepass) {
*shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
DRW_shgroup_state_disable(*shgrp_depth, all_state);
DRW_shgroup_state_enable(*shgrp_depth, cur_state);
}
if (ma->use_nodes && ma->nodetree) {
static float error_col[3] = {1.0f, 0.0f, 1.0f};
static float compile_col[3] = {0.5f, 0.5f, 0.5f};
@@ -1468,30 +1498,13 @@ static void material_transparent(Material *ma,
DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1);
}
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState all_state = (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK |
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
DRWState cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
/* Disable other blend modes and use the one we want. */
DRW_shgroup_state_disable(*shgrp, all_state);
DRW_shgroup_state_enable(*shgrp, cur_state);
/* Depth prepass */
if (use_prepass) {
*shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
DRW_shgroup_state_disable(*shgrp_depth, all_state);
DRW_shgroup_state_enable(*shgrp_depth, cur_state);
}
}
/* Return correct material or &defmaterial if slot is empty. */
@@ -1810,6 +1823,9 @@ void EEVEE_materials_free(void)
MEM_SAFE_FREE(e_data.frag_shader_lib);
MEM_SAFE_FREE(e_data.vert_shader_str);
MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
MEM_SAFE_FREE(e_data.vert_background_shader_str);
MEM_SAFE_FREE(e_data.vert_volume_shader_str);
MEM_SAFE_FREE(e_data.geom_volume_shader_str);
MEM_SAFE_FREE(e_data.volume_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);

View File

@@ -359,6 +359,7 @@ static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_Data *vedata,
DRWPass *pass,
GPUShader *shader,
Object *ob,
float (*obmat)[4],
bGPdata *gpd,
bGPDlayer *gpl,
MaterialGPencilStyle *gp_style,
@@ -372,6 +373,8 @@ static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_Data *vedata,
/* e_data.gpencil_fill_sh */
DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1);
/* set style type */
@@ -499,6 +502,7 @@ DRWShadingGroup *gpencil_shgroup_stroke_create(GPENCIL_Data *vedata,
DRWPass *pass,
GPUShader *shader,
Object *ob,
float (*obmat)[4],
bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
@@ -520,6 +524,8 @@ DRWShadingGroup *gpencil_shgroup_stroke_create(GPENCIL_Data *vedata,
DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
/* avoid wrong values */
if ((gpd) && (gpd->pixfactor == 0.0f)) {
gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
@@ -650,6 +656,7 @@ static DRWShadingGroup *gpencil_shgroup_point_create(GPENCIL_Data *vedata,
DRWPass *pass,
GPUShader *shader,
Object *ob,
float (*obmat)[4],
bGPdata *gpd,
bGPDlayer *gpl,
bGPDstroke *gps,
@@ -670,6 +677,8 @@ static DRWShadingGroup *gpencil_shgroup_point_create(GPENCIL_Data *vedata,
DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
/* avoid wrong values */
if ((gpd) && (gpd->pixfactor == 0.0f)) {
gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
@@ -1506,6 +1515,9 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s);
stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
float unit_mat[4][4];
unit_m4(unit_mat);
/* if only one point, don't need to draw buffer because the user has no time to see it */
if (gpd->runtime.sbuffer_used > 1) {
if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
@@ -1514,6 +1526,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
psl->drawing_pass,
e_data->gpencil_stroke_sh,
NULL,
unit_mat,
gpd,
NULL,
NULL,
@@ -1538,6 +1551,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
psl->drawing_pass,
e_data->gpencil_point_sh,
NULL,
unit_mat,
gpd,
NULL,
NULL,
@@ -1718,6 +1732,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
stroke_pass,
e_data->gpencil_stroke_sh,
ob,
obmat,
gpd,
gpl,
gps,
@@ -1727,7 +1742,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
scale,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
DRW_shgroup_call_range_obmat(shgrp, cache->b_stroke.batch, obmat, start_stroke, len);
DRW_shgroup_call_range(shgrp, cache->b_stroke.batch, start_stroke, len);
}
stl->storage->shgroup_id++;
start_stroke = elm->vertex_idx;
@@ -1752,6 +1767,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
stroke_pass,
e_data->gpencil_point_sh,
ob,
obmat,
gpd,
gpl,
gps,
@@ -1762,7 +1778,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
DRW_shgroup_call_range_obmat(shgrp, cache->b_point.batch, obmat, start_point, len);
DRW_shgroup_call_range(shgrp, cache->b_point.batch, start_point, len);
}
stl->storage->shgroup_id++;
start_point = elm->vertex_idx;
@@ -1780,6 +1796,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
stroke_pass,
e_data->gpencil_fill_sh,
ob,
obmat,
gpd,
gpl,
gp_style,
@@ -1787,7 +1804,7 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
DRW_shgroup_call_range_obmat(shgrp, cache->b_fill.batch, obmat, start_fill, len);
DRW_shgroup_call_range(shgrp, cache->b_fill.batch, start_fill, len);
}
stl->storage->shgroup_id++;
start_fill = elm->vertex_idx;
@@ -1801,9 +1818,12 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
case eGpencilBatchGroupType_Edit: {
if (stl->g_data->shgrps_edit_point) {
const int len = elm->vertex_idx - start_edit;
shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_point);
DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat);
/* use always the same group */
DRW_shgroup_call_range_obmat(
stl->g_data->shgrps_edit_point, cache->b_edit.batch, obmat, start_edit, len);
DRW_shgroup_call_range(
stl->g_data->shgrps_edit_point, cache->b_edit.batch, start_edit, len);
start_edit = elm->vertex_idx;
}
@@ -1812,9 +1832,12 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
case eGpencilBatchGroupType_Edlin: {
if (stl->g_data->shgrps_edit_line) {
const int len = elm->vertex_idx - start_edlin;
shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_line);
DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat);
/* use always the same group */
DRW_shgroup_call_range_obmat(
stl->g_data->shgrps_edit_line, cache->b_edlin.batch, obmat, start_edlin, len);
DRW_shgroup_call_range(
stl->g_data->shgrps_edit_line, cache->b_edlin.batch, start_edlin, len);
start_edlin = elm->vertex_idx;
}

View File

@@ -401,6 +401,7 @@ struct DRWShadingGroup *gpencil_shgroup_stroke_create(struct GPENCIL_Data *vedat
struct DRWPass *pass,
struct GPUShader *shader,
struct Object *ob,
float (*obmat)[4],
struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDstroke *gps,

View File

@@ -1,4 +1,6 @@
uniform mat4 gpModelMatrix;
in vec3 pos;
in vec4 color;
in float size;
@@ -8,7 +10,7 @@ out float finalThickness;
void main()
{
gl_Position = point_object_to_ndc(pos);
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
finalColor = color;
finalThickness = size;
}

View File

@@ -1,4 +1,6 @@
uniform mat4 gpModelMatrix;
in vec3 pos;
in vec4 color;
in vec2 texCoord;
@@ -8,7 +10,7 @@ out vec2 texCoord_interp;
void main(void)
{
gl_Position = point_object_to_ndc(pos);
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
finalColor = color;
texCoord_interp = texCoord;
}

View File

@@ -6,6 +6,7 @@ uniform float pixfactor;
uniform int viewport_xray;
uniform int shading_type[2];
uniform vec4 wire_color;
uniform mat4 gpModelMatrix;
in vec3 pos;
in vec4 color;
@@ -30,8 +31,8 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor);
void main()
{
gl_Position = point_object_to_ndc(pos);
finalprev_pos = point_object_to_ndc(prev_pos);
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
finalprev_pos = point_world_to_ndc((gpModelMatrix * vec4(prev_pos, 1.0)).xyz);
finalColor = color;
if (keep_size == TRUE) {

View File

@@ -6,6 +6,7 @@ uniform float pixfactor;
uniform int viewport_xray;
uniform int shading_type[2];
uniform vec4 wire_color;
uniform mat4 gpModelMatrix;
in vec3 pos;
in vec4 color;
@@ -28,7 +29,7 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor);
void main(void)
{
gl_Position = point_object_to_ndc(pos);
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
finalColor = color;
if (keep_size == TRUE) {

View File

@@ -1,5 +1,6 @@
uniform int object_id = 0;
layout(location = 0) out uint objectId;
uniform float ImageTransparencyCutoff = 0.1;
#ifdef V3D_SHADING_TEXTURE_COLOR
uniform sampler2D image;
@@ -10,11 +11,10 @@ in vec2 uv_interp;
void main()
{
#ifdef V3D_SHADING_TEXTURE_COLOR
vec4 diffuse_color = texture(image, uv_interp);
if (diffuse_color.a < ImageTransparencyCutoff) {
if (texture(image, uv_interp).a < ImageTransparencyCutoff) {
discard;
}
#endif
objectId = uint(object_id);
objectId = uint(resource_id + 1) & 0xFFu;
}

View File

@@ -8,8 +8,7 @@ uniform float alpha = 0.5;
uniform vec2 invertedViewportSize;
uniform vec4 viewvecs[3];
uniform vec3 materialDiffuseColor;
uniform vec3 materialSpecularColor;
uniform vec4 materialColorAndMetal;
uniform float materialRoughness;
uniform float shadowMultiplier = 0.5;
@@ -41,17 +40,17 @@ layout(location = 1) out
void main()
{
vec4 diffuse_color;
vec4 base_color;
#if defined(V3D_SHADING_TEXTURE_COLOR)
diffuse_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied);
if (diffuse_color.a < ImageTransparencyCutoff) {
base_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied);
if (base_color.a < ImageTransparencyCutoff) {
discard;
}
#elif defined(V3D_SHADING_VERTEX_COLOR)
diffuse_color = vec4(vertexColor, 1.0);
base_color.rgb = vertexColor;
#else
diffuse_color = vec4(materialDiffuseColor, 1.0);
base_color.rgb = materialColorAndMetal.rgb;
#endif /* V3D_SHADING_TEXTURE_COLOR */
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
@@ -63,17 +62,26 @@ void main()
/* -------- SHADING --------- */
#ifdef V3D_LIGHTING_FLAT
vec3 shaded_color = diffuse_color.rgb;
vec3 shaded_color = base_color.rgb;
#elif defined(V3D_LIGHTING_MATCAP)
bool flipped = world_data.matcap_orientation != 0;
vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
vec3 shaded_color = matcap * diffuse_color.rgb;
vec3 shaded_color = matcap * base_color.rgb;
#elif defined(V3D_LIGHTING_STUDIO)
# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
float metallic = materialColorAndMetal.a;
vec3 specular_color = mix(vec3(0.05), base_color.rgb, metallic);
vec3 diffuse_color = mix(base_color.rgb, vec3(0.0), metallic);
# else
vec3 specular_color = vec3(0.0);
vec3 diffuse_color = base_color.rgb;
# endif
vec3 shaded_color = get_world_lighting(
world_data, diffuse_color.rgb, materialSpecularColor, materialRoughness, nor, I_vs);
world_data, diffuse_color, specular_color, materialRoughness, nor, I_vs);
#endif
#ifdef V3D_SHADING_SHADOW

View File

@@ -1,7 +1,5 @@
uniform int object_id = 0;
uniform vec3 materialDiffuseColor;
uniform float materialMetallic;
uniform vec4 materialColorAndMetal;
uniform float materialRoughness;
uniform sampler2D image;
@@ -48,7 +46,7 @@ void main()
# elif defined(V3D_SHADING_VERTEX_COLOR)
color.rgb = vertexColor;
# else
color.rgb = materialDiffuseColor;
color.rgb = materialColorAndMetal.rgb;
# endif
# ifdef V3D_LIGHTING_MATCAP
@@ -56,7 +54,7 @@ void main()
metallic = float(gl_FrontFacing);
roughness = 0.0;
# else
metallic = materialMetallic;
metallic = materialColorAndMetal.a;
roughness = materialRoughness;
# endif
@@ -64,7 +62,7 @@ void main()
/* Add some variation to the hairs to avoid uniform look. */
float hair_variation = hair_rand * 0.1;
color = clamp(color - hair_variation, 0.0, 1.0);
metallic = clamp(materialMetallic - hair_variation, 0.0, 1.0);
metallic = clamp(materialColorAndMetal.a - hair_variation, 0.0, 1.0);
roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0);
# endif
@@ -73,7 +71,7 @@ void main()
#endif /* MATDATA_PASS_ENABLED */
#ifdef OBJECT_ID_PASS_ENABLED
objectId = uint(object_id);
objectId = uint(resource_id + 1) & 0xFFu;
#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED

View File

@@ -25,6 +25,10 @@ out vec2 uv_interp;
out vec3 vertexColor;
#endif
#ifdef OBJECT_ID_PASS_ENABLED
RESOURCE_ID_VARYING
#endif
/* From http://libnoise.sourceforge.net/noisegen/index.html */
float integer_noise(int n)
{
@@ -91,12 +95,18 @@ void main()
#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
normal_viewport = normal_object_to_view(nor);
# ifndef HAIR_SHADER
normal_viewport = normal_object_to_view(nor);
normal_viewport = normalize(normal_viewport);
# else
normal_viewport = normal_world_to_view(nor);
# endif
#endif
#ifdef OBJECT_ID_PASS_ENABLED
PASS_RESOURCE_ID
#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif

View File

@@ -1,6 +1,4 @@
uniform vec3 OrcoTexCoFactors[2];
uniform sampler2D depthBuffer;
uniform sampler3D densityTexture;
@@ -216,13 +214,13 @@ void main()
vs_ray_dir /= abs(vs_ray_dir.z);
/* TODO(fclem) Precompute the matrix/ */
vec3 ls_ray_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0;
vec3 ls_ray_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1].xyz * 2.0;
ls_ray_dir = mat3(ModelMatrixInverse) * ls_ray_dir;
vec3 ls_ray_ori = point_view_to_object(vs_ray_ori);
vec3 ls_ray_end = point_view_to_object(vs_ray_end);
ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0;
ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0;
ls_ray_ori = (OrcoTexCoFactors[0].xyz + ls_ray_ori * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
ls_ray_end = (OrcoTexCoFactors[0].xyz + ls_ray_end * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
/* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */

View File

@@ -1,5 +1,4 @@
uniform vec3 OrcoTexCoFactors[2];
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
@@ -27,6 +26,6 @@ void main()
#else
vec3 final_pos = pos;
#endif
final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1];
final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0].xyz) / OrcoTexCoFactors[1].xyz;
gl_Position = point_object_to_ndc(final_pos);
}

View File

@@ -83,7 +83,6 @@ static struct {
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
SceneDisplay display; /* world light direction for shadows */
int next_object_id;
struct GPUUniformBuffer *sampling_ubo;
struct GPUTexture *jitter_tx;
@@ -147,6 +146,7 @@ static char *workbench_build_prepass_frag(void)
{
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_prepass_frag_glsl);
@@ -330,7 +330,6 @@ static struct GPUTexture *create_jitter_texture(int num_samples)
static void workbench_init_object_data(DrawData *dd)
{
WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd;
data->object_id = ((e_data.next_object_id++) & 0xff) + 1;
data->shadow_bbox_dirty = true;
}
@@ -379,11 +378,10 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
workbench_effect_info_init(stl->effects);
}
if (!e_data.next_object_id) {
if (!e_data.shadow_pass_sh) {
WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
memset(sh_data->prepass_sh_cache, 0, sizeof(sh_data->prepass_sh_cache));
memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache));
e_data.next_object_id = 1;
#ifdef DEBUG_SHADOW_VOLUME
const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl;
#else
@@ -862,18 +860,11 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_PrivateData *wpd = stl->g_data;
WORKBENCH_MaterialData *material;
WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
&ob->id,
&draw_engine_workbench_solid,
sizeof(WORKBENCH_ObjectData),
&workbench_init_object_data,
NULL);
WORKBENCH_MaterialData material_template;
const bool is_ghost = (ob->dtx & OB_DRAWXRAY);
/* Solid */
workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
material_template.iuser = iuser;
@@ -893,8 +884,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
shader, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
workbench_material_copy(material, &material_template);
DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1);
workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true, interp);
workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, interp);
BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material);
}
return material;
@@ -937,8 +927,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
(ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_hair_pass : psl->prepass_hair_pass,
shader);
DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true, interp);
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, interp);
}
}
}

View File

@@ -63,8 +63,6 @@ static struct {
struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */
struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
int next_object_id;
} e_data = {{{{NULL}}}};
/* Shaders */
@@ -98,6 +96,18 @@ static char *workbench_build_forward_vert(bool is_hair)
return str;
}
static char *workbench_build_forward_outline_frag(void)
{
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_forward_depth_frag_glsl);
char *str = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return str;
}
static char *workbench_build_forward_transparent_accum_frag(void)
{
DynStr *ds = BLI_dynstr_new();
@@ -129,12 +139,6 @@ static char *workbench_build_forward_composite_frag(void)
return str;
}
static void workbench_init_object_data(DrawData *dd)
{
WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd;
data->object_id = ((e_data.next_object_id++) & 0xff) + 1;
}
WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_Data *vedata,
Object *ob,
Material *mat,
@@ -149,18 +153,11 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
WORKBENCH_PassList *psl = vedata->psl;
WORKBENCH_PrivateData *wpd = stl->g_data;
WORKBENCH_MaterialData *material;
WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
&ob->id,
&draw_engine_workbench_solid,
sizeof(WORKBENCH_ObjectData),
&workbench_init_object_data,
NULL);
WORKBENCH_MaterialData material_template;
DRWShadingGroup *grp;
/* Solid */
workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
material_template.iuser = iuser;
@@ -199,7 +196,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus);
}
workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false, interp);
workbench_material_shgroup_uniform(wpd, grp, material, ob, false, interp);
material->shgrp = grp;
/* Depth */
@@ -213,8 +210,6 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_sh,
psl->object_outline_pass);
}
material->object_id = engine_object_data->object_id;
DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_state_enable(material->shgrp_object_outline, DRW_STATE_CLIP_PLANES);
}
@@ -286,26 +281,30 @@ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUSh
char *defines_texture = workbench_material_build_defines(wpd, true, false, false);
char *defines_hair = workbench_material_build_defines(wpd, false, true, false);
char *forward_vert = workbench_build_forward_vert(false);
char *forward_frag = workbench_build_forward_outline_frag();
char *forward_hair_vert = workbench_build_forward_vert(true);
const char *define_id_pass = "#define OBJECT_ID_PASS_ENABLED\n";
sh_data->object_outline_sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL},
.frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines, NULL},
.frag = (const char *[]){forward_frag, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines, define_id_pass, NULL},
});
sh_data->object_outline_texture_sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL},
.frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines_texture, NULL},
.frag = (const char *[]){forward_frag, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines_texture, define_id_pass, NULL},
});
sh_data->object_outline_hair_sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib, forward_hair_vert, NULL},
.frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines_hair, NULL},
.frag = (const char *[]){forward_frag, NULL},
.defs = (const char *[]){sh_cfg_data->def, defines_hair, define_id_pass, NULL},
});
MEM_freeN(forward_hair_vert);
MEM_freeN(forward_vert);
MEM_freeN(forward_frag);
MEM_freeN(defines);
MEM_freeN(defines_texture);
MEM_freeN(defines_hair);
@@ -521,7 +520,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
ob, psys, md, psl->transparent_accum_pass, shader);
DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false, interp);
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, interp);
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
/* Hairs have lots of layer and can rapidly become the most prominent surface.
* So lower their alpha artificially. */
@@ -539,7 +538,6 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
shgrp = DRW_shgroup_hair_create(
ob, psys, md, vedata->psl->object_outline_pass, sh_data->object_outline_hair_sh);
DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
}
}
}

View File

@@ -44,20 +44,15 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
WORKBENCH_MaterialData *data,
int color_type)
{
copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f);
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */
data->metallic = 0.0f;
data->roughness = 0.632455532f; /* sqrtf(0.4f); */
data->alpha = wpd->shading.xray_alpha;
if (color_type == V3D_SHADING_SINGLE_COLOR) {
copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_v3(data->base_color, wpd->shading.single_color);
}
else if (color_type == V3D_SHADING_ERROR_COLOR) {
copy_v3_fl3(data->diffuse_color, 0.8, 0.0, 0.8);
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_fl3(data->base_color, 0.8, 0.0, 0.8);
}
else if (color_type == V3D_SHADING_RANDOM_COLOR) {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
@@ -67,30 +62,24 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
float hue = BLI_hash_int_01(hash);
float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
hsv_to_rgb_v(hsv, data->diffuse_color);
copy_v3_v3(data->base_color, data->diffuse_color);
hsv_to_rgb_v(hsv, data->base_color);
}
else if (ELEM(color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_VERTEX_COLOR)) {
copy_v3_v3(data->diffuse_color, ob->color);
copy_v3_v3(data->base_color, data->diffuse_color);
data->alpha *= ob->color[3];
copy_v3_v3(data->base_color, ob->color);
}
else {
/* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */
if (mat) {
data->alpha *= mat->a;
copy_v3_v3(data->base_color, &mat->r);
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
copy_v3_v3(data->base_color, &mat->r);
mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic);
add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic));
data->metallic = mat->metallic;
data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */
}
else {
copy_v3_v3(data->base_color, &mat->r);
copy_v3_v3(data->diffuse_color, &mat->r);
}
}
else {
copy_v3_fl(data->base_color, 0.8f);
}
}
}
@@ -160,34 +149,40 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
return str;
}
uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost)
uint workbench_material_get_hash(WORKBENCH_MaterialData *mat, bool is_ghost)
{
uint input[4];
uint result;
float *color = material_template->diffuse_color;
input[0] = (uint)(color[0] * 512);
input[1] = (uint)(color[1] * 512);
input[2] = (uint)(color[2] * 512);
input[3] = material_template->object_id;
result = BLI_ghashutil_uinthash_v4_murmur(input);
union {
struct {
/* WHATCH: Keep in sync with View3DShading.color_type max value. */
uchar color_type;
uchar diff_r;
uchar diff_g;
uchar diff_b;
color = material_template->specular_color;
input[0] = (uint)(color[0] * 512);
input[1] = (uint)(color[1] * 512);
input[2] = (uint)(color[2] * 512);
input[3] = (uint)(material_template->roughness * 512);
result += BLI_ghashutil_uinthash_v4_murmur(input);
uchar alpha;
uchar ghost;
uchar metal;
uchar roughness;
result += BLI_ghashutil_uinthash((uint)(material_template->alpha * 512));
result += BLI_ghashutil_uinthash((uint)is_ghost);
result += BLI_ghashutil_uinthash(material_template->color_type);
void *ima;
};
/* HACK to ensure input is 4 uint long. */
uint a[4];
} input = {.color_type = (uchar)(mat->color_type),
.diff_r = (uchar)(mat->base_color[0] * 0xFF),
.diff_g = (uchar)(mat->base_color[1] * 0xFF),
.diff_b = (uchar)(mat->base_color[2] * 0xFF),
/* add texture reference */
if (material_template->ima) {
result += BLI_ghashutil_inthash_p_murmur(material_template->ima);
}
.alpha = (uint)(mat->alpha * 0xFF),
.ghost = (uchar)is_ghost,
.metal = (uchar)(mat->metallic * 0xFF),
.roughness = (uchar)(mat->roughness * 0xFF),
return result;
.ima = mat->ima};
BLI_assert(sizeof(input) == sizeof(uint) * 4);
return BLI_ghashutil_uinthash_v4((uint *)&input);
}
int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
@@ -313,35 +308,28 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp,
WORKBENCH_MaterialData *material,
Object *ob,
const bool use_metallic,
const bool deferred,
const int interp)
{
if (!deferred || workbench_is_matdata_pass_enabled(wpd)) {
if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
V3D_SHADING_TEXTURE_COLOR) {
GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "image", tex);
DRW_shgroup_uniform_bool_copy(
grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
}
else {
DRW_shgroup_uniform_vec3(grp,
"materialDiffuseColor",
(use_metallic) ? material->base_color : material->diffuse_color,
1);
}
if (!(!deferred || workbench_is_matdata_pass_enabled(wpd))) {
return;
}
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
if (use_metallic) {
DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
}
else {
DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
}
DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
const bool use_highlight = SPECULAR_HIGHLIGHT_ENABLED(wpd);
const bool use_texture = (V3D_SHADING_TEXTURE_COLOR == workbench_material_determine_color_type(
wpd, material->ima, ob, false));
if (use_texture) {
GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "image", tex);
DRW_shgroup_uniform_bool_copy(
grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
}
if (!use_texture || use_highlight) {
DRW_shgroup_uniform_vec4(grp, "materialColorAndMetal", material->base_color, 1);
}
if (use_highlight) {
DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
if (WORLD_CLIPPING_ENABLED(wpd)) {
@@ -352,10 +340,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
void workbench_material_copy(WORKBENCH_MaterialData *dest_material,
const WORKBENCH_MaterialData *source_material)
{
dest_material->object_id = source_material->object_id;
copy_v3_v3(dest_material->base_color, source_material->base_color);
copy_v3_v3(dest_material->diffuse_color, source_material->diffuse_color);
copy_v3_v3(dest_material->specular_color, source_material->specular_color);
dest_material->metallic = source_material->metallic;
dest_material->roughness = source_material->roughness;
dest_material->ima = source_material->ima;

View File

@@ -284,13 +284,8 @@ typedef struct WORKBENCH_EffectInfo {
} WORKBENCH_EffectInfo;
typedef struct WORKBENCH_MaterialData {
float base_color[3];
float diffuse_color[3];
float specular_color[3];
float alpha;
float metallic;
float roughness;
int object_id;
float base_color[3], metallic;
float roughness, alpha;
int color_type;
int interp;
Image *ima;
@@ -311,8 +306,6 @@ typedef struct WORKBENCH_ObjectData {
float shadow_min[3], shadow_max[3];
BoundBox shadow_bbox;
bool shadow_bbox_dirty;
int object_id;
} WORKBENCH_ObjectData;
/* inline helper functions */
@@ -493,7 +486,6 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp,
WORKBENCH_MaterialData *material,
Object *ob,
const bool use_metallic,
const bool deferred,
const int interp);
void workbench_material_copy(WORKBENCH_MaterialData *dest_material,

View File

@@ -27,6 +27,7 @@
#include "BLI_rand.h"
#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
@@ -54,6 +55,7 @@ static struct {
extern char datatoc_workbench_volume_vert_glsl[];
extern char datatoc_workbench_volume_frag_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic)
{
@@ -78,12 +80,16 @@ static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic)
char *defines = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
char *libs = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_gpu_shader_common_obinfos_lib_glsl);
e_data.volume_sh[id] = DRW_shader_create_with_lib(datatoc_workbench_volume_vert_glsl,
NULL,
datatoc_workbench_volume_frag_glsl,
datatoc_common_view_lib_glsl,
libs,
defines);
MEM_freeN(libs);
MEM_freeN(defines);
}

View File

@@ -84,8 +84,6 @@ typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
typedef struct DRWView DRWView;
/* Opaque type to avoid usage as a DRWCall but it is exactly the same thing. */
typedef struct DRWCallBuffer DRWCallBuffer;
/* TODO Put it somewhere else? */
@@ -407,35 +405,29 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
Object *ob,
float (*obmat)[4],
struct GPUBatch *geom,
uint v_sta,
uint v_ct,
bool bypass_culling,
void *user_data);
/* If ob is NULL, unit modelmatrix is assumed and culling is bypassed. */
#define DRW_shgroup_call(shgrp, geom, ob) \
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, false, NULL)
#define DRW_shgroup_call(shgrp, geom, ob) DRW_shgroup_call_ex(shgrp, ob, NULL, geom, false, NULL)
/* Same as DRW_shgroup_call but override the obmat. Not culled. */
#define DRW_shgroup_call_obmat(shgrp, geom, obmat) \
DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, 0, 0, false, NULL)
DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, false, NULL)
/* TODO(fclem) remove this when we have DRWView */
/* user_data is used by DRWCallVisibilityFn defined in DRWView. */
#define DRW_shgroup_call_with_callback(shgrp, geom, ob, user_data) \
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, false, user_data)
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, false, user_data)
/* Same as DRW_shgroup_call but bypass culling even if ob is not NULL. */
#define DRW_shgroup_call_no_cull(shgrp, geom, ob) \
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, 0, 0, true, NULL)
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, true, NULL)
/* Only draw a certain range of geom. */
#define DRW_shgroup_call_range(shgrp, geom, ob, v_sta, v_ct) \
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, v_sta, v_ct, false, NULL)
/* Same as DRW_shgroup_call_range but override the obmat. Special for gpencil. */
#define DRW_shgroup_call_range_obmat(shgrp, geom, obmat, v_sta, v_ct) \
DRW_shgroup_call_ex(shgrp, NULL, obmat, geom, v_sta, v_ct, false, NULL)
void DRW_shgroup_call_range(DRWShadingGroup *shgroup,
struct GPUBatch *geom,
uint v_sta,
uint v_ct);
void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_ct);
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_ct);
@@ -528,9 +520,14 @@ void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const
void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4]);
/* Store value instead of referencing it. */
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value);
void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgrp, const char *name, const int *value);
void DRW_shgroup_uniform_ivec3_copy(DRWShadingGroup *shgrp, const char *name, const int *value);
void DRW_shgroup_uniform_ivec4_copy(DRWShadingGroup *shgrp, const char *name, const int *value);
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value);
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value);
void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);

View File

@@ -215,7 +215,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl,
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len);
DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), start_index, len);
}
/* Draw points. */
@@ -231,7 +231,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl,
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len);
DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), start_index, len);
/* Draw frame numbers at each framestep value */
bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;

View File

@@ -201,30 +201,33 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
/* Transform Feedback subdiv. */
if (need_ft_update) {
int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len;
GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
if (final_points_len) {
GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
#ifdef USE_TRANSFORM_FEEDBACK
DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf);
DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(
tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf);
#else
DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
pr_call->next = g_tf_calls;
pr_call->vbo = hair_cache->final[subdiv].proc_buf;
pr_call->shgrp = tf_shgrp;
pr_call->vert_len = final_points_len;
g_tf_calls = pr_call;
DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
pr_call->next = g_tf_calls;
pr_call->vbo = hair_cache->final[subdiv].proc_buf;
pr_call->shgrp = tf_shgrp;
pr_call->vert_len = final_points_len;
g_tf_calls = pr_call;
DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
#endif
DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex);
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex);
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex);
DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex);
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex);
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex);
DRW_shgroup_uniform_int(
tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
}
}
return shgrp;

View File

@@ -64,7 +64,7 @@ typedef struct DRWTempBufferHandle {
/** Format pointer for reuse. */
GPUVertFormat *format;
/** Touched vertex length for resize. */
uint *vert_len;
int *vert_len;
} DRWTempBufferHandle;
static ListBase g_idatalists = {NULL, NULL};
@@ -112,7 +112,7 @@ static void instance_batch_free(GPUBatch *geom, void *UNUSED(user_data))
*/
GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist,
GPUVertFormat *format,
uint *vert_len)
int *vert_len)
{
BLI_assert(format != NULL);
BLI_assert(vert_len != NULL);

View File

@@ -42,7 +42,7 @@ DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint
GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist,
GPUVertFormat *format,
uint *vert_len);
int *vert_len);
GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist,
GPUVertBuf *buf,
GPUBatch *geom);

View File

@@ -540,8 +540,11 @@ static void drw_viewport_cache_resize(void)
GPU_texture_free(*tex);
}
BLI_memblock_clear(DST.vmempool->calls, NULL);
BLI_memblock_clear(DST.vmempool->states, NULL);
BLI_memblock_clear(DST.vmempool->commands, NULL);
BLI_memblock_clear(DST.vmempool->commands_small, NULL);
BLI_memblock_clear(DST.vmempool->callbuffers, NULL);
BLI_memblock_clear(DST.vmempool->obmats, NULL);
BLI_memblock_clear(DST.vmempool->obinfos, NULL);
BLI_memblock_clear(DST.vmempool->cullstates, NULL);
BLI_memblock_clear(DST.vmempool->shgroups, NULL);
BLI_memblock_clear(DST.vmempool->uniforms, NULL);
@@ -589,27 +592,27 @@ static void drw_context_state_init(void)
}
}
static DRWCallState *draw_unit_state_create(void)
static void draw_unit_state_create(void)
{
DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states);
state->flag = 0;
state->matflag = 0;
DRWObjectInfos *infos = BLI_memblock_alloc(DST.vmempool->obinfos);
DRWObjectMatrix *mats = BLI_memblock_alloc(DST.vmempool->obmats);
DRWCullingState *culling = BLI_memblock_alloc(DST.vmempool->cullstates);
unit_m4(state->model);
unit_m4(state->modelinverse);
unit_m4(mats->model);
unit_m4(mats->modelinverse);
copy_v3_fl(state->orcotexfac[0], 0.0f);
copy_v3_fl(state->orcotexfac[1], 1.0f);
copy_v3_fl(infos->orcotexfac[0], 0.0f);
copy_v3_fl(infos->orcotexfac[1], 1.0f);
state->ob_index = 0;
state->ob_random = 0.0f;
infos->ob_index = 0;
infos->ob_random = 0.0f;
infos->ob_neg_scale = 1.0f;
/* TODO(fclem) get rid of this. */
state->culling = BLI_memblock_alloc(DST.vmempool->cullstates);
state->culling->bsphere.radius = -1.0f;
state->culling->user_data = NULL;
culling->bsphere.radius = -1.0f;
culling->user_data = NULL;
return state;
DRW_handle_increment(&DST.resource_handle);
}
/* It also stores viewport variable to an immutable place: DST
@@ -634,33 +637,48 @@ static void drw_viewport_var_init(void)
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
if (DST.vmempool->calls == NULL) {
DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
if (DST.vmempool->commands == NULL) {
DST.vmempool->commands = BLI_memblock_create(sizeof(DRWCommandChunk));
}
if (DST.vmempool->states == NULL) {
DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
if (DST.vmempool->commands_small == NULL) {
DST.vmempool->commands_small = BLI_memblock_create(sizeof(DRWCommandSmallChunk));
}
if (DST.vmempool->callbuffers == NULL) {
DST.vmempool->callbuffers = BLI_memblock_create(sizeof(DRWCallBuffer));
}
if (DST.vmempool->obmats == NULL) {
uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN;
DST.vmempool->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len);
}
if (DST.vmempool->obinfos == NULL) {
uint chunk_len = sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN;
DST.vmempool->obinfos = BLI_memblock_create_ex(sizeof(DRWObjectInfos), chunk_len);
}
if (DST.vmempool->cullstates == NULL) {
DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState));
uint chunk_len = sizeof(DRWCullingState) * DRW_RESOURCE_CHUNK_LEN;
DST.vmempool->cullstates = BLI_memblock_create_ex(sizeof(DRWCullingState), chunk_len);
}
if (DST.vmempool->shgroups == NULL) {
DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
}
if (DST.vmempool->uniforms == NULL) {
DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform));
DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniformChunk));
}
if (DST.vmempool->views == NULL) {
DST.vmempool->views = BLI_memblock_create(sizeof(DRWView));
}
if (DST.vmempool->passes == NULL) {
DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
uint chunk_len = sizeof(DRWPass) * DRW_RESOURCE_CHUNK_LEN;
DST.vmempool->passes = BLI_memblock_create_ex(sizeof(DRWPass), chunk_len);
}
if (DST.vmempool->images == NULL) {
DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
}
/* Alloc default unit state */
DST.unit_state = draw_unit_state_create();
DST.resource_handle = 0;
DST.pass_handle = 0;
draw_unit_state_create();
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
DRW_instance_data_list_reset(DST.idatalist);
@@ -674,8 +692,6 @@ static void drw_viewport_var_init(void)
DST.default_framebuffer = NULL;
DST.vmempool = NULL;
DST.unit_state = NULL;
}
DST.primary_view_ct = 0;
@@ -718,6 +734,10 @@ static void drw_viewport_var_init(void)
G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
}
if (DST.draw_list == NULL) {
DST.draw_list = GPU_draw_list_create(DRW_DRAWLIST_LEN);
}
memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data));
}
@@ -1101,7 +1121,7 @@ static void drw_engines_world_update(Scene *scene)
static void drw_engines_cache_populate(Object *ob)
{
DST.ob_state = NULL;
DST.ob_handle = 0;
/* HACK: DrawData is copied by COW from the duplicated object.
* This is valid for IDs that cannot be instantiated but this
@@ -2065,7 +2085,7 @@ void DRW_render_object_iter(
if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
DST.ob_state = NULL;
DST.ob_handle = 0;
drw_duplidata_load(DST.dupli_source);
if (!DST.dupli_source) {
@@ -2172,6 +2192,7 @@ void DRW_render_instance_buffer_finish(void)
BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!");
DST.buffer_finish_called = true;
DRW_instance_buffer_finish(DST.idatalist);
drw_resource_buffer_finish(DST.vmempool);
}
/**
@@ -2195,7 +2216,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
Object *obact = OBACT(view_layer);
Object *obedit = OBEDIT_FROM_OBACT(obact);
#ifndef USE_GPU_SELECT
UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
UNUSED_VARS(scene, view_layer, v3d, ar, rect);
#else
RegionView3D *rv3d = ar->regiondata;
@@ -2901,6 +2922,10 @@ void DRW_engines_free(void)
MEM_SAFE_FREE(DST.uniform_names.buffer);
if (DST.draw_list) {
GPU_draw_list_discard(DST.draw_list);
}
DRW_opengl_context_disable();
}

View File

@@ -28,8 +28,10 @@
#include "DRW_engine.h"
#include "DRW_render.h"
#include "BLI_assert.h"
#include "BLI_linklist.h"
#include "BLI_threads.h"
#include "BLI_memblock.h"
#include "GPU_batch.h"
#include "GPU_context.h"
@@ -43,6 +45,9 @@
/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
#define USE_GPU_SELECT
/* Use drawcall batching using instanced rendering. */
#define USE_BATCHING 1
// #define DRW_DEBUG_CULLING
#define DRW_DEBUG_USE_UNIFORM_NAME 0
#define DRW_UNIFORM_BUFFER_NAME 64
@@ -90,19 +95,6 @@
* > DRWUniform
*/
/* Used by DRWCallState.flag */
enum {
DRW_CALL_NEGSCALE = (1 << 1),
};
/* Used by DRWCallState.matflag */
enum {
DRW_CALL_MODELINVERSE = (1 << 0),
DRW_CALL_MODELVIEWPROJECTION = (1 << 1),
DRW_CALL_ORCOTEXFAC = (1 << 2),
DRW_CALL_OBJECTINFO = (1 << 3),
};
typedef struct DRWCullingState {
uint32_t mask;
/* Culling: Using Bounding Sphere for now for faster culling.
@@ -112,37 +104,151 @@ typedef struct DRWCullingState {
void *user_data;
} DRWCullingState;
typedef struct DRWCallState {
DRWCullingState *culling;
uchar flag;
uchar matflag; /* Which matrices to compute. */
short ob_index;
/* Matrices */
/* Minimum max UBO size is 64KiB. We take the largest
* UBO struct and alloc the max number.
* ((1 << 16) / sizeof(DRWObjectMatrix)) = 512
* Keep in sync with common_view_lib.glsl */
#define DRW_RESOURCE_CHUNK_LEN 512
/**
* Identifier used to sort similar drawcalls together.
* Also used to reference elements inside memory blocks.
*
* From MSB to LSB
* 1 bit for negative scale.
* 22 bits for chunk id.
* 9 bits for resource id inside the chunk. (can go up to 511)
* |-|----------------------|---------|
*
* Use manual bitsift and mask instead of bitfields to avoid
* compiler dependant behavior that would mess the ordering of
* the members thus changing the sorting order.
*/
typedef uint32_t DRWResourceHandle;
BLI_INLINE uint32_t DRW_handle_negative_scale_get(const DRWResourceHandle *handle)
{
return (*handle & 0x80000000) != 0;
}
BLI_INLINE uint32_t DRW_handle_chunk_get(const DRWResourceHandle *handle)
{
return (*handle & 0x7FFFFFFF) >> 9;
}
BLI_INLINE uint32_t DRW_handle_id_get(const DRWResourceHandle *handle)
{
return (*handle & 0x000001FF);
}
BLI_INLINE void DRW_handle_increment(DRWResourceHandle *handle)
{
*handle += 1;
}
BLI_INLINE void DRW_handle_negative_scale_enable(DRWResourceHandle *handle)
{
*handle |= 0x80000000;
}
BLI_INLINE void *DRW_memblock_elem_from_handle(struct BLI_memblock *memblock,
const DRWResourceHandle *handle)
{
int elem = DRW_handle_id_get(handle);
int chunk = DRW_handle_chunk_get(handle);
return BLI_memblock_elem_get(memblock, chunk, elem);
}
typedef struct DRWObjectMatrix {
float model[4][4];
float modelinverse[4][4];
float orcotexfac[2][3];
} DRWObjectMatrix;
typedef struct DRWObjectInfos {
float orcotexfac[2][4];
float ob_index;
float pad; /* UNUSED*/
float ob_random;
} DRWCallState;
float ob_neg_scale;
} DRWObjectInfos;
typedef struct DRWCall {
struct DRWCall *next;
DRWCallState *state;
BLI_STATIC_ASSERT_ALIGN(DRWObjectMatrix, 16)
BLI_STATIC_ASSERT_ALIGN(DRWObjectInfos, 16)
typedef enum {
/* Draw Commands */
DRW_CMD_DRAW = 0, /* Only sortable type. Must be 0. */
DRW_CMD_DRAW_RANGE = 1,
DRW_CMD_DRAW_INSTANCE = 2,
DRW_CMD_DRAW_PROCEDURAL = 3,
/* Other Commands */
DRW_CMD_DRWSTATE = 13,
DRW_CMD_STENCIL = 14,
DRW_CMD_SELECTID = 15,
/* Needs to fit in 4bits */
} eDRWCommandType;
#define DRW_MAX_DRAW_CMD_TYPE DRW_CMD_DRAW_PROCEDURAL
typedef struct DRWCommandDraw {
GPUBatch *batch;
DRWResourceHandle handle;
} DRWCommandDraw;
/* Assume DRWResourceHandle to be 0. */
typedef struct DRWCommandDrawRange {
GPUBatch *batch;
uint vert_first;
uint vert_count;
uint inst_count;
} DRWCommandDrawRange;
#ifdef USE_GPU_SELECT
/* TODO(fclem) remove once we have a dedicated selection engine. */
int select_id;
GPUVertBuf *inst_selectid;
#endif
} DRWCall;
typedef struct DRWCommandDrawInstance {
GPUBatch *batch;
DRWResourceHandle handle;
uint inst_count;
} DRWCommandDrawInstance;
typedef struct DRWCommandDrawProcedural {
GPUBatch *batch;
DRWResourceHandle handle;
uint vert_count;
} DRWCommandDrawProcedural;
typedef struct DRWCommandSetMutableState {
/** State changes (or'd or and'd with the pass's state) */
DRWState enable;
DRWState disable;
} DRWCommandSetMutableState;
typedef struct DRWCommandSetStencil {
uint mask;
} DRWCommandSetStencil;
typedef struct DRWCommandSetSelectID {
GPUVertBuf *select_buf;
uint select_id;
} DRWCommandSetSelectID;
typedef union DRWCommand {
DRWCommandDraw draw;
DRWCommandDrawRange range;
DRWCommandDrawInstance instance;
DRWCommandDrawProcedural procedural;
DRWCommandSetMutableState state;
DRWCommandSetStencil stencil;
DRWCommandSetSelectID select_id;
} DRWCommand;
/* Used for agregating calls into GPUVertBufs. */
struct DRWCallBuffer {
GPUVertBuf *buf;
GPUVertBuf *buf_select;
int count;
};
/* Used by DRWUniform.type */
typedef enum {
DRW_UNIFORM_INT,
DRW_UNIFORM_INT = 0,
DRW_UNIFORM_INT_COPY,
DRW_UNIFORM_FLOAT,
DRW_UNIFORM_FLOAT_COPY,
@@ -151,54 +257,56 @@ typedef enum {
DRW_UNIFORM_TEXTURE_REF,
DRW_UNIFORM_BLOCK,
DRW_UNIFORM_BLOCK_PERSIST,
DRW_UNIFORM_TFEEDBACK_TARGET,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
DRW_UNIFORM_RESOURCE_CHUNK,
/** Legacy / Fallback */
DRW_UNIFORM_BASE_INSTANCE,
DRW_UNIFORM_MODEL_MATRIX,
DRW_UNIFORM_MODEL_MATRIX_INVERSE,
DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX,
/* WARNING: set DRWUniform->type
* bit length accordingly. */
} DRWUniformType;
struct DRWUniform {
DRWUniform *next; /* single-linked list */
union {
/* For reference or array/vector types. */
const void *pvalue;
/* Single values. */
float fvalue[2];
int ivalue[2];
float fvalue[4];
int ivalue[4];
};
int name_ofs; /* name offset in name buffer. */
int location;
char type; /* DRWUniformType */
char length; /* cannot be more than 16 */
char arraysize; /* cannot be more than 16 too */
uint32_t type : 5; /* DRWUniformType */
uint32_t length : 5; /* cannot be more than 16 */
uint32_t arraysize : 5; /* cannot be more than 16 too */
uint32_t name_ofs : 17; /* name offset in name buffer. */
};
struct DRWShadingGroup {
DRWShadingGroup *next;
GPUShader *shader; /* Shader to bind */
DRWUniform *uniforms; /* Uniforms pointers */
GPUShader *shader; /* Shader to bind */
struct DRWUniformChunk *uniforms; /* Uniforms pointers */
struct {
DRWCall *first, *last; /* Linked list of DRWCall */
} calls;
/* Chunks of draw calls. */
struct DRWCommandChunk *first, *last;
} cmd;
/** TODO Maybe remove from here */
struct GPUVertBuf *tfeedback_target;
/** State changes for this batch only (or'd with the pass's state) */
DRWState state_extra;
/** State changes for this batch only (and'd with the pass's state) */
DRWState state_extra_disable;
/** Stencil mask to use for stencil test / write operations */
uint stencil_mask;
/* Builtin matrices locations */
int model;
int modelinverse;
int modelviewprojection;
int orcotexfac;
int callid;
int objectinfo;
uchar matflag; /* Matrices needed, same as DRWCall.flag */
DRWPass *pass_parent; /* backlink to pass we're in */
union {
struct {
int objectinfo; /* Equal to 1 if the shader needs obinfos. */
DRWResourceHandle pass_handle; /* Memblock key to parent pass. */
};
struct {
float distance; /* Distance from camera. */
uint original_index; /* Original position inside the shgroup list. */
} z_sorting;
};
};
#define MAX_PASS_NAME 32
@@ -210,6 +318,7 @@ struct DRWPass {
DRWShadingGroup *last;
} shgroups;
DRWResourceHandle handle;
DRWState state;
char name[MAX_PASS_NAME];
};
@@ -229,6 +338,8 @@ typedef struct DRWViewUboStorage {
float viewcamtexcofac[4];
} DRWViewUboStorage;
BLI_STATIC_ASSERT_ALIGN(DRWViewUboStorage, 16)
#define MAX_CULLED_VIEWS 32
struct DRWView {
@@ -250,13 +361,45 @@ struct DRWView {
void *user_data;
};
/* TODO(fclem): Future awaits */
#if 0
typedef struct ModelUboStorage {
float model[4][4];
float modelinverse[4][4];
} ModelUboStorage;
#endif
/* ------------ Data Chunks --------------- */
/**
* In order to keep a cache friendly data structure,
* we alloc most of our little data into chunks of multiple item.
* Iteration, allocation and memory usage are better.
* We loose a bit of memory by allocating more than what we need
* but it's counterbalanced by not needing the linked-list pointers
* for each item.
**/
typedef struct DRWUniformChunk {
struct DRWUniformChunk *next; /* single-linked list */
uint32_t uniform_len;
uint32_t uniform_used;
DRWUniform uniforms[10];
} DRWUniformChunk;
typedef struct DRWCommandChunk {
struct DRWCommandChunk *next;
uint32_t command_len;
uint32_t command_used;
/* 4bits for each command. */
uint64_t command_type[6];
/* -- 64 bytes aligned -- */
DRWCommand commands[96];
/* -- 64 bytes aligned -- */
} DRWCommandChunk;
typedef struct DRWCommandSmallChunk {
struct DRWCommandChunk *next;
uint32_t command_len;
uint32_t command_used;
/* 4bits for each command. */
/* TODO reduce size of command_type. */
uint64_t command_type[6];
DRWCommand commands[6];
} DRWCommandSmallChunk;
BLI_STATIC_ASSERT_ALIGN(DRWCommandChunk, 16);
/* ------------- DRAW DEBUG ------------ */
@@ -277,21 +420,31 @@ typedef struct DRWDebugSphere {
#define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
#define STENCIL_UNDEFINED 256
#define DRW_DRAWLIST_LEN 256
typedef struct DRWManager {
/* TODO clean up this struct a bit */
/* Cache generation */
ViewportMemoryPool *vmempool;
DRWInstanceDataList *idatalist;
DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
/* Default Unit model matrix state without culling. */
DRWCallState *unit_state;
/* State of the object being evaluated if already allocated. */
DRWCallState *ob_state;
DRWResourceHandle ob_handle;
/** True if current DST.ob_state has its matching DRWObjectInfos init. */
bool ob_state_obinfo_init;
/** Handle of current object resource in object resource arrays (DRWObjectMatrices/Infos). */
DRWResourceHandle resource_handle;
/** Handle of next DRWPass to be allocated. */
DRWResourceHandle pass_handle;
/** Dupli state. NULL if not dupli. */
struct DupliObject *dupli_source;
struct Object *dupli_parent;
struct Object *dupli_origin;
/** Ghash containing original objects. */
struct GHash *dupli_ghash;
void **dupli_datas; /* Array of dupli_data (one for each enabled engine) to handle duplis. */
/** TODO(fclem) try to remove usage of this. */
DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
/* Array of dupli_data (one for each enabled engine) to handle duplis. */
void **dupli_datas;
/* Rendering state */
GPUShader *shader;
@@ -354,6 +507,8 @@ typedef struct DRWManager {
/** Mutex to lock the drw manager and avoid concurrent context usage. */
TicketMutex *gl_context_mutex;
GPUDrawList *draw_list;
/** GPU Resource State: Memory storage between drawing. */
struct {
/* High end GPUs supports up to 32 binds per shader stage.
@@ -394,9 +549,13 @@ void drw_state_set(DRWState state);
void drw_debug_draw(void);
void drw_debug_init(void);
eDRWCommandType command_type_get(uint64_t *command_type_bits, int index);
void drw_batch_cache_validate(Object *ob);
void drw_batch_cache_generate_requested(struct Object *ob);
void drw_resource_buffer_finish(ViewportMemoryPool *vmempool);
/* Procedural Drawing */
GPUBatch *drw_cache_procedural_points_get(void);
GPUBatch *drw_cache_procedural_lines_get(void);

File diff suppressed because it is too large Load Diff

View File

@@ -37,16 +37,41 @@
# include "GPU_select.h"
#endif
#ifdef USE_GPU_SELECT
void DRW_select_load_id(uint id)
{
#ifdef USE_GPU_SELECT
BLI_assert(G.f & G_FLAG_PICKSEL);
DST.select_id = id;
}
#endif
}
#define DEBUG_UBO_BINDING
typedef struct DRWCommandsState {
GPUBatch *batch;
int resource_chunk;
int base_inst;
int inst_count;
int v_first;
int v_count;
bool neg_scale;
/* Resource location. */
int obmats_loc;
int obinfos_loc;
int baseinst_loc;
int chunkid_loc;
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
int mvp_loc;
/* Selection ID state. */
GPUVertBuf *select_buf;
uint select_id;
/* Drawing State */
DRWState drw_state_enabled;
DRWState drw_state_disabled;
} DRWCommandsState;
/* -------------------------------------------------------------------- */
/** \name Draw State (DRW_state)
* \{ */
@@ -391,9 +416,10 @@ void DRW_state_reset(void)
/** \name Culling (DRW_culling)
* \{ */
static bool draw_call_is_culled(DRWCall *call, DRWView *view)
static bool draw_call_is_culled(const DRWResourceHandle *handle, DRWView *view)
{
return (call->state->culling->mask & view->culling_mask) != 0;
DRWCullingState *culling = DRW_memblock_elem_from_handle(DST.vmempool->cullstates, handle);
return (culling->mask & view->culling_mask) != 0;
}
/* Set active view for rendering. */
@@ -572,62 +598,96 @@ static void draw_compute_culling(DRWView *view)
/** \name Draw (DRW_draw)
* \{ */
static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
DRWResourceHandle *handle,
float obmat_loc,
float obinv_loc,
float mvp_loc)
{
BLI_assert(call);
DRWCallState *state = call->state;
if (shgroup->model != -1) {
GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
/* Still supported for compatibility with gpu_shader_* but should be forbidden. */
DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle);
if (obmat_loc != -1) {
GPU_shader_uniform_vector(shgroup->shader, obmat_loc, 16, 1, (float *)ob_mats->model);
}
if (shgroup->modelinverse != -1) {
GPU_shader_uniform_vector(
shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
}
if (shgroup->objectinfo != -1) {
float infos[4];
infos[0] = state->ob_index;
// infos[1]; /* UNUSED. */
infos[2] = state->ob_random;
infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos);
}
if (shgroup->orcotexfac != -1) {
GPU_shader_uniform_vector(
shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
if (obinv_loc != -1) {
GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse);
}
/* Still supported for compatibility with gpu_shader_* but should be forbidden
* and is slow (since it does not cache the result). */
if (shgroup->modelviewprojection != -1) {
if (mvp_loc != -1) {
float mvp[4][4];
mul_m4_m4m4(mvp, DST.view_active->storage.persmat, state->model);
GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)mvp);
mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model);
GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp);
}
}
BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom)
{
/* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
if (DST.batch) {
DST.batch->program_in_use = false;
}
DST.batch = geom;
GPU_batch_program_set_no_use(
geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
geom->program_in_use = true;
GPU_batch_bind(geom);
}
BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup,
GPUBatch *geom,
uint vert_first,
uint vert_count,
uint inst_first,
uint inst_count)
int vert_first,
int vert_count,
int inst_first,
int inst_count,
int baseinst_loc)
{
/* bind vertex array */
if (DST.batch != geom) {
DST.batch = geom;
/* inst_count can be -1. */
inst_count = max_ii(0, inst_count);
GPU_batch_program_set_no_use(
geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
GPU_batch_bind(geom);
if (baseinst_loc != -1) {
/* Fallback when ARB_shader_draw_parameters is not supported. */
GPU_shader_uniform_vector_int(shgroup->shader, baseinst_loc, 1, 1, (int *)&inst_first);
/* Avoids VAO reconfiguration on older hardware. (see GPU_batch_draw_advanced) */
inst_first = 0;
}
/* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
geom->program_in_use = true;
/* bind vertex array */
if (DST.batch != geom) {
draw_geometry_bind(shgroup, geom);
}
GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count);
}
geom->program_in_use = false; /* XXX hacking gawain */
BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *state)
{
if (state->inst_count == 0) {
return;
}
if (state->baseinst_loc == -1) {
/* bind vertex array */
if (DST.batch != state->batch) {
GPU_draw_list_submit(DST.draw_list);
draw_geometry_bind(shgroup, state->batch);
}
GPU_draw_list_command_add(
DST.draw_list, state->v_first, state->v_count, state->base_inst, state->inst_count);
}
/* Fallback when unsupported */
else {
draw_geometry_execute(shgroup,
state->batch,
state->v_first,
state->v_count,
state->base_inst,
state->inst_count,
state->baseinst_loc);
}
}
enum {
@@ -699,6 +759,9 @@ static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
/* UBO isn't bound yet. Find an empty slot and bind it. */
idx = get_empty_slot_index(DST.RST.bound_ubo_slots);
/* [0..1] are reserved ubo slots. */
idx += 2;
if (idx < GPU_max_ubo_binds()) {
GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx];
/* Unbind any previous UBO. */
@@ -718,10 +781,13 @@ static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
}
}
else {
BLI_assert(idx < 64);
/* This UBO slot was released but the UBO is
* still bound here. Just flag the slot again. */
BLI_assert(DST.RST.bound_ubos[idx] == ubo);
}
/* Remove offset for flag bitfield. */
idx -= 2;
set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type);
}
@@ -765,8 +831,12 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
printf("Trying to draw with missing UBO binding.\n");
valid = false;
}
DRWPass *parent_pass = DRW_memblock_elem_from_handle(DST.vmempool->passes,
&shgroup->pass_handle);
printf("Pass : %s, Shader : %s, Block : %s\n",
shgroup->pass_parent->name,
parent_pass->name,
shgroup->shader->name,
blockname);
}
@@ -798,119 +868,330 @@ static void release_ubo_slots(bool with_persist)
}
}
static void draw_update_uniforms(DRWShadingGroup *shgroup)
static void draw_update_uniforms(DRWShadingGroup *shgroup,
DRWCommandsState *state,
bool *use_tfeedback)
{
for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
GPUTexture *tex;
GPUUniformBuffer *ubo;
if (uni->location == -2) {
uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
DST.uniform_names.buffer + uni->name_ofs);
if (uni->location == -1) {
continue;
for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) {
DRWUniform *uni = unichunk->uniforms;
for (int i = 0; i < unichunk->uniform_used; i++, uni++) {
GPUTexture *tex;
GPUUniformBuffer *ubo;
if (uni->location == -2) {
uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
DST.uniform_names.buffer + uni->name_ofs);
if (uni->location == -1) {
continue;
}
}
const void *data = uni->pvalue;
if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
data = uni->fvalue;
}
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_FLOAT_COPY:
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_TEXTURE:
tex = (GPUTexture *)uni->pvalue;
BLI_assert(tex);
bind_texture(tex, BIND_TEMP);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_TEXTURE_PERSIST:
tex = (GPUTexture *)uni->pvalue;
BLI_assert(tex);
bind_texture(tex, BIND_PERSIST);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_TEXTURE_REF:
tex = *((GPUTexture **)uni->pvalue);
BLI_assert(tex);
bind_texture(tex, BIND_TEMP);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BLOCK:
ubo = (GPUUniformBuffer *)uni->pvalue;
bind_ubo(ubo, BIND_TEMP);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
case DRW_UNIFORM_BLOCK_PERSIST:
ubo = (GPUUniformBuffer *)uni->pvalue;
bind_ubo(ubo, BIND_PERSIST);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
case DRW_UNIFORM_BLOCK_OBMATS:
state->obmats_loc = uni->location;
ubo = DST.vmempool->matrices_ubo[0];
GPU_uniformbuffer_bind(ubo, 0);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
case DRW_UNIFORM_BLOCK_OBINFOS:
state->obinfos_loc = uni->location;
ubo = DST.vmempool->obinfos_ubo[0];
GPU_uniformbuffer_bind(ubo, 1);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
GPU_shader_uniform_int(shgroup->shader, uni->location, 0);
break;
case DRW_UNIFORM_TFEEDBACK_TARGET:
BLI_assert(data && (*use_tfeedback == false));
*use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
((GPUVertBuf *)data)->vbo_id);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
state->baseinst_loc = uni->location;
break;
case DRW_UNIFORM_MODEL_MATRIX:
state->obmat_loc = uni->location;
break;
case DRW_UNIFORM_MODEL_MATRIX_INVERSE:
state->obinv_loc = uni->location;
break;
case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX:
state->mvp_loc = uni->location;
break;
}
}
const void *data = uni->pvalue;
if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
data = uni->fvalue;
}
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_FLOAT_COPY:
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_TEXTURE:
tex = (GPUTexture *)uni->pvalue;
BLI_assert(tex);
bind_texture(tex, BIND_TEMP);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_TEXTURE_PERSIST:
tex = (GPUTexture *)uni->pvalue;
BLI_assert(tex);
bind_texture(tex, BIND_PERSIST);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_TEXTURE_REF:
tex = *((GPUTexture **)uni->pvalue);
BLI_assert(tex);
bind_texture(tex, BIND_TEMP);
GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BLOCK:
ubo = (GPUUniformBuffer *)uni->pvalue;
bind_ubo(ubo, BIND_TEMP);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
case DRW_UNIFORM_BLOCK_PERSIST:
ubo = (GPUUniformBuffer *)uni->pvalue;
bind_ubo(ubo, BIND_PERSIST);
GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
break;
}
}
BLI_assert(ubo_bindings_validate(shgroup));
}
BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call)
BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup,
DRWCommandsState *state,
GPUBatch *batch,
const DRWResourceHandle *handle)
{
#ifdef USE_GPU_SELECT
if ((G.f & G_FLAG_PICKSEL) == 0) {
return false;
}
if (call->inst_selectid != NULL) {
const bool is_instancing = (call->inst_count != 0);
uint start = 0;
uint count = 1;
uint tot = is_instancing ? call->inst_count : call->vert_count;
/* Hack : get vbo data without actually drawing. */
GPUVertBufRaw raw;
GPU_vertbuf_attr_get_raw_data(call->inst_selectid, 0, &raw);
int *select_id = GPU_vertbuf_raw_step(&raw);
const bool is_instancing = (batch->inst != NULL);
int start = 0;
int count = 1;
int tot = is_instancing ? batch->inst->vertex_len : batch->verts[0]->vertex_len;
/* Hack : get "vbo" data without actually drawing. */
int *select_id = (void *)state->select_buf->data;
/* Batching */
if (!is_instancing) {
/* FIXME: Meh a bit nasty. */
if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) {
count = 3;
}
else if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) {
count = 2;
/* Batching */
if (!is_instancing) {
/* FIXME: Meh a bit nasty. */
if (batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) {
count = 3;
}
else if (batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) {
count = 2;
}
}
while (start < tot) {
GPU_select_load_id(select_id[start]);
if (is_instancing) {
draw_geometry_execute(shgroup, batch, 0, 0, start, count, state->baseinst_loc);
}
else {
draw_geometry_execute(
shgroup, batch, start, count, DRW_handle_id_get(handle), 0, state->baseinst_loc);
}
start += count;
}
}
typedef struct DRWCommandIterator {
int cmd_index;
DRWCommandChunk *curr_chunk;
} DRWCommandIterator;
static void draw_command_iter_begin(DRWCommandIterator *iter, DRWShadingGroup *shgroup)
{
iter->curr_chunk = shgroup->cmd.first;
iter->cmd_index = 0;
}
static DRWCommand *draw_command_iter_step(DRWCommandIterator *iter, eDRWCommandType *cmd_type)
{
if (iter->curr_chunk) {
if (iter->cmd_index == iter->curr_chunk->command_len) {
iter->curr_chunk = iter->curr_chunk->next;
iter->cmd_index = 0;
}
if (iter->curr_chunk) {
*cmd_type = command_type_get(iter->curr_chunk->command_type, iter->cmd_index);
if (iter->cmd_index < iter->curr_chunk->command_used) {
return iter->curr_chunk->commands + iter->cmd_index++;
}
}
while (start < tot) {
GPU_select_load_id(select_id[start]);
if (is_instancing) {
draw_geometry_execute(shgroup, call->batch, 0, 0, start, count);
}
else {
draw_geometry_execute(shgroup, call->batch, start, count, 0, 0);
}
start += count;
}
return true;
}
return NULL;
}
static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHandle *handle)
{
/* Front face is not a resource but it is inside the resource handle. */
bool neg_scale = DRW_handle_negative_scale_get(handle);
if (neg_scale != state->neg_scale) {
glFrontFace((neg_scale) ? GL_CW : GL_CCW);
state->neg_scale = neg_scale;
}
int chunk = DRW_handle_chunk_get(handle);
if (state->resource_chunk != chunk) {
if (state->chunkid_loc != -1) {
GPU_shader_uniform_int(NULL, state->chunkid_loc, chunk);
}
if (state->obmats_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]);
GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0);
}
if (state->obinfos_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[chunk], 1);
}
state->resource_chunk = chunk;
}
}
static void draw_call_batching_flush(DRWShadingGroup *shgroup, DRWCommandsState *state)
{
draw_indirect_call(shgroup, state);
GPU_draw_list_submit(DST.draw_list);
state->batch = NULL;
state->inst_count = 0;
state->base_inst = -1;
}
static void draw_call_single_do(DRWShadingGroup *shgroup,
DRWCommandsState *state,
GPUBatch *batch,
DRWResourceHandle handle,
int vert_first,
int vert_count,
int inst_count)
{
draw_call_batching_flush(shgroup, state);
draw_call_resource_bind(state, &handle);
/* TODO This is Legacy. Need to be removed. */
if (state->obmats_loc == -1 &&
(state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) {
draw_legacy_matrix_update(
shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc);
}
if (G.f & G_FLAG_PICKSEL) {
if (state->select_buf != NULL) {
draw_select_buffer(shgroup, state, batch, &handle);
return;
}
else {
GPU_select_load_id(state->select_id);
}
}
draw_geometry_execute(shgroup,
batch,
vert_first,
vert_count,
DRW_handle_id_get(&handle),
inst_count,
state->baseinst_loc);
}
static void draw_call_batching_start(DRWCommandsState *state)
{
state->neg_scale = false;
state->resource_chunk = 0;
state->base_inst = 0;
state->inst_count = 0;
state->v_first = 0;
state->v_count = 0;
state->batch = NULL;
state->select_id = -1;
state->select_buf = NULL;
}
static void draw_call_batching_do(DRWShadingGroup *shgroup,
DRWCommandsState *state,
DRWCommandDraw *call)
{
/* If any condition requires to interupt the merging. */
bool neg_scale = DRW_handle_negative_scale_get(&call->handle);
int chunk = DRW_handle_chunk_get(&call->handle);
int id = DRW_handle_id_get(&call->handle);
if ((state->neg_scale != neg_scale) || /* Need to change state. */
(state->resource_chunk != chunk) || /* Need to change UBOs. */
(state->batch != call->batch) /* Need to change VAO. */
) {
draw_call_batching_flush(shgroup, state);
state->batch = call->batch;
state->v_first = (call->batch->elem) ? call->batch->elem->index_start : 0;
state->v_count = (call->batch->elem) ? call->batch->elem->index_len :
call->batch->verts[0]->vertex_len;
state->inst_count = 1;
state->base_inst = id;
draw_call_resource_bind(state, &call->handle);
GPU_draw_list_init(DST.draw_list, state->batch);
}
/* Is the id consecutive? */
else if (id != state->base_inst + state->inst_count) {
/* We need to add a draw command for the pending instances. */
draw_indirect_call(shgroup, state);
state->inst_count = 1;
state->base_inst = id;
}
/* We avoid a drawcall by merging with the precedent
* drawcall using instancing. */
else {
GPU_select_load_id(call->select_id);
return false;
state->inst_count++;
}
}
/* Flush remaining pending drawcalls. */
static void draw_call_batching_finish(DRWShadingGroup *shgroup, DRWCommandsState *state)
{
draw_call_batching_flush(shgroup, state);
/* Reset state */
if (state->neg_scale) {
glFrontFace(GL_CCW);
}
if (state->obmats_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]);
}
if (state->obinfos_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
}
#else
return false;
#endif
}
static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
{
BLI_assert(shgroup->shader);
DRWCommandsState state = {
.obmats_loc = -1,
.obinfos_loc = -1,
.baseinst_loc = -1,
.chunkid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
.mvp_loc = -1,
.drw_state_enabled = 0,
.drw_state_disabled = ~0x0,
};
const bool shader_changed = (DST.shader != shgroup->shader);
bool use_tfeedback = false;
@@ -920,56 +1201,100 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
}
GPU_shader_bind(shgroup->shader);
DST.shader = shgroup->shader;
/* XXX hacking gawain */
if (DST.batch) {
DST.batch->program_in_use = false;
}
DST.batch = NULL;
}
if (shgroup->tfeedback_target != NULL) {
use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
shgroup->tfeedback_target->vbo_id);
}
release_ubo_slots(shader_changed);
release_texture_slots(shader_changed);
drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
drw_stencil_set(shgroup->stencil_mask);
draw_update_uniforms(shgroup, &state, &use_tfeedback);
draw_update_uniforms(shgroup);
drw_state_set(pass_state);
/* Rendering Calls */
{
bool prev_neg_scale = false;
int callid = 0;
for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
DRWCommandIterator iter;
DRWCommand *cmd;
eDRWCommandType cmd_type;
if (draw_call_is_culled(call, DST.view_active)) {
continue;
draw_command_iter_begin(&iter, shgroup);
draw_call_batching_start(&state);
while ((cmd = draw_command_iter_step(&iter, &cmd_type))) {
switch (cmd_type) {
case DRW_CMD_DRWSTATE:
case DRW_CMD_STENCIL:
draw_call_batching_flush(shgroup, &state);
break;
case DRW_CMD_DRAW:
case DRW_CMD_DRAW_PROCEDURAL:
case DRW_CMD_DRAW_INSTANCE:
if (draw_call_is_culled(&cmd->instance.handle, DST.view_active)) {
continue;
}
break;
default:
break;
}
/* XXX small exception/optimisation for outline rendering. */
if (shgroup->callid != -1) {
GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid);
callid += 1;
switch (cmd_type) {
case DRW_CMD_DRWSTATE:
state.drw_state_enabled |= cmd->state.enable;
state.drw_state_disabled &= ~cmd->state.disable;
drw_state_set((pass_state & state.drw_state_disabled) | state.drw_state_enabled);
break;
case DRW_CMD_STENCIL:
drw_stencil_set(cmd->stencil.mask);
break;
case DRW_CMD_SELECTID:
state.select_id = cmd->select_id.select_id;
state.select_buf = cmd->select_id.select_buf;
break;
case DRW_CMD_DRAW:
if (!USE_BATCHING || state.obmats_loc == -1 || (G.f & G_FLAG_PICKSEL)) {
draw_call_single_do(shgroup, &state, cmd->draw.batch, cmd->draw.handle, 0, 0, 0);
}
else {
draw_call_batching_do(shgroup, &state, &cmd->draw);
}
break;
case DRW_CMD_DRAW_PROCEDURAL:
draw_call_single_do(shgroup,
&state,
cmd->procedural.batch,
cmd->procedural.handle,
0,
cmd->procedural.vert_count,
1);
break;
case DRW_CMD_DRAW_INSTANCE:
draw_call_single_do(shgroup,
&state,
cmd->instance.batch,
cmd->instance.handle,
0,
0,
cmd->instance.inst_count);
break;
case DRW_CMD_DRAW_RANGE:
draw_call_single_do(shgroup,
&state,
cmd->range.batch,
(DRWResourceHandle)0,
cmd->range.vert_first,
cmd->range.vert_count,
1);
break;
}
/* Negative scale objects */
bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE;
if (neg_scale != prev_neg_scale) {
glFrontFace((neg_scale) ? GL_CW : GL_CCW);
prev_neg_scale = neg_scale;
}
draw_geometry_prepare(shgroup, call);
if (draw_select_do_call(shgroup, call)) {
continue;
}
draw_geometry_execute(
shgroup, call->batch, call->vert_first, call->vert_count, 0, call->inst_count);
}
/* Reset state */
glFrontFace(GL_CCW);
draw_call_batching_finish(shgroup, &state);
}
if (use_tfeedback) {
@@ -1045,6 +1370,11 @@ static void drw_draw_pass_ex(DRWPass *pass,
DST.shader = NULL;
}
if (DST.batch) {
DST.batch->program_in_use = false;
DST.batch = NULL;
}
/* HACK: Rasterized discard can affect clear commands which are not
* part of a DRWPass (as of now). So disable rasterized discard here
* if it has been enabled. */

View File

@@ -126,7 +126,7 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
datatoc_edit_curve_overlay_normals_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define IN_PLACE_INSTANCES\n", NULL},
});
}

View File

@@ -285,15 +285,10 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *outlines_transform;
/* Lightprobes */
DRWCallBuffer *lightprobes_cube_select;
DRWCallBuffer *lightprobes_cube_select_dupli;
DRWCallBuffer *lightprobes_cube_active;
DRWCallBuffer *lightprobes_cube_transform;
DRWCallBuffer *lightprobes_planar_select;
DRWCallBuffer *lightprobes_planar_select_dupli;
DRWCallBuffer *lightprobes_planar_active;
DRWCallBuffer *lightprobes_planar_transform;
DRWShadingGroup *probe_outlines_transform;
DRWShadingGroup *probe_outlines_select;
DRWShadingGroup *probe_outlines_select_dupli;
DRWShadingGroup *probe_outlines_active;
/* Objects Centers */
DRWCallBuffer *center_active;
@@ -302,17 +297,6 @@ typedef struct OBJECT_PrivateData {
DRWCallBuffer *center_selected_lib;
DRWCallBuffer *center_deselected_lib;
/* Outlines id offset (accessed as an array) */
int id_ofs_active;
int id_ofs_select;
int id_ofs_select_dupli;
int id_ofs_transform;
int id_ofs_prb_active;
int id_ofs_prb_select;
int id_ofs_prb_select_dupli;
int id_ofs_prb_transform;
bool xray_enabled;
bool xray_enabled_and_not_wire;
} OBJECT_PrivateData; /* Transient data */
@@ -415,7 +399,10 @@ static void OBJECT_engine_init(void *vedata)
if (!sh_data->outline_resolve) {
/* Outline */
sh_data->outline_prepass = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL},
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_view_lib_glsl,
datatoc_object_outline_prepass_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -429,7 +416,7 @@ static void OBJECT_engine_init(void *vedata)
datatoc_object_outline_prepass_geom_glsl,
NULL},
.frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL},
});
sh_data->outline_resolve = DRW_shader_create_fullscreen(
@@ -537,10 +524,11 @@ static void OBJECT_engine_init(void *vedata)
/* Lightprobes */
sh_data->lightprobe_grid = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_view_lib_glsl,
datatoc_common_globals_lib_glsl,
datatoc_object_lightprobe_grid_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_gpu_shader_flat_id_frag_glsl, NULL},
.frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -723,12 +711,12 @@ static void OBJECT_engine_free(void)
}
static DRWShadingGroup *shgroup_outline(DRWPass *pass,
const int *ofs,
int outline_id,
GPUShader *sh,
eGPUShaderConfig sh_cfg)
{
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_int(grp, "baseId", ofs, 1);
DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
@@ -767,107 +755,10 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass,
return grp;
}
static int *shgroup_theme_id_to_probe_outline_counter(OBJECT_StorageList *stl,
int theme_id,
const int base_flag)
{
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return &stl->g_data->id_ofs_prb_select_dupli;
case TH_TRANSFORM:
default:
return &stl->g_data->id_ofs_prb_transform;
}
}
switch (theme_id) {
case TH_ACTIVE:
return &stl->g_data->id_ofs_prb_active;
case TH_SELECT:
return &stl->g_data->id_ofs_prb_select;
case TH_TRANSFORM:
default:
return &stl->g_data->id_ofs_prb_transform;
}
}
static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl,
int theme_id,
const int base_flag)
{
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return &stl->g_data->id_ofs_select_dupli;
case TH_TRANSFORM:
default:
return &stl->g_data->id_ofs_transform;
}
}
switch (theme_id) {
case TH_ACTIVE:
return &stl->g_data->id_ofs_active;
case TH_SELECT:
return &stl->g_data->id_ofs_select;
case TH_TRANSFORM:
default:
return &stl->g_data->id_ofs_transform;
}
}
static DRWCallBuffer *buffer_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl,
int theme_id)
{
/* does not increment counter */
switch (theme_id) {
case TH_ACTIVE:
return stl->g_data->lightprobes_planar_active;
case TH_SELECT:
return stl->g_data->lightprobes_planar_select;
case TH_TRANSFORM:
default:
return stl->g_data->lightprobes_planar_transform;
}
}
static DRWCallBuffer *buffer_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl,
int theme_id,
const int base_flag)
{
/* does not increment counter */
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return stl->g_data->lightprobes_cube_select_dupli;
case TH_TRANSFORM:
default:
return stl->g_data->lightprobes_cube_transform;
}
}
switch (theme_id) {
case TH_ACTIVE:
return stl->g_data->lightprobes_cube_active;
case TH_SELECT:
return stl->g_data->lightprobes_cube_select;
case TH_TRANSFORM:
default:
return stl->g_data->lightprobes_cube_transform;
}
}
static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OBJECT_StorageList *stl,
int theme_id,
const int base_flag)
{
int *counter = shgroup_theme_id_to_outline_counter(stl, theme_id, base_flag);
*counter += 1;
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
@@ -892,6 +783,64 @@ static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OBJECT_StorageList *
}
}
static DRWShadingGroup *shgroup_theme_id_to_probe_outline_or_null(OBJECT_StorageList *stl,
int theme_id,
const int base_flag)
{
if (UNLIKELY(DRW_state_is_select())) {
return stl->g_data->probe_outlines_select;
}
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return stl->g_data->probe_outlines_select_dupli;
case TH_TRANSFORM:
return stl->g_data->probe_outlines_transform;
default:
return NULL;
}
}
switch (theme_id) {
case TH_ACTIVE:
return stl->g_data->probe_outlines_active;
case TH_SELECT:
return stl->g_data->probe_outlines_select;
case TH_TRANSFORM:
return stl->g_data->probe_outlines_transform;
default:
return NULL;
}
}
static int shgroup_theme_id_to_outline_id(int theme_id, const int base_flag)
{
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return 2;
case TH_TRANSFORM:
return 0;
default:
return -1;
}
}
switch (theme_id) {
case TH_ACTIVE:
return 3;
case TH_SELECT:
return 1;
case TH_TRANSFORM:
return 0;
default:
return -1;
}
}
static DRWShadingGroup *shgroup_theme_id_to_wire(OBJECT_ShadingGroupList *sgl,
int theme_id,
const short base_flag)
@@ -1372,7 +1321,8 @@ static void OBJECT_cache_init(void *vedata)
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
OBJECT_PrivateData *g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
eGPUShaderConfig cfg = draw_ctx->sh_cfg;
OBJECT_Shaders *sh_data = &e_data.sh_data[cfg];
const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH);
const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f);
@@ -1393,59 +1343,25 @@ static void OBJECT_cache_init(void *vedata)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
psl->outlines = DRW_pass_create("Outlines Depth Pass", state);
psl->lightprobes = DRW_pass_create("Outlines Probe Pass", state);
GPUShader *sh = sh_data->outline_prepass;
g_data->probe_outlines_transform = shgroup_outline(psl->lightprobes, 0, sh, cfg);
g_data->probe_outlines_select = shgroup_outline(psl->lightprobes, 1, sh, cfg);
g_data->probe_outlines_select_dupli = shgroup_outline(psl->lightprobes, 2, sh, cfg);
g_data->probe_outlines_active = shgroup_outline(psl->lightprobes, 3, sh, cfg);
psl->outlines = DRW_pass_create("Outlines Depth Pass", state);
if (g_data->xray_enabled_and_not_wire) {
sh = sh_data->outline_prepass_wire;
}
g_data->outlines_select = shgroup_outline(
psl->outlines, &g_data->id_ofs_select, sh, draw_ctx->sh_cfg);
g_data->outlines_select_dupli = shgroup_outline(
psl->outlines, &g_data->id_ofs_select_dupli, sh, draw_ctx->sh_cfg);
g_data->outlines_transform = shgroup_outline(
psl->outlines, &g_data->id_ofs_transform, sh, draw_ctx->sh_cfg);
g_data->outlines_active = shgroup_outline(
psl->outlines, &g_data->id_ofs_active, sh, draw_ctx->sh_cfg);
g_data->id_ofs_select = 0;
g_data->id_ofs_select_dupli = 0;
g_data->id_ofs_active = 0;
g_data->id_ofs_transform = 0;
}
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state);
struct GPUBatch *sphere = DRW_cache_sphere_get();
struct GPUBatch *quad = DRW_cache_quad_get();
/* Cubemap */
g_data->lightprobes_cube_select = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_select, draw_ctx->sh_cfg);
g_data->lightprobes_cube_select_dupli = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_select_dupli, draw_ctx->sh_cfg);
g_data->lightprobes_cube_active = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_active, draw_ctx->sh_cfg);
g_data->lightprobes_cube_transform = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_transform, draw_ctx->sh_cfg);
/* Planar */
g_data->lightprobes_planar_select = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_select, draw_ctx->sh_cfg);
g_data->lightprobes_planar_select_dupli = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_select_dupli, draw_ctx->sh_cfg);
g_data->lightprobes_planar_active = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_active, draw_ctx->sh_cfg);
g_data->lightprobes_planar_transform = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_transform, draw_ctx->sh_cfg);
g_data->id_ofs_prb_select = 0;
g_data->id_ofs_prb_select_dupli = 0;
g_data->id_ofs_prb_active = 0;
g_data->id_ofs_prb_transform = 0;
g_data->outlines_transform = shgroup_outline(psl->outlines, 0, sh, cfg);
g_data->outlines_select = shgroup_outline(psl->outlines, 1, sh, cfg);
g_data->outlines_select_dupli = shgroup_outline(psl->outlines, 2, sh, cfg);
g_data->outlines_active = shgroup_outline(psl->outlines, 3, sh, cfg);
}
{
@@ -1464,7 +1380,6 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu);
DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4);
DRW_shgroup_call(grp, quad, NULL);
/* This is the bleed pass if do_outline_expand is false. */
@@ -2781,15 +2696,6 @@ static void DRW_shgroup_speaker(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLa
DRW_buffer_add_entry(sgl->speaker, color, &one, ob->obmat);
}
typedef struct OBJECT_LightProbeEngineData {
DrawData dd;
float increment_x[3];
float increment_y[3];
float increment_z[3];
float corner[3];
} OBJECT_LightProbeEngineData;
static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
OBJECT_StorageList *stl,
OBJECT_PassList *psl,
@@ -2806,13 +2712,10 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost :
&stl->g_data->sgl;
OBJECT_LightProbeEngineData *prb_data = (OBJECT_LightProbeEngineData *)DRW_drawdata_ensure(
&ob->id, &draw_engine_object_type, sizeof(OBJECT_LightProbeEngineData), NULL, NULL);
if (DRW_state_is_select() || do_outlines) {
int *call_id = shgroup_theme_id_to_probe_outline_counter(stl, theme_id, ob->base_flag);
if (prb->type == LIGHTPROBE_TYPE_GRID) {
float corner[3];
float increment[3][3];
/* Update transforms */
float cell_dim[3], half_cell_dim[3];
cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x);
@@ -2822,65 +2725,40 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
/* First cell. */
copy_v3_fl(prb_data->corner, -1.0f);
add_v3_v3(prb_data->corner, half_cell_dim);
mul_m4_v3(ob->obmat, prb_data->corner);
copy_v3_fl(corner, -1.0f);
add_v3_v3(corner, half_cell_dim);
mul_m4_v3(ob->obmat, corner);
/* Opposite neighbor cell. */
copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f);
add_v3_v3(prb_data->increment_x, half_cell_dim);
add_v3_fl(prb_data->increment_x, -1.0f);
mul_m4_v3(ob->obmat, prb_data->increment_x);
sub_v3_v3(prb_data->increment_x, prb_data->corner);
copy_v3_fl3(increment[0], cell_dim[0], 0.0f, 0.0f);
copy_v3_fl3(increment[1], 0.0f, cell_dim[1], 0.0f);
copy_v3_fl3(increment[2], 0.0f, 0.0f, cell_dim[2]);
copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f);
add_v3_v3(prb_data->increment_y, half_cell_dim);
add_v3_fl(prb_data->increment_y, -1.0f);
mul_m4_v3(ob->obmat, prb_data->increment_y);
sub_v3_v3(prb_data->increment_y, prb_data->corner);
copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]);
add_v3_v3(prb_data->increment_z, half_cell_dim);
add_v3_fl(prb_data->increment_z, -1.0f);
mul_m4_v3(ob->obmat, prb_data->increment_z);
sub_v3_v3(prb_data->increment_z, prb_data->corner);
for (int i = 0; i < 3; i++) {
add_v3_v3(increment[i], half_cell_dim);
add_v3_fl(increment[i], -1.0f);
mul_m4_v3(ob->obmat, increment[i]);
sub_v3_v3(increment[i], corner);
}
int outline_id = shgroup_theme_id_to_outline_id(theme_id, ob->base_flag);
uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z;
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->lightprobe_grid, psl->lightprobes);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_int_copy(grp, "call_id", *call_id);
DRW_shgroup_uniform_int(grp, "baseId", call_id, 1); /* that's correct */
DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1);
DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1);
DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1);
DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1);
DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1);
DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id);
DRW_shgroup_uniform_vec3_copy(grp, "corner", corner);
DRW_shgroup_uniform_vec3_copy(grp, "increment_x", increment[0]);
DRW_shgroup_uniform_vec3_copy(grp, "increment_y", increment[1]);
DRW_shgroup_uniform_vec3_copy(grp, "increment_z", increment[2]);
DRW_shgroup_uniform_ivec3_copy(grp, "grid_resolution", &prb->grid_resolution_x);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
DRW_shgroup_call_procedural_points(grp, NULL, cell_count);
*call_id += 1;
}
else if (prb->type == LIGHTPROBE_TYPE_CUBE) {
float draw_size = 1.0f;
float probe_cube_mat[4][4];
// prb_data->draw_size = prb->data_draw_size * 0.1f;
// unit_m4(prb_data->probe_cube_mat);
// copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]);
DRWCallBuffer *buf = buffer_theme_id_to_probe_cube_outline_shgrp(
else if (prb->type == LIGHTPROBE_TYPE_PLANAR && (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
DRWShadingGroup *grp = shgroup_theme_id_to_probe_outline_or_null(
stl, theme_id, ob->base_flag);
/* TODO remove or change the drawing of the cube probes. This line draws nothing on purpose
* to keep the call ids correct. */
zero_m4(probe_cube_mat);
DRW_buffer_add_entry(buf, call_id, &draw_size, probe_cube_mat);
*call_id += 1;
}
else if (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) {
float draw_size = 1.0f;
DRWCallBuffer *buf = buffer_theme_id_to_probe_planar_outline_shgrp(stl, theme_id);
DRW_buffer_add_entry(buf, call_id, &draw_size, ob->obmat);
*call_id += 1;
DRW_shgroup_call_no_cull(grp, DRW_cache_quad_get(), ob);
}
}
@@ -3784,19 +3662,7 @@ static void OBJECT_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
int id_len_select = g_data->id_ofs_select;
int id_len_select_dupli = g_data->id_ofs_select_dupli;
int id_len_active = g_data->id_ofs_active;
int id_len_transform = g_data->id_ofs_transform;
int id_len_prb_select = g_data->id_ofs_prb_select;
int id_len_prb_select_dupli = g_data->id_ofs_prb_select_dupli;
int id_len_prb_active = g_data->id_ofs_prb_active;
int id_len_prb_transform = g_data->id_ofs_prb_transform;
int outline_calls = id_len_select + id_len_select_dupli + id_len_active + id_len_transform;
outline_calls += id_len_prb_select + id_len_prb_select_dupli + id_len_prb_active +
id_len_prb_transform;
int do_outlines = !DRW_pass_is_empty(psl->outlines) || !DRW_pass_is_empty(psl->lightprobes);
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -3804,35 +3670,24 @@ static void OBJECT_draw_scene(void *vedata)
/* Don't draw Transparent passes in MSAA buffer. */
// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */
DRW_draw_pass(stl->g_data->sgl.transp_shapes);
DRW_draw_pass(g_data->sgl.transp_shapes);
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
DRW_draw_pass(stl->g_data->sgl.bone_solid);
DRW_draw_pass(stl->g_data->sgl.bone_wire);
DRW_draw_pass(stl->g_data->sgl.bone_outline);
DRW_draw_pass(stl->g_data->sgl.non_meshes);
DRW_draw_pass(g_data->sgl.bone_solid);
DRW_draw_pass(g_data->sgl.bone_wire);
DRW_draw_pass(g_data->sgl.bone_outline);
DRW_draw_pass(g_data->sgl.non_meshes);
DRW_draw_pass(psl->particle);
DRW_draw_pass(stl->g_data->sgl.bone_axes);
DRW_draw_pass(g_data->sgl.bone_axes);
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
DRW_draw_pass(stl->g_data->sgl.image_empties);
DRW_draw_pass(g_data->sgl.image_empties);
if (DRW_state_is_fbo() && outline_calls > 0) {
if (DRW_state_is_fbo() && do_outlines) {
DRW_stats_group_start("Outlines");
g_data->id_ofs_active = 1;
g_data->id_ofs_select = g_data->id_ofs_active + id_len_active + id_len_prb_active + 1;
g_data->id_ofs_select_dupli = g_data->id_ofs_select + id_len_select + id_len_prb_select + 1;
g_data->id_ofs_transform = g_data->id_ofs_select_dupli + id_len_select_dupli +
id_len_prb_select_dupli + 1;
g_data->id_ofs_prb_active = g_data->id_ofs_active + id_len_active;
g_data->id_ofs_prb_select = g_data->id_ofs_select + id_len_select;
g_data->id_ofs_prb_select_dupli = g_data->id_ofs_select_dupli + id_len_select_dupli;
g_data->id_ofs_prb_transform = g_data->id_ofs_transform + id_len_transform;
/* Render filled polygon on a separate framebuffer */
GPU_framebuffer_bind(fbl->outlines_fb);
GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f);
@@ -3867,7 +3722,7 @@ static void OBJECT_draw_scene(void *vedata)
}
/* Combine with scene buffer last */
if (outline_calls > 0) {
if (do_outlines) {
DRW_draw_pass(psl->outlines_resolve);
}
}

View File

@@ -23,8 +23,6 @@
#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
#include "BIF_glutil.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -77,7 +75,6 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *face_wires_shgrp;
DRWShadingGroup *face_wires_xray_shgrp;
DRWView *view_wires;
BLI_mempool *wire_color_mempool;
View3DOverlay overlay;
float wire_step_param;
bool clear_stencil;
@@ -208,10 +205,6 @@ static void overlay_cache_init(void *vedata)
if (v3d->shading.type == OB_WIRE) {
g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) {
g_data->wire_color_mempool = BLI_mempool_create(sizeof(float[3]), 0, 512, 0);
}
}
{
@@ -256,7 +249,6 @@ static void overlay_cache_init(void *vedata)
}
static void overlay_wire_color_get(const View3D *v3d,
const OVERLAY_PrivateData *pd,
const Object *ob,
const bool use_coloring,
float **rim_col,
@@ -305,8 +297,10 @@ static void overlay_wire_color_get(const View3D *v3d,
if (v3d->shading.type == OB_WIRE) {
if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) {
*wire_col = BLI_mempool_alloc(pd->wire_color_mempool);
*rim_col = BLI_mempool_alloc(pd->wire_color_mempool);
/* Theses stays valid until next call. So we need to copy them when using them as uniform. */
static float wire_col_val[3], rim_col_val[3];
*wire_col = wire_col_val;
*rim_col = rim_col_val;
if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) {
linearrgb_to_srgb_v3_v3(*wire_col, ob->color);
@@ -427,9 +421,9 @@ static void overlay_cache_populate(void *vedata, Object *ob)
if (!(DRW_state_is_select() || DRW_state_is_depth())) {
float *rim_col, *wire_col;
overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
overlay_wire_color_get(v3d, ob, use_coloring, &rim_col, &wire_col);
DRW_shgroup_uniform_vec3_copy(shgrp, "wireColor", wire_col);
DRW_shgroup_uniform_vec3_copy(shgrp, "rimColor", rim_col);
DRW_shgroup_stencil_mask(shgrp,
(is_xray && (is_wire || !pd->clear_stencil)) ? 0x00 : 0xFF);
}
@@ -506,12 +500,6 @@ static void overlay_draw_scene(void *vedata)
/* TODO(fclem): find a way to unify the multisample pass together
* (non meshes + armature + wireframe) */
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
/* XXX TODO(fclem) do not discard data after drawing! Store them per viewport. */
if (stl->g_data->wire_color_mempool) {
BLI_mempool_destroy(stl->g_data->wire_color_mempool);
stl->g_data->wire_color_mempool = NULL;
}
}
static void overlay_engine_free(void)

View File

@@ -1,4 +1,5 @@
#define COMMON_VIEW_LIB
#define DRW_RESOURCE_CHUNK_LEN 512
/* keep in sync with DRWManager.view_data */
layout(std140) uniform viewBlock
@@ -23,8 +24,66 @@ layout(std140) uniform viewBlock
_world_clip_planes_calc_clip_distance(p, clipPlanes)
#endif
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixInverse;
uniform int resourceChunk;
#ifdef GPU_VERTEX_SHADER
# ifdef GL_ARB_shader_draw_parameters
# define baseInstance gl_BaseInstanceARB
# else /* no ARB_shader_draw_parameters */
uniform int baseInstance;
# endif
# ifdef IN_PLACE_INSTANCES
/* When drawing instances of an object at the same position. */
# define instanceId 0
# elif defined(GPU_CRAPPY_AMD_DRIVER)
/* NOTE: This does contain the baseInstance ofset */
in int _instanceId;
# define instanceId (_instanceId - baseInstance)
# else
# define instanceId gl_InstanceID
# endif
# define resource_id (baseInstance + instanceId)
/* Use this to declare and pass the value if
* the fragment shader uses the resource_id. */
# define RESOURCE_ID_VARYING flat out int resourceIDFrag;
# define RESOURCE_ID_VARYING_GEOM flat out int resourceIDGeom;
# define PASS_RESOURCE_ID resourceIDFrag = resource_id;
# define PASS_RESOURCE_ID_GEOM resourceIDGeom = resource_id;
#endif
/* If used in a fragment / geometry shader, we pass
* resource_id as varying. */
#ifdef GPU_GEOMETRY_SHADER
# define RESOURCE_ID_VARYING \
flat out int resourceIDFrag; \
flat in int resourceIDGeom[];
# define resource_id resourceIDGeom
# define PASS_RESOURCE_ID(i) resourceIDFrag = resource_id[i];
#endif
#ifdef GPU_FRAGMENT_SHADER
flat in int resourceIDFrag;
# define resource_id resourceIDFrag
#endif
struct ObjectMatrices {
mat4 drw_modelMatrix;
mat4 drw_modelMatrixInverse;
};
layout(std140) uniform modelBlock
{
ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN];
};
#define ModelMatrix (drw_matrices[resource_id].drw_modelMatrix)
#define ModelMatrixInverse (drw_matrices[resource_id].drw_modelMatrixInverse)
#define resource_handle (resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id)
/** Transform shortcuts. */
/* Rule of thumb: Try to reuse world positions and normals because converting though viewspace

View File

@@ -1,18 +1,11 @@
uniform mat4 ViewProjectionMatrix;
uniform float sphere_size;
uniform ivec3 grid_resolution;
uniform vec3 corner;
uniform vec3 increment_x;
uniform vec3 increment_y;
uniform vec3 increment_z;
uniform vec3 screen_vecs[2];
uniform int call_id; /* we don't want the builtin callId which would be 0. */
uniform int baseId;
flat out uint finalId;
flat out int objectId;
void main()
{
@@ -29,7 +22,8 @@ void main()
gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0);
gl_PointSize = 2.0f;
finalId = uint(baseId + call_id);
/* ID 0 is nothing (background) */
objectId = resource_handle + 1;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(ws_cell_location);

View File

@@ -7,26 +7,27 @@ uniform usampler2D outlineId;
uniform sampler2D outlineDepth;
uniform sampler2D sceneDepth;
uniform int idOffsets[4];
uniform float alphaOcclu;
uniform vec2 viewportSize;
vec4 convert_id_to_color(int id)
vec4 convert_id_to_color(uint id)
{
if (id == 0) {
if (id == 0u) {
return vec4(0.0);
}
if (id < idOffsets[1]) {
return colorActive;
}
else if (id < idOffsets[2]) {
/* WATCH: Keep in sync with outlineId of the prepass. */
uint color_id = id >> 14u;
if (color_id == 1u) {
return colorSelect;
}
else if (id < idOffsets[3]) {
else if (color_id == 2u) {
return colorDupliSelect;
}
else {
else if (color_id == 3u) {
return colorActive;
}
else { /* color_id == 0u */
return colorTransform;
}
}
@@ -85,7 +86,7 @@ void main()
const float epsilon = 3.0 / 8388608.0;
bool occluded = (ref_depth > scene_depth + epsilon);
FragColor = convert_id_to_color(int(ref_id));
FragColor = convert_id_to_color(ref_id);
FragColor.a *= (occluded) ? alphaOcclu : 1.0;
FragColor.a = (outline) ? FragColor.a : 0.0;
}

View File

@@ -1,10 +1,17 @@
uniform int callId;
uniform int baseId;
/* Should be 2 bits only [0..3]. */
uniform int outlineId;
flat in int objectId;
/* using uint because 16bit uint can contain more ids than int. */
out uint outId;
/* Replace top 2 bits (of the 16bit output) by outlineId.
* This leaves 16K different IDs to create outlines between objects. */
#define SHIFT (32u - (16u - 2u))
void main()
{
outId = uint(baseId + callId);
outId = (uint(outlineId) << 14u) | ((uint(objectId) << SHIFT) >> SHIFT);
}

View File

@@ -2,12 +2,15 @@
layout(lines_adjacency) in;
layout(line_strip, max_vertices = 2) out;
in vec4 pPos[];
in vec3 vPos[];
in int objectId_g[];
flat out int objectId;
void vert_from_gl_in(int v)
{
gl_Position = pPos[v];
gl_Position = gl_in[v].gl_Position;
objectId = objectId_g[v];
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance);
#endif

View File

@@ -1,16 +1,27 @@
in vec3 pos;
out vec4 pPos;
#ifdef USE_GEOM
out vec3 vPos;
out int objectId_g;
# define objectId objectId_g
#else
flat out int objectId;
#endif
void main()
{
vec3 world_pos = point_object_to_world(pos);
#ifdef USE_GEOM
vPos = point_world_to_view(world_pos);
pPos = point_world_to_ndc(world_pos);
#endif
gl_Position = point_world_to_ndc(world_pos);
/* Small bias to always be on top of the geom. */
pPos.z -= 1e-3;
gl_Position.z -= 1e-3;
/* ID 0 is nothing (background) */
objectId = resource_handle + 1;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);

View File

@@ -101,17 +101,19 @@ static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
/**
* Use for intersect and boolean.
*/
static void edbm_intersect_select(BMEditMesh *em)
static void edbm_intersect_select(BMEditMesh *em, bool do_select)
{
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
if (do_select) {
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
BMIter iter;
BMEdge *e;
if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
BMIter iter;
BMEdge *e;
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
BM_edge_select_set(em->bm, e, true);
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
BM_edge_select_set(em->bm, e, true);
}
}
}
}
@@ -210,10 +212,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
em->bm, BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
}
if (has_isect) {
edbm_intersect_select(em);
}
else {
edbm_intersect_select(em, has_isect);
if (!has_isect) {
isect_len++;
}
}
@@ -317,10 +318,9 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
boolean_operation,
eps);
if (has_isect) {
edbm_intersect_select(em);
}
else {
edbm_intersect_select(em, has_isect);
if (!has_isect) {
isect_len++;
}
}

View File

@@ -242,6 +242,8 @@ data_to_c_simple(shaders/gpu_shader_gpencil_fill_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC)
data_to_c_simple(shaders/gpu_shader_common_obinfos_lib.glsl SRC)
if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)

View File

@@ -193,6 +193,17 @@ GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff
#endif /* future plans */
/* GPUDrawList is an API to do lots of similar drawcalls very fast using multidrawindirect.
* There is a fallback if the feature is not supported. */
typedef struct GPUDrawList GPUDrawList;
GPUDrawList *GPU_draw_list_create(int length);
void GPU_draw_list_discard(GPUDrawList *list);
void GPU_draw_list_init(GPUDrawList *list, GPUBatch *batch);
void GPU_draw_list_command_add(
GPUDrawList *list, int v_first, int v_count, int i_first, int i_count);
void GPU_draw_list_submit(GPUDrawList *list);
void gpu_batch_init(void);
void gpu_batch_exit(void);

View File

@@ -45,12 +45,12 @@ typedef enum {
GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */
GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
GPU_UNIFORM_ORCO, /* vec4 OrcoTexCoFactors[] */
GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */
GPU_UNIFORM_COLOR, /* vec4 color */
GPU_UNIFORM_CALLID, /* int callId */
GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */
GPU_UNIFORM_COLOR, /* vec4 color */
GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */
GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */
GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */

View File

@@ -37,14 +37,20 @@ typedef struct GPUViewport GPUViewport;
/* Contains memory pools information */
typedef struct ViewportMemoryPool {
struct BLI_memblock *calls;
struct BLI_memblock *states;
struct BLI_memblock *commands;
struct BLI_memblock *commands_small;
struct BLI_memblock *callbuffers;
struct BLI_memblock *obmats;
struct BLI_memblock *obinfos;
struct BLI_memblock *cullstates;
struct BLI_memblock *shgroups;
struct BLI_memblock *uniforms;
struct BLI_memblock *views;
struct BLI_memblock *passes;
struct BLI_memblock *images;
struct GPUUniformBuffer **matrices_ubo;
struct GPUUniformBuffer **obinfos_ubo;
uint ubo_len;
} ViewportMemoryPool;
/* All FramebufferLists are just the same pointers with different names */

View File

@@ -39,8 +39,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
static void batch_update_program_bindings(GPUBatch *batch, uint v_first);
static void batch_update_program_bindings(GPUBatch *batch, uint i_first);
void GPU_batch_vao_cache_clear(GPUBatch *batch)
{
@@ -446,20 +447,51 @@ static void create_bindings(GPUVertBuf *verts,
}
}
static void batch_update_program_bindings(GPUBatch *batch, uint v_first)
static void instance_id_workaround(GPUBatch *batch)
{
/**
* A driver bug make it so that when using an attribute with GL_INT_2_10_10_10_REV as format,
* the gl_InstanceID is incremented by the 2 bit component of the attrib. To workaround this,
* we create a new vertex attrib containing the expected value of gl_InstanceID.
**/
const GPUShaderInput *input = GPU_shaderinterface_attr(batch->interface, "_instanceId");
if (input) {
#define DRW_RESOURCE_CHUNK_LEN 512 /* Keep in sync. */
static GLint vbo_id = 0;
if (vbo_id == 0) {
short data[DRW_RESOURCE_CHUNK_LEN];
for (int i = 0; i < DRW_RESOURCE_CHUNK_LEN; i++) {
data[i] = i;
}
/* GPU_context takes care of deleting `vbo_id` at the end. */
vbo_id = GPU_buf_alloc();
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
}
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glEnableVertexAttribArray(input->location);
glVertexAttribIPointer(input->location, 1, GL_SHORT, 0, NULL);
glVertexAttribDivisor(input->location, 1);
}
}
static void batch_update_program_bindings(GPUBatch *batch, uint i_first)
{
/* Reverse order so first vbos have more prevalence (in term of attrib override). */
for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; --v) {
if (batch->verts[v] != NULL) {
create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false);
create_bindings(batch->verts[v], batch->interface, 0, false);
}
}
if (batch->inst) {
create_bindings(batch->inst, batch->interface, v_first, true);
create_bindings(batch->inst, batch->interface, i_first, true);
}
if (batch->elem) {
GPU_indexbuf_use(batch->elem);
}
if (GPU_crappy_amd_driver()) {
instance_id_workaround(batch);
}
}
void GPU_batch_program_use_begin(GPUBatch *batch)
@@ -618,6 +650,14 @@ void GPU_batch_draw(GPUBatch *batch)
GPU_batch_program_use_end(batch);
}
#if GPU_TRACK_INDEX_RANGE
# define BASE_INDEX(el) ((el)->base_index)
# define INDEX_TYPE(el) ((el)->gl_index_type)
#else
# define BASE_INDEX(el) 0
# define INDEX_TYPE(el) GL_UNSIGNED_INT
#endif
void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count)
{
#if TRUST_NO_ONE
@@ -632,8 +672,13 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi
i_count = (batch->inst) ? batch->inst->vertex_len : 1;
}
if (v_count == 0 || i_count == 0) {
/* Nothing to draw. */
return;
}
if (!GPU_arb_base_instance_is_supported()) {
if (i_first > 0 && i_count > 0) {
if (i_first > 0) {
/* If using offset drawing with instancing, we must
* use the default VAO and redo bindings. */
glBindVertexArray(GPU_vao_default());
@@ -648,13 +693,8 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi
if (batch->elem) {
const GPUIndexBuf *el = batch->elem;
#if GPU_TRACK_INDEX_RANGE
GLenum index_type = el->gl_index_type;
GLint base_index = el->base_index;
#else
GLenum index_type = GL_UNSIGNED_INT;
GLint base_index = 0;
#endif
GLenum index_type = INDEX_TYPE(el);
GLint base_index = BASE_INDEX(el);
void *v_first_ofs = elem_offset(el, v_first);
if (GPU_arb_base_instance_is_supported()) {
@@ -696,6 +736,179 @@ void GPU_draw_primitive(GPUPrimType prim_type, int v_count)
// glBindVertexArray(0);
}
/* -------------------------------------------------------------------- */
/** \name Indirect Draw Calls
* \{ */
#if 0
# define USE_MULTI_DRAW_INDIRECT 0
#else
# define USE_MULTI_DRAW_INDIRECT \
(GL_ARB_multi_draw_indirect && GPU_arb_base_instance_is_supported())
#endif
typedef struct GPUDrawCommand {
uint v_count;
uint i_count;
uint v_first;
uint i_first;
} GPUDrawCommand;
typedef struct GPUDrawCommandIndexed {
uint v_count;
uint i_count;
uint v_first;
uint base_index;
uint i_first;
} GPUDrawCommandIndexed;
struct GPUDrawList {
GPUBatch *batch;
uint base_index; /* Avoid dereferencing batch. */
uint cmd_offset; /* in bytes, offset inside indirect command buffer. */
uint cmd_len; /* Number of used command for the next call. */
uint buffer_size; /* in bytes, size of indirect command buffer. */
GLuint buffer_id; /* Draw Indirect Buffer id */
union {
GPUDrawCommand *commands;
GPUDrawCommandIndexed *commands_indexed;
};
};
GPUDrawList *GPU_draw_list_create(int length)
{
GPUDrawList *list = MEM_callocN(sizeof(GPUDrawList), "GPUDrawList");
/* Alloc the biggest possible command list which is indexed. */
list->buffer_size = sizeof(GPUDrawCommandIndexed) * length;
if (USE_MULTI_DRAW_INDIRECT) {
list->buffer_id = GPU_buf_alloc();
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id);
glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW);
}
else {
list->commands = MEM_mallocN(list->buffer_size, "GPUDrawList data");
}
return list;
}
void GPU_draw_list_discard(GPUDrawList *list)
{
if (list->buffer_id) {
GPU_buf_free(list->buffer_id);
}
else {
MEM_SAFE_FREE(list->commands);
}
MEM_freeN(list);
}
void GPU_draw_list_init(GPUDrawList *list, GPUBatch *batch)
{
BLI_assert(batch->phase == GPU_BATCH_READY_TO_DRAW);
list->batch = batch;
list->base_index = batch->elem ? BASE_INDEX(batch->elem) : UINT_MAX;
list->cmd_len = 0;
if (USE_MULTI_DRAW_INDIRECT) {
if (list->commands == NULL) {
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id);
if (list->cmd_offset >= list->buffer_size) {
/* Orphan buffer data and start fresh. */
glBufferData(GL_DRAW_INDIRECT_BUFFER, list->buffer_size, NULL, GL_DYNAMIC_DRAW);
list->cmd_offset = 0;
}
GLenum flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
list->commands = glMapBufferRange(
GL_DRAW_INDIRECT_BUFFER, list->cmd_offset, list->buffer_size - list->cmd_offset, flags);
}
}
else {
list->cmd_offset = 0;
}
}
void GPU_draw_list_command_add(
GPUDrawList *list, int v_first, int v_count, int i_first, int i_count)
{
BLI_assert(list->commands);
if (list->base_index != UINT_MAX) {
GPUDrawCommandIndexed *cmd = list->commands_indexed + list->cmd_len;
cmd->v_first = v_first;
cmd->v_count = v_count;
cmd->i_count = i_count;
cmd->base_index = list->base_index;
cmd->i_first = i_first;
}
else {
GPUDrawCommand *cmd = list->commands + list->cmd_len;
cmd->v_first = v_first;
cmd->v_count = v_count;
cmd->i_count = i_count;
cmd->i_first = i_first;
}
list->cmd_len++;
uint offset = list->cmd_offset + list->cmd_len * sizeof(GPUDrawCommandIndexed);
if (offset == list->buffer_size) {
GPU_draw_list_submit(list);
GPU_draw_list_init(list, list->batch);
}
}
void GPU_draw_list_submit(GPUDrawList *list)
{
GPUBatch *batch = list->batch;
if (list->cmd_len == 0)
return;
BLI_assert(list->commands);
BLI_assert(batch->program_in_use);
/* TODO could assert that VAO is bound. */
/* TODO We loose a bit of memory here if we only draw arrays. Fix that. */
uintptr_t offset = list->cmd_offset;
uint cmd_len = list->cmd_len;
size_t bytes_used = cmd_len * sizeof(GPUDrawCommandIndexed);
list->cmd_offset += bytes_used;
list->cmd_len = 0; /* Avoid reuse. */
if (USE_MULTI_DRAW_INDIRECT) {
GLenum prim = batch->gl_prim_type;
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, list->buffer_id);
glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, bytes_used);
glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
list->commands = NULL; /* Unmapped */
if (batch->elem) {
glMultiDrawElementsIndirect(prim, INDEX_TYPE(batch->elem), (void *)offset, cmd_len, 0);
}
else {
glMultiDrawArraysIndirect(prim, (void *)offset, cmd_len, 0);
}
}
else {
/* Fallback */
if (batch->elem) {
GPUDrawCommandIndexed *cmd = list->commands_indexed;
for (int i = 0; i < cmd_len; i++, cmd++) {
GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count);
}
}
else {
GPUDrawCommand *cmd = list->commands;
for (int i = 0; i < cmd_len; i++, cmd++) {
GPU_batch_draw_advanced(batch, cmd->v_first, cmd->v_count, cmd->i_first, cmd->i_count);
}
}
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */

View File

@@ -58,6 +58,9 @@
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_geometry_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
static char *glsl_material_library = NULL;
/* -------------------- GPUPass Cache ------------------ */
@@ -790,6 +793,9 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
else if (input->builtin == GPU_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "objmat");
}
else if (input->builtin == GPU_OBJECT_INFO) {
BLI_dynstr_append(ds, "ObjectInfo");
}
else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "objinv");
}
@@ -852,6 +858,10 @@ static char *code_generate_fragment(GPUMaterial *material,
codegen_set_unique_ids(nodes);
*rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes);
if (builtins & GPU_OBJECT_INFO) {
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n");
}
@@ -1000,7 +1010,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
/* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
if (input->attr_type == CD_ORCO) {
/* OPTI : orco is computed from local positions, but only if no modifier is present. */
BLI_dynstr_append(ds, "uniform vec3 OrcoTexCoFactors[2];\n");
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
}
else if (input->attr_name[0] == '\0') {
@@ -1082,6 +1092,8 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "\n");
BLI_dynstr_append(ds, use_geom ? "RESOURCE_ID_VARYING_GEOM\n" : "RESOURCE_ID_VARYING\n");
BLI_dynstr_append(ds,
"#define USE_ATTR\n"
"vec3 srgb_to_linear_attr(vec3 c) {\n"
@@ -1102,6 +1114,8 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "void pass_attr(in vec3 position) {\n");
BLI_dynstr_append(ds, use_geom ? "\tPASS_RESOURCE_ID_GEOM\n" : "\tPASS_RESOURCE_ID\n");
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
if (builtins & GPU_BARYCENTRIC_TEXCO) {
@@ -1128,8 +1142,8 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
}
else if (input->attr_type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * "
"vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n",
"\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
"vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
input->attr_id,
use_geom ? "g" : "");
/* TODO: fix ORCO with modifiers. */
@@ -1184,7 +1198,8 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
}
else if (input->attr_type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
"\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
" OrcoTexCoFactors[1].xyz;\n",
input->attr_id,
use_geom ? "g" : "");
/* See mesh_create_loop_orco() for explanation. */
@@ -1299,6 +1314,8 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "out vec3 worldNormal;\n");
BLI_dynstr_append(ds, "out vec3 viewNormal;\n");
BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, "void main(){\n");
if (builtins & GPU_BARYCENTRIC_DIST) {
@@ -1343,9 +1360,13 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "}\n");
}
BLI_dynstr_append(ds, "RESOURCE_ID_VARYING\n");
/* Generate varying assignments. */
BLI_dynstr_append(ds, "void pass_attr(in int vert) {\n");
BLI_dynstr_append(ds, "\tPASS_RESOURCE_ID(vert)\n");
/* XXX HACK: Eevee specific. */
if (geom_code == NULL) {
BLI_dynstr_append(ds, "\tworldPosition = worldPositiong[vert];\n");

View File

@@ -249,6 +249,9 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
/* a #version 400 feature, but we use #version 330 maximum so use extension */
strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
}
if (GLEW_ARB_shader_draw_parameters) {
strcat(defines, "#extension GL_ARB_shader_draw_parameters : enable\n");
}
}
static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
@@ -256,6 +259,9 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
strcat(defines, "#define GPU_ATI\n");
if (GPU_crappy_amd_driver()) {
strcat(defines, "#define GPU_CRAPPY_AMD_DRIVER\n");
}
}
else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) {
strcat(defines, "#define GPU_NVIDIA\n");

View File

@@ -65,8 +65,8 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_CLIPPLANES] = "WorldClipPlanes",
[GPU_UNIFORM_COLOR] = "color",
[GPU_UNIFORM_CALLID] = "callId",
[GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo",
[GPU_UNIFORM_BASE_INSTANCE] = "baseInstance",
[GPU_UNIFORM_RESOURCE_CHUNK] = "resourceChunk",
[GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,

View File

@@ -40,6 +40,7 @@
#include "GPU_texture.h"
#include "GPU_viewport.h"
#include "GPU_draw.h"
#include "GPU_uniformbuffer.h"
#include "DRW_engine.h"
@@ -620,11 +621,20 @@ void GPU_viewport_free(GPUViewport *viewport)
MEM_freeN(viewport->fbl);
MEM_freeN(viewport->txl);
if (viewport->vmempool.calls != NULL) {
BLI_memblock_destroy(viewport->vmempool.calls, NULL);
if (viewport->vmempool.commands != NULL) {
BLI_memblock_destroy(viewport->vmempool.commands, NULL);
}
if (viewport->vmempool.states != NULL) {
BLI_memblock_destroy(viewport->vmempool.states, NULL);
if (viewport->vmempool.commands_small != NULL) {
BLI_memblock_destroy(viewport->vmempool.commands_small, NULL);
}
if (viewport->vmempool.callbuffers != NULL) {
BLI_memblock_destroy(viewport->vmempool.callbuffers, NULL);
}
if (viewport->vmempool.obmats != NULL) {
BLI_memblock_destroy(viewport->vmempool.obmats, NULL);
}
if (viewport->vmempool.obinfos != NULL) {
BLI_memblock_destroy(viewport->vmempool.obinfos, NULL);
}
if (viewport->vmempool.cullstates != NULL) {
BLI_memblock_destroy(viewport->vmempool.cullstates, NULL);
@@ -651,6 +661,13 @@ void GPU_viewport_free(GPUViewport *viewport)
BLI_memblock_destroy(viewport->vmempool.images, NULL);
}
for (int i = 0; i < viewport->vmempool.ubo_len; i++) {
GPU_uniformbuffer_free(viewport->vmempool.matrices_ubo[i]);
GPU_uniformbuffer_free(viewport->vmempool.obinfos_ubo[i]);
}
MEM_SAFE_FREE(viewport->vmempool.matrices_ubo);
MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo);
DRW_instance_data_list_free(viewport->idatalist);
MEM_freeN(viewport->idatalist);

View File

@@ -0,0 +1,17 @@
/* Need to be included after common_view_lib.glsl for resource_id. */
#ifndef GPU_OBINFOS_UBO
#define GPU_OBINFOS_UBO
struct ObjectInfos {
vec4 drw_OrcoTexCoFactors[2];
vec4 drw_Infos;
};
layout(std140) uniform infoBlock
{
/* DRW_RESOURCE_CHUNK_LEN = 512 */
ObjectInfos drw_infos[512];
};
#define OrcoTexCoFactors (drw_infos[resource_id].drw_OrcoTexCoFactors)
#define ObjectInfo (drw_infos[resource_id].drw_Infos)
#endif

View File

@@ -1,8 +1,5 @@
uniform mat4 ViewProjectionMatrix;
#ifdef USE_WORLD_CLIP_PLANES
uniform mat4 ModelMatrix;
#endif
/* ---- Instantiated Attrs ---- */
in float pos;
@@ -47,11 +44,12 @@ void main()
pPos = vec3(0.0);
}
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0);
vec4 wPos = InstanceModelMatrix * vec4(pPos, 1.0);
gl_Position = ViewProjectionMatrix * wPos;
finalColor = vec4(color, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * vec4(pPos, 1.0)).xyz);
world_clip_planes_calc_clip_distance(wPos.xyz);
#endif
}

View File

@@ -18,13 +18,14 @@ void main()
{
float len = end - start;
vec3 sta = vec3(0.0, 0.0, -start);
vec4 pos_4d = vec4(pos * -len + sta, 1.0);
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d;
vec4 wPos = InstanceModelMatrix * vec4(pos * -len + sta, 1.0);
gl_Position = ViewProjectionMatrix * wPos;
gl_PointSize = size;
finalColor = vec4(color, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance((InstanceModelMatrix * pos_4d).xyz);
world_clip_planes_calc_clip_distance(wPos.xyz);
#endif
}

View File

@@ -1,6 +1,5 @@
uniform mat4 ViewProjectionMatrix;
uniform mat4 ModelMatrix;
/* ---- Instantiated Attrs ---- */
in vec3 pos;
@@ -20,10 +19,10 @@ void main()
{
finalColor = color;
vec4 pos_4d = vec4(pos * size, 1.0);
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d;
vec4 wPos = InstanceModelMatrix * vec4(pos * size, 1.0);
gl_Position = ViewProjectionMatrix * wPos;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz);
world_clip_planes_calc_clip_distance(wPos.xyz);
#endif
}

View File

@@ -1,8 +1,6 @@
uniform mat4 ViewProjectionMatrix;
#ifdef USE_WORLD_CLIP_PLANES
uniform mat4 ModelMatrix;
#endif
uniform int baseId;
/* ---- Instantiated Attrs ---- */
@@ -21,11 +19,11 @@ flat out uint finalId;
void main()
{
vec4 pos_4d = vec4(pos * size, 1.0);
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d;
vec4 wPos = InstanceModelMatrix * vec4(pos * size, 1.0);
gl_Position = ViewProjectionMatrix * wPos;
finalId = uint(baseId + callId);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz);
world_clip_planes_calc_clip_distance(wPos.xyz);
#endif
}

View File

@@ -9,5 +9,5 @@ in mat4 InstanceModelMatrix;
void main()
{
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0));
}