diff options
Diffstat (limited to 'intern/gawain/src')
-rw-r--r-- | intern/gawain/src/gwn_attr_binding.c (renamed from intern/gawain/src/attrib_binding.c) | 4 | ||||
-rw-r--r-- | intern/gawain/src/gwn_batch.c (renamed from intern/gawain/src/batch.c) | 75 | ||||
-rw-r--r-- | intern/gawain/src/gwn_buffer_id.cpp (renamed from intern/gawain/src/buffer_id.cpp) | 2 | ||||
-rw-r--r-- | intern/gawain/src/gwn_element.c (renamed from intern/gawain/src/element.c) | 4 | ||||
-rw-r--r-- | intern/gawain/src/gwn_imm_util.c (renamed from intern/gawain/src/imm_util.c) | 4 | ||||
-rw-r--r-- | intern/gawain/src/gwn_immediate.c (renamed from intern/gawain/src/immediate.c) | 12 | ||||
-rw-r--r-- | intern/gawain/src/gwn_primitive.c (renamed from intern/gawain/src/primitive.c) | 4 | ||||
-rw-r--r-- | intern/gawain/src/gwn_shader_interface.c | 311 | ||||
-rw-r--r-- | intern/gawain/src/gwn_vertex_buffer.c (renamed from intern/gawain/src/vertex_buffer.c) | 45 | ||||
-rw-r--r-- | intern/gawain/src/gwn_vertex_format.c (renamed from intern/gawain/src/vertex_format.c) | 14 | ||||
-rw-r--r-- | intern/gawain/src/shader_interface.c | 311 |
11 files changed, 427 insertions, 359 deletions
diff --git a/intern/gawain/src/attrib_binding.c b/intern/gawain/src/gwn_attr_binding.c index 6cdb8a0e542..7647a927b1e 100644 --- a/intern/gawain/src/attrib_binding.c +++ b/intern/gawain/src/gwn_attr_binding.c @@ -9,8 +9,8 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "attrib_binding.h" -#include "attrib_binding_private.h" +#include "gwn_attr_binding.h" +#include "gwn_attr_binding_private.h" #include <stddef.h> #if GWN_VERT_ATTR_MAX_LEN != 16 diff --git a/intern/gawain/src/batch.c b/intern/gawain/src/gwn_batch.c index 17e45084613..c651fb3a26f 100644 --- a/intern/gawain/src/batch.c +++ b/intern/gawain/src/gwn_batch.c @@ -9,25 +9,29 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "batch.h" -#include "buffer_id.h" -#include "primitive_private.h" +#include "gwn_batch.h" +#include "gwn_buffer_id.h" +#include "gwn_primitive_private.h" #include <stdlib.h> // necessary functions from matrix API extern void gpuBindMatrices(const Gwn_ShaderInterface* shaderface); extern bool gpuMatricesDirty(void); // how best to use this here? -Gwn_Batch* GWN_batch_create(Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem) +Gwn_Batch* GWN_batch_create_ex( + Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem, + unsigned owns_flag) { Gwn_Batch* batch = calloc(1, sizeof(Gwn_Batch)); - GWN_batch_init(batch, prim_type, verts, elem); + GWN_batch_init_ex(batch, prim_type, verts, elem, owns_flag); return batch; } -void GWN_batch_init(Gwn_Batch* batch, Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem) +void GWN_batch_init_ex( + Gwn_Batch* batch, Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem, + unsigned owns_flag) { #if TRUST_NO_ONE assert(verts != NULL); @@ -40,32 +44,34 @@ void GWN_batch_init(Gwn_Batch* batch, Gwn_PrimType prim_type, Gwn_VertBuf* verts batch->prim_type = prim_type; batch->gl_prim_type = convert_prim_type_to_gl(prim_type); batch->phase = GWN_BATCH_READY_TO_DRAW; + batch->owns_flag = owns_flag; } void GWN_batch_discard(Gwn_Batch* batch) { - if (batch->vao_id) - GWN_vao_free(batch->vao_id); - - free(batch); - } + if (batch->owns_flag & GWN_BATCH_OWNS_INDEX) + GWN_indexbuf_discard(batch->elem); -void GWN_batch_discard_all(Gwn_Batch* batch) - { - for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) + if ((batch->owns_flag & ~GWN_BATCH_OWNS_INDEX) != 0) { - if (batch->verts[v] == NULL) - break; - GWN_vertbuf_discard(batch->verts[v]); + for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) + { + if (batch->verts[v] == NULL) + break; + if (batch->owns_flag & (1 << v)) + GWN_vertbuf_discard(batch->verts[v]); + } } - if (batch->elem) - GWN_indexbuf_discard(batch->elem); + if (batch->vao_id) + GWN_vao_free(batch->vao_id); - GWN_batch_discard(batch); + free(batch); } -int GWN_batch_vertbuf_add(Gwn_Batch* batch, Gwn_VertBuf* verts) +int GWN_batch_vertbuf_add_ex( + Gwn_Batch* batch, Gwn_VertBuf* verts, + bool own_vbo) { for (unsigned v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) { @@ -78,6 +84,8 @@ int GWN_batch_vertbuf_add(Gwn_Batch* batch, Gwn_VertBuf* verts) #endif batch->verts[v] = verts; // TODO: mark dirty so we can keep attrib bindings up-to-date + if (own_vbo) + batch->owns_flag |= (1 << v); return v; } } @@ -102,6 +110,14 @@ void GWN_batch_program_set(Gwn_Batch* batch, GLuint program, const Gwn_ShaderInt GWN_batch_program_use_begin(batch); // hack! to make Batch_Uniform* simpler } +// fclem : hack ! +// we need this because we don't want to unbind the shader between drawcalls +// but we still want the correct shader to be bound outside the draw manager +void GWN_batch_program_unset(Gwn_Batch* batch) + { + batch->program_in_use = false; + } + static void Batch_update_program_bindings(Gwn_Batch* batch) { // disable all as a precaution @@ -219,6 +235,12 @@ void GWN_batch_uniform_1f(Gwn_Batch* batch, const char* name, float x) glUniform1f(uniform->location, x); } +void GWN_batch_uniform_2fv(Gwn_Batch* batch, const char* name, const float data[2]) + { + GET_UNIFORM + glUniform2fv(uniform->location, 1, data); + } + void GWN_batch_uniform_3fv(Gwn_Batch* batch, const char* name, const float data[3]) { GET_UNIFORM @@ -365,8 +387,11 @@ void GWN_batch_draw_stupid_instanced(Gwn_Batch* batch, unsigned int instance_vbo if (batch->elem) { const Gwn_IndexBuf* el = batch->elem; - +#if GWN_TRACK_INDEX_RANGE + glDrawElementsInstancedBaseVertex(batch->gl_prim_type, el->index_ct, el->gl_index_type, 0, instance_count, el->base_index); +#else glDrawElementsInstanced(batch->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count); +#endif } else glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_ct, instance_count); @@ -432,11 +457,15 @@ void GWN_batch_draw_stupid_instanced_with_batch(Gwn_Batch* batch_instanced, Gwn_ { const Gwn_IndexBuf* el = batch_instanced->elem; +#if GWN_TRACK_INDEX_RANGE + glDrawElementsInstancedBaseVertex(batch_instanced->gl_prim_type, el->index_ct, el->gl_index_type, 0, verts->vertex_ct, el->base_index); +#else glDrawElementsInstanced(batch_instanced->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, verts->vertex_ct); +#endif } else glDrawArraysInstanced(batch_instanced->gl_prim_type, 0, batch_instanced->verts[0]->vertex_ct, verts->vertex_ct); // GWN_batch_program_use_end(batch); glBindVertexArray(0); - }
\ No newline at end of file + } diff --git a/intern/gawain/src/buffer_id.cpp b/intern/gawain/src/gwn_buffer_id.cpp index 59a6b9c89e7..a93c3950d29 100644 --- a/intern/gawain/src/buffer_id.cpp +++ b/intern/gawain/src/gwn_buffer_id.cpp @@ -9,7 +9,7 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.#include "buffer_id.h" -#include "buffer_id.h" +#include "gwn_buffer_id.h" #include <mutex> #include <vector> diff --git a/intern/gawain/src/element.c b/intern/gawain/src/gwn_element.c index ecf555fbfe8..f31b64fa232 100644 --- a/intern/gawain/src/element.c +++ b/intern/gawain/src/gwn_element.c @@ -9,8 +9,8 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "element.h" -#include "buffer_id.h" +#include "gwn_element.h" +#include "gwn_buffer_id.h" #include <stdlib.h> #define KEEP_SINGLE_COPY 1 diff --git a/intern/gawain/src/imm_util.c b/intern/gawain/src/gwn_imm_util.c index b06778c9045..45d8a7036e8 100644 --- a/intern/gawain/src/imm_util.c +++ b/intern/gawain/src/gwn_imm_util.c @@ -9,8 +9,8 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "imm_util.h" -#include "immediate.h" +#include "gwn_imm_util.h" +#include "gwn_immediate.h" void immRectf(unsigned pos, float x1, float y1, float x2, float y2) diff --git a/intern/gawain/src/immediate.c b/intern/gawain/src/gwn_immediate.c index 5eb5ebb8336..1c0776d1bbf 100644 --- a/intern/gawain/src/immediate.c +++ b/intern/gawain/src/gwn_immediate.c @@ -9,12 +9,12 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "immediate.h" -#include "buffer_id.h" -#include "attrib_binding.h" -#include "attrib_binding_private.h" -#include "vertex_format_private.h" -#include "primitive_private.h" +#include "gwn_immediate.h" +#include "gwn_buffer_id.h" +#include "gwn_attr_binding.h" +#include "gwn_attr_binding_private.h" +#include "gwn_vertex_format_private.h" +#include "gwn_primitive_private.h" #include <string.h> // necessary functions from matrix API diff --git a/intern/gawain/src/primitive.c b/intern/gawain/src/gwn_primitive.c index b9d92a6bdf8..b206b3ae1b3 100644 --- a/intern/gawain/src/primitive.c +++ b/intern/gawain/src/gwn_primitive.c @@ -9,8 +9,8 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "primitive.h" -#include "primitive_private.h" +#include "gwn_primitive.h" +#include "gwn_primitive_private.h" Gwn_PrimClass GWN_primtype_class(Gwn_PrimType prim_type) { diff --git a/intern/gawain/src/gwn_shader_interface.c b/intern/gawain/src/gwn_shader_interface.c new file mode 100644 index 00000000000..1fb941f9225 --- /dev/null +++ b/intern/gawain/src/gwn_shader_interface.c @@ -0,0 +1,311 @@ + +// Gawain shader interface (C --> GLSL) +// +// This code is part of the Gawain library, with modifications +// specific to integration with Blender. +// +// Copyright 2017 Mike Erwin +// +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of +// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "gwn_shader_interface.h" +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#define DEBUG_SHADER_INTERFACE 0 + +#if DEBUG_SHADER_INTERFACE + #include <stdio.h> +#endif + +static const char* BuiltinUniform_name(Gwn_UniformBuiltin u) + { + static const char* names[] = + { + [GWN_UNIFORM_NONE] = NULL, + + [GWN_UNIFORM_MODEL] = "ModelMatrix", + [GWN_UNIFORM_VIEW] = "ViewMatrix", + [GWN_UNIFORM_MODELVIEW] = "ModelViewMatrix", + [GWN_UNIFORM_PROJECTION] = "ProjectionMatrix", + [GWN_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix", + [GWN_UNIFORM_MVP] = "ModelViewProjectionMatrix", + + [GWN_UNIFORM_MODEL_INV] = "ModelMatrixInverse", + [GWN_UNIFORM_VIEW_INV] = "ViewMatrixInverse", + [GWN_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse", + [GWN_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse", + [GWN_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse", + + [GWN_UNIFORM_NORMAL] = "NormalMatrix", + [GWN_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix", + [GWN_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors", + [GWN_UNIFORM_ORCO] = "OrcoTexCoFactors", + [GWN_UNIFORM_CLIPPLANES] = "ClipPlanes", + + [GWN_UNIFORM_COLOR] = "color", + [GWN_UNIFORM_EYE] = "eye", + + [GWN_UNIFORM_CUSTOM] = NULL, + [GWN_NUM_UNIFORMS] = NULL, + }; + + return names[u]; + } + +GWN_INLINE bool match(const char* a, const char* b) + { + return strcmp(a, b) == 0; + } + +GWN_INLINE unsigned hash_string(const char *str) + { + unsigned i = 0, c; + + while ((c = *str++)) + { + i = i * 37 + c; + } + + return i; + } + +GWN_INLINE void set_input_name(Gwn_ShaderInterface* shaderface, Gwn_ShaderInput* input, + const char* name, uint32_t name_len) + { + input->name_offset = shaderface->name_buffer_offset; + input->name_hash = hash_string(name); + shaderface->name_buffer_offset += name_len + 1; // include NULL terminator + } + +GWN_INLINE void shader_input_to_bucket(Gwn_ShaderInput* input, + Gwn_ShaderInput* buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]) + { + const unsigned bucket_index = input->name_hash % GWN_NUM_SHADERINTERFACE_BUCKETS; + input->next = buckets[bucket_index]; + buckets[bucket_index] = input; + } + +GWN_INLINE const Gwn_ShaderInput* buckets_lookup(Gwn_ShaderInput* const buckets[GWN_NUM_SHADERINTERFACE_BUCKETS], + const char *name_buffer, const char *name) + { + const unsigned name_hash = hash_string(name); + const unsigned bucket_index = name_hash % GWN_NUM_SHADERINTERFACE_BUCKETS; + const Gwn_ShaderInput* input = buckets[bucket_index]; + if (input == NULL) + { + // Requested uniform is not found at all. + return NULL; + } + // Optimization bit: if there is no hash collision detected when constructing shader interface + // it means we can only request the single possible uniform. Surely, it's possible we request + // uniform which causes hash collision, but that will be detected in debug builds. + if (input->next == NULL) + { + if (name_hash == input->name_hash) + { +#if TRUST_NO_ONE + assert(match(name_buffer + input->name_offset, name)); +#endif + return input; + } + return NULL; + } + // Work through possible collisions. + const Gwn_ShaderInput* next = input; + while (next != NULL) + { + input = next; + next = input->next; + + if (input->name_hash != name_hash) + { + continue; + } + if (match(name_buffer + input->name_offset, name)) + { + return input; + } + } + return NULL; // not found + } + +GWN_INLINE void buckets_free(Gwn_ShaderInput* buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]) + { + for (unsigned bucket_index = 0; bucket_index < GWN_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) + { + Gwn_ShaderInput *input = buckets[bucket_index]; + while (input != NULL) + { + Gwn_ShaderInput *input_next = input->next; + free(input); + input = input_next; + } + } + } + +static bool setup_builtin_uniform(Gwn_ShaderInput* input, const char* name) + { + // TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types + + // detect built-in uniforms (name must match) + for (Gwn_UniformBuiltin u = GWN_UNIFORM_NONE + 1; u < GWN_UNIFORM_CUSTOM; ++u) + { + const char* builtin_name = BuiltinUniform_name(u); + if (match(name, builtin_name)) + { + input->builtin_type = u; + return true; + } + } + + input->builtin_type = GWN_UNIFORM_CUSTOM; + return false; + } + +static const Gwn_ShaderInput* add_uniform(Gwn_ShaderInterface* shaderface, const char* name) + { + Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput)); + + input->location = glGetUniformLocation(shaderface->program, name); + + unsigned name_len = strlen(name); + shaderface->name_buffer = realloc(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); // include NULL terminator + char* name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset; + strcpy(name_buffer, name); + + set_input_name(shaderface, input, name, name_len); + setup_builtin_uniform(input, name); + + shader_input_to_bucket(input, shaderface->uniform_buckets); + if (input->builtin_type != GWN_UNIFORM_NONE && + input->builtin_type != GWN_UNIFORM_CUSTOM) + { + shaderface->builtin_uniforms[input->builtin_type] = input; + } +#if DEBUG_SHADER_INTERFACE + printf("Gwn_ShaderInterface %p, program %d, uniform[] '%s' at location %d\n", shaderface, shaderface->program, name, input->location); +#endif + return input; + } + +Gwn_ShaderInterface* GWN_shaderinterface_create(GLint program) + { + Gwn_ShaderInterface* shaderface = calloc(1, sizeof(Gwn_ShaderInterface)); + shaderface->program = program; + +#if DEBUG_SHADER_INTERFACE + printf("%s {\n", __func__); // enter function + printf("Gwn_ShaderInterface %p, program %d\n", shaderface, program); +#endif + + GLint max_attrib_name_len, attrib_ct; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len); + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attrib_ct); + + GLint max_ubo_name_len, ubo_ct; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_ct); + + const uint32_t name_buffer_len = attrib_ct * max_attrib_name_len + ubo_ct * max_ubo_name_len; + shaderface->name_buffer = malloc(name_buffer_len); + + // Attributes + for (uint32_t i = 0; i < attrib_ct; ++i) + { + Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput)); + GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; + char* name = shaderface->name_buffer + shaderface->name_buffer_offset; + GLsizei name_len = 0; + + glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); + + // TODO: reject DOUBLE gl_types + + input->location = glGetAttribLocation(program, name); + + set_input_name(shaderface, input, name, name_len); + + shader_input_to_bucket(input, shaderface->attrib_buckets); + +#if DEBUG_SHADER_INTERFACE + printf("attrib[%u] '%s' at location %d\n", i, name, input->location); +#endif + } + + // Uniform Blocks + for (uint32_t i = 0; i < ubo_ct; ++i) + { + Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput)); + GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; + char* name = shaderface->name_buffer + shaderface->name_buffer_offset; + GLsizei name_len = 0; + + glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); + + input->location = i; + + set_input_name(shaderface, input, name, name_len); + + shader_input_to_bucket(input, shaderface->ubo_buckets); + +#if DEBUG_SHADER_INTERFACE + printf("attrib[%u] '%s' at location %d\n", i, name, input->location); +#endif + } + + return shaderface; + } + +void GWN_shaderinterface_discard(Gwn_ShaderInterface* shaderface) + { + // Free memory used by buckets and has entries. + buckets_free(shaderface->uniform_buckets); + buckets_free(shaderface->attrib_buckets); + buckets_free(shaderface->ubo_buckets); + // Free memory used by name_buffer. + free(shaderface->name_buffer); + // Free memory used by shader interface by its self. + free(shaderface); + } + +const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface* shaderface, const char* name) + { + // TODO: Warn if we find a matching builtin, since these can be looked up much quicker. + const Gwn_ShaderInput* input = buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name); + + // If input is not found add it so it's found next time. + if (input == NULL) + input = add_uniform((Gwn_ShaderInterface*)shaderface, name); + + return (input->location != -1) ? input : NULL; + } + +const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface* shaderface, Gwn_UniformBuiltin builtin) + { +#if TRUST_NO_ONE + assert(builtin != GWN_UNIFORM_NONE); + assert(builtin != GWN_UNIFORM_CUSTOM); + assert(builtin != GWN_NUM_UNIFORMS); +#endif + + const Gwn_ShaderInput* input = shaderface->builtin_uniforms[builtin]; + + // If input is not found add it so it's found next time. + if (input == NULL) + input = add_uniform((Gwn_ShaderInterface*)shaderface, BuiltinUniform_name(builtin)); + + return (input->location != -1) ? input : NULL; + } + +const Gwn_ShaderInput* GWN_shaderinterface_ubo(const Gwn_ShaderInterface* shaderface, const char* name) + { + return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name); + } + +const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface* shaderface, const char* name) + { + return buckets_lookup(shaderface->attrib_buckets, shaderface->name_buffer, name); + } diff --git a/intern/gawain/src/vertex_buffer.c b/intern/gawain/src/gwn_vertex_buffer.c index 03691b0c21d..2019d7d50bc 100644 --- a/intern/gawain/src/vertex_buffer.c +++ b/intern/gawain/src/gwn_vertex_buffer.c @@ -9,9 +9,9 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "vertex_buffer.h" -#include "buffer_id.h" -#include "vertex_format_private.h" +#include "gwn_vertex_buffer.h" +#include "gwn_buffer_id.h" +#include "gwn_vertex_format_private.h" #include <stdlib.h> #include <string.h> @@ -51,6 +51,25 @@ void GWN_vertbuf_init_with_format(Gwn_VertBuf* verts, const Gwn_VertFormat* form VertexFormat_pack(&verts->format); } +/** + * Like #GWN_vertbuf_discard but doesn't free. + */ +void GWN_vertbuf_clear(Gwn_VertBuf* verts) + { + if (verts->vbo_id) { + GWN_buf_id_free(verts->vbo_id); + vbo_memory_usage -= GWN_vertbuf_size_get(verts); + } +#if KEEP_SINGLE_COPY + else +#endif + if (verts->data) + { + free(verts->data); + verts->data = NULL; + } + } + void GWN_vertbuf_discard(Gwn_VertBuf* verts) { if (verts->vbo_id) { @@ -151,6 +170,26 @@ void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned s } } +void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertBufRaw *access) + { + const Gwn_VertFormat* format = &verts->format; + const Gwn_VertAttr* a = format->attribs + a_idx; + +#if TRUST_NO_ONE + assert(a_idx < format->attrib_ct); + assert(verts->data != NULL); // data must be in main mem +#endif + + access->size = a->sz; + access->stride = format->stride; + access->data = (GLubyte*)verts->data + a->offset; + access->data_init = access->data; +#if TRUST_NO_ONE + access->_data_end = access->data_init + (size_t)(verts->vertex_ct * format->stride); +#endif + } + + static void VertexBuffer_prime(Gwn_VertBuf* verts) { const unsigned buffer_sz = GWN_vertbuf_size_get(verts); diff --git a/intern/gawain/src/vertex_format.c b/intern/gawain/src/gwn_vertex_format.c index 139a76cf7ef..d6367935703 100644 --- a/intern/gawain/src/vertex_format.c +++ b/intern/gawain/src/gwn_vertex_format.c @@ -9,8 +9,8 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of // the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "vertex_format.h" -#include "vertex_format_private.h" +#include "gwn_vertex_format.h" +#include "gwn_vertex_format_private.h" #include <stddef.h> #include <string.h> @@ -251,7 +251,7 @@ void VertexFormat_pack(Gwn_VertFormat* format) // OpenGL ES packs in a different order as desktop GL but component conversion is the same. -// Of the code here, only struct PackedNormal needs to change. +// Of the code here, only struct Gwn_PackedNormal needs to change. #define SIGNED_INT_10_MAX 511 #define SIGNED_INT_10_MIN -512 @@ -283,14 +283,14 @@ static int convert_i16(short x) // TODO: round? } -PackedNormal convert_i10_v3(const float data[3]) +Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3]) { - PackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) }; + Gwn_PackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) }; return n; } -PackedNormal convert_i10_s3(const short data[3]) +Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3]) { - PackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]) }; + Gwn_PackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]) }; return n; } diff --git a/intern/gawain/src/shader_interface.c b/intern/gawain/src/shader_interface.c deleted file mode 100644 index dff2c06f531..00000000000 --- a/intern/gawain/src/shader_interface.c +++ /dev/null @@ -1,311 +0,0 @@ - -// Gawain shader interface (C --> GLSL) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2017 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "shader_interface.h" -#include <stdlib.h> -#include <stddef.h> -#include <string.h> - -#define SUPPORT_LEGACY_GLSL 1 -#define DEBUG_SHADER_INTERFACE 0 - -#if DEBUG_SHADER_INTERFACE - #include <stdio.h> -#endif - -static const char* BuiltinUniform_name(Gwn_UniformBuiltin u) - { - static const char* names[] = - { - [GWN_UNIFORM_NONE] = NULL, - - [GWN_UNIFORM_MODELVIEW] = "ModelViewMatrix", - [GWN_UNIFORM_PROJECTION] = "ProjectionMatrix", - [GWN_UNIFORM_MVP] = "ModelViewProjectionMatrix", - - [GWN_UNIFORM_MODELVIEW_INV] = "ModelViewInverseMatrix", - [GWN_UNIFORM_PROJECTION_INV] = "ProjectionInverseMatrix", - - [GWN_UNIFORM_NORMAL] = "NormalMatrix", - - [GWN_UNIFORM_COLOR] = "color", - - [GWN_UNIFORM_CUSTOM] = NULL - }; - - return names[u]; - } - -static bool match(const char* a, const char* b) - { - return strcmp(a, b) == 0; - } - -static unsigned hash_string(const char *str) - { - unsigned i = 0, c; - - while ((c = *str++)) - { - i = i * 37 + c; - } - - return i; - } - -static void set_input_name(Gwn_ShaderInput* input, const char* name) - { - input->name = name; - input->name_hash = hash_string(name); - } - -// keep these in sync with Gwn_UniformBuiltin order -#define FIRST_MAT4_UNIFORM GWN_UNIFORM_MODELVIEW -#define LAST_MAT4_UNIFORM GWN_UNIFORM_PROJECTION_INV - -static bool setup_builtin_uniform(Gwn_ShaderInput* input, const char* name) - { - // TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types - - // detect built-in uniforms (gl_type and name must match) - // if a match is found, use BuiltinUniform_name so name buffer space can be reclaimed - switch (input->gl_type) - { - case GL_FLOAT_MAT4: - for (Gwn_UniformBuiltin u = FIRST_MAT4_UNIFORM; u <= LAST_MAT4_UNIFORM; ++u) - { - const char* builtin_name = BuiltinUniform_name(u); - if (match(name, builtin_name)) - { - set_input_name(input, builtin_name); - input->builtin_type = u; - return true; - } - } - break; - case GL_FLOAT_MAT3: - { - const char* builtin_name = BuiltinUniform_name(GWN_UNIFORM_NORMAL); - if (match(name, builtin_name)) - { - set_input_name(input, builtin_name); - input->builtin_type = GWN_UNIFORM_NORMAL; - return true; - } - } - break; - case GL_FLOAT_VEC4: - { - const char* builtin_name = BuiltinUniform_name(GWN_UNIFORM_COLOR); - if (match(name, builtin_name)) - { - set_input_name(input, builtin_name); - input->builtin_type = GWN_UNIFORM_COLOR; - return true; - } - } - break; - default: - ; - } - - input->builtin_type = GWN_UNIFORM_CUSTOM; - return false; - } - -Gwn_ShaderInterface* GWN_shaderinterface_create(GLint program) - { -#if DEBUG_SHADER_INTERFACE - printf("%s {\n", __func__); // enter function -#endif - - GLint uniform_ct, attrib_ct; - glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_ct); - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attrib_ct); - const GLint input_ct = uniform_ct + attrib_ct; - - GLint max_uniform_name_len, max_attrib_name_len; - glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len); - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len); - const uint32_t name_buffer_len = uniform_ct * max_uniform_name_len + attrib_ct * max_attrib_name_len; - - // allocate enough space for input counts, details for each input, and a buffer for name strings - Gwn_ShaderInterface* shaderface = calloc(1, offsetof(Gwn_ShaderInterface, inputs) + input_ct * sizeof(Gwn_ShaderInput) + name_buffer_len); - shaderface->uniform_ct = uniform_ct; - shaderface->attrib_ct = attrib_ct; - - char* name_buffer = (char*)shaderface + offsetof(Gwn_ShaderInterface, inputs) + input_ct * sizeof(Gwn_ShaderInput); - uint32_t name_buffer_offset = 0; - - for (uint32_t i = 0; i < uniform_ct; ++i) - { - Gwn_ShaderInput* input = shaderface->inputs + i; - GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; - char* name = name_buffer + name_buffer_offset; - GLsizei name_len = 0; - - glGetActiveUniform(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); - - input->location = glGetUniformLocation(program, name); - -#if SUPPORT_LEGACY_GLSL - if (input->location != -1) - { -#elif TRUST_NO_ONE - assert(input->location != -1); -#endif - - if (setup_builtin_uniform(input, name)) - ; // reclaim space from name buffer (don't advance offset) - else - { - set_input_name(input, name); - name_buffer_offset += name_len + 1; // include NULL terminator - } -#if SUPPORT_LEGACY_GLSL - } -#endif - -#if DEBUG_SHADER_INTERFACE - printf("uniform[%u] '%s' at location %d\n", i, name, input->location); -#endif - } - - for (uint32_t i = 0; i < attrib_ct; ++i) - { - Gwn_ShaderInput* input = shaderface->inputs + uniform_ct + i; - GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; - char* name = name_buffer + name_buffer_offset; - GLsizei name_len = 0; - - glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); - - // TODO: reject DOUBLE gl_types - - input->location = glGetAttribLocation(program, name); - -#if SUPPORT_LEGACY_GLSL - if (input->location != -1) - { -#elif TRUST_NO_ONE - assert(input->location != -1); -#endif - - set_input_name(input, name); - name_buffer_offset += name_len + 1; // include NULL terminator -#if SUPPORT_LEGACY_GLSL - } -#endif - -#if DEBUG_SHADER_INTERFACE - printf("attrib[%u] '%s' at location %d\n", i, name, input->location); -#endif - } - - const uint32_t name_buffer_used = name_buffer_offset; - -#if DEBUG_SHADER_INTERFACE - printf("using %u of %u bytes from name buffer\n", name_buffer_used, name_buffer_len); - printf("}\n"); // exit function -#endif - - if (name_buffer_used < name_buffer_len) - { - // realloc shaderface to shrink name buffer - const size_t shaderface_alloc = - offsetof(Gwn_ShaderInterface, inputs) + (input_ct * sizeof(Gwn_ShaderInput)) + name_buffer_used; - const char* shaderface_orig_start = (const char*)shaderface; - const char* shaderface_orig_end = &shaderface_orig_start[shaderface_alloc]; - shaderface = realloc(shaderface, shaderface_alloc); - const ptrdiff_t delta = (char*)shaderface - shaderface_orig_start; - - if (delta) - { - // each input->name will need adjustment (except static built-in names) - for (uint32_t i = 0; i < input_ct; ++i) - { - Gwn_ShaderInput* input = shaderface->inputs + i; - - if (input->name >= shaderface_orig_start && input->name < shaderface_orig_end) - input->name += delta; - } - } - } - - return shaderface; - } - -void GWN_shaderinterface_discard(Gwn_ShaderInterface* shaderface) - { - // allocated as one chunk, so discard is simple - free(shaderface); - } - -const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface* shaderface, const char* name) - { - const unsigned name_hash = hash_string(name); - for (uint32_t i = 0; i < shaderface->uniform_ct; ++i) - { - const Gwn_ShaderInput* uniform = shaderface->inputs + i; - -#if SUPPORT_LEGACY_GLSL - if (uniform->name == NULL) continue; -#endif - - if (uniform->name_hash != name_hash) continue; - - if (match(uniform->name, name)) - return uniform; - - // TODO: warn if we find a matching builtin, since these can be looked up much quicker --v - } - - return NULL; // not found - } - -const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface* shaderface, Gwn_UniformBuiltin builtin) - { -#if TRUST_NO_ONE - assert(builtin != GWN_UNIFORM_NONE); - assert(builtin != GWN_UNIFORM_CUSTOM); -#endif - - // look up by enum, not name - for (uint32_t i = 0; i < shaderface->uniform_ct; ++i) - { - const Gwn_ShaderInput* uniform = shaderface->inputs + i; - - if (uniform->builtin_type == builtin) - return uniform; - } - return NULL; // not found - } - -const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface* shaderface, const char* name) - { - // attribs are stored after uniforms - const uint32_t input_ct = shaderface->uniform_ct + shaderface->attrib_ct; - const unsigned name_hash = hash_string(name); - for (uint32_t i = shaderface->uniform_ct; i < input_ct; ++i) - { - const Gwn_ShaderInput* attrib = shaderface->inputs + i; - -#if SUPPORT_LEGACY_GLSL - if (attrib->name == NULL) continue; -#endif - - if (attrib->name_hash != name_hash) continue; - - if (match(attrib->name, name)) - return attrib; - } - return NULL; // not found - } |