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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2019-05-31 02:45:41 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-09-17 16:16:43 +0300
commit3a08153d7a842b7ab1e40a9048730e1a3ddab5f7 (patch)
tree37e7c902ceb35c5626644ccbbc7e0376e169e56c /source/blender/gpu
parent41299bce936afb5e7da9c332d1140c5a77d49317 (diff)
DRW: Refactor to support draw call batching
Reviewers: brecht Differential Revision: D4997
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_batch.h11
-rw-r--r--source/blender/gpu/GPU_shader_interface.h9
-rw-r--r--source/blender/gpu/GPU_viewport.h10
-rw-r--r--source/blender/gpu/intern/gpu_batch.c244
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c35
-rw-r--r--source/blender/gpu/intern/gpu_shader.c6
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c5
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_vert.glsl2
15 files changed, 349 insertions, 51 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 8d2355ff5ac..bc08da4b2cb 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -330,6 +330,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)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 175033f70d9..7d8c3347eb4 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -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);
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index ec97e1b085e..e336aa53d24 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -45,13 +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_OBJECT_COLOR, /* vec4 objectColor */
+ 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 */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index e7600279d6f..4bbcb6a4335 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -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 */
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index e0c0aea576c..e0d77f37512 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -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,12 +650,18 @@ 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
BLI_assert(batch->program_in_use);
/* TODO could assert that VAO is bound. */
-#endif
if (v_count == 0) {
v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len;
@@ -632,8 +670,18 @@ 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;
+ }
+
+ /* Verify there is enough data do draw. */
+ BLI_assert(i_first + i_count <= batch->inst ? batch->inst->vertex_len : 1);
+ BLI_assert(v_first + v_count <= batch->elem ? batch->elem->index_len :
+ batch->verts[0]->vertex_len);
+
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 +696,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()) {
@@ -697,6 +740,179 @@ void GPU_draw_primitive(GPUPrimType prim_type, int v_count)
}
/* -------------------------------------------------------------------- */
+/** \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
* \{ */
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 7483be74e01..410e23c9576 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -55,6 +55,12 @@
#include <string.h>
#include <stdarg.h>
+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[];
+
/* -------------------- GPUPass Cache ------------------ */
/**
* Internal shader cache: This prevent the shader recompilation / stall when
@@ -778,6 +784,12 @@ 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_OBJECT_COLOR) {
+ BLI_dynstr_append(ds, "ObjectColor");
+ }
else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "objinv");
}
@@ -840,6 +852,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 | GPU_OBJECT_COLOR)) {
+ BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
+ }
+
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n");
}
@@ -988,7 +1004,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') {
@@ -1070,6 +1086,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"
@@ -1099,6 +1117,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) {
@@ -1125,8 +1145,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. */
@@ -1181,7 +1201,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. */
@@ -1296,6 +1317,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) {
@@ -1340,9 +1363,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");
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 42c21626c05..7e8cb8a4fa0 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -248,6 +248,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])
@@ -255,6 +258,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");
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 083c5bf2b60..983c5dfc27a 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -65,9 +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_OBJECT_COLOR] = "unfobjectcolor",
+ [GPU_UNIFORM_BASE_INSTANCE] = "baseInstance",
+ [GPU_UNIFORM_RESOURCE_CHUNK] = "resourceChunk",
[GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index fcb1a008226..615af57c1bd 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -39,6 +39,7 @@
#include "GPU_immediate.h"
#include "GPU_texture.h"
#include "GPU_viewport.h"
+#include "GPU_uniformbuffer.h"
#include "DRW_engine.h"
@@ -619,11 +620,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);
@@ -650,6 +660,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);
diff --git a/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl b/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl
new file mode 100644
index 00000000000..aa1d437c307
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_common_obinfos_lib.glsl
@@ -0,0 +1,19 @@
+
+/* 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_ObjectColor;
+ 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)
+#define ObjectColor (drw_infos[resource_id].drw_ObjectColor)
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
index 31b359dbe6d..f32c47bcec3 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
@@ -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
}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
index d9a0ffbbdac..5bd29c55e42 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
@@ -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
}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
index 3e52e43beae..10228a1e985 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
@@ -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
}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl
index 130f46e1e33..32db8d17572 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl
@@ -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
}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
index eeca6e972fa..b8d31f5540a 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
@@ -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));
}