diff options
Diffstat (limited to 'intern/gawain')
-rw-r--r-- | intern/gawain/CMakeLists.txt | 48 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_attr_binding.h (renamed from intern/gawain/gawain/attrib_binding.h) | 4 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_attr_binding_private.h (renamed from intern/gawain/gawain/attrib_binding_private.h) | 4 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_batch.h (renamed from intern/gawain/gawain/batch.h) | 42 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_buffer_id.h (renamed from intern/gawain/gawain/buffer_id.h) | 2 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_common.h (renamed from intern/gawain/gawain/common.h) | 7 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_element.h (renamed from intern/gawain/gawain/element.h) | 6 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_imm_util.h (renamed from intern/gawain/gawain/imm_util.h) | 0 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_immediate.h (renamed from intern/gawain/gawain/immediate.h) | 8 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_primitive.h (renamed from intern/gawain/gawain/primitive.h) | 2 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_primitive_private.h (renamed from intern/gawain/gawain/primitive_private.h) | 0 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_shader_interface.h | 74 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_vertex_buffer.h (renamed from intern/gawain/gawain/vertex_buffer.h) | 34 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_vertex_format.h (renamed from intern/gawain/gawain/vertex_format.h) | 14 | ||||
-rw-r--r-- | intern/gawain/gawain/gwn_vertex_format_private.h (renamed from intern/gawain/gawain/vertex_format_private.h) | 0 | ||||
-rw-r--r-- | intern/gawain/gawain/shader_interface.h | 53 | ||||
-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 |
27 files changed, 610 insertions, 474 deletions
diff --git a/intern/gawain/CMakeLists.txt b/intern/gawain/CMakeLists.txt index 48392012176..9924daa8cd1 100644 --- a/intern/gawain/CMakeLists.txt +++ b/intern/gawain/CMakeLists.txt @@ -8,31 +8,31 @@ set(INC_SYS ) set(SRC - src/attrib_binding.c - src/batch.c - src/element.c - src/buffer_id.cpp - src/immediate.c - src/imm_util.c - src/primitive.c - src/shader_interface.c - src/vertex_buffer.c - src/vertex_format.c + src/gwn_attr_binding.c + src/gwn_batch.c + src/gwn_element.c + src/gwn_buffer_id.cpp + src/gwn_immediate.c + src/gwn_imm_util.c + src/gwn_primitive.c + src/gwn_shader_interface.c + src/gwn_vertex_buffer.c + src/gwn_vertex_format.c - gawain/attrib_binding.h - gawain/attrib_binding_private.h - gawain/batch.h - gawain/buffer_id.h - gawain/common.h - gawain/element.h - gawain/imm_util.h - gawain/immediate.h - gawain/primitive.h - gawain/primitive_private.h - gawain/shader_interface.h - gawain/vertex_buffer.h - gawain/vertex_format.h - gawain/vertex_format_private.h + gawain/gwn_attr_binding.h + gawain/gwn_attr_binding_private.h + gawain/gwn_batch.h + gawain/gwn_buffer_id.h + gawain/gwn_common.h + gawain/gwn_element.h + gawain/gwn_imm_util.h + gawain/gwn_immediate.h + gawain/gwn_primitive.h + gawain/gwn_primitive_private.h + gawain/gwn_shader_interface.h + gawain/gwn_vertex_buffer.h + gawain/gwn_vertex_format.h + gawain/gwn_vertex_format_private.h ) add_definitions(${GL_DEFINITIONS}) diff --git a/intern/gawain/gawain/attrib_binding.h b/intern/gawain/gawain/gwn_attr_binding.h index a254f05dc05..a209e1c4f0f 100644 --- a/intern/gawain/gawain/attrib_binding.h +++ b/intern/gawain/gawain/gwn_attr_binding.h @@ -11,9 +11,9 @@ #pragma once -#include "common.h" +#include "gwn_common.h" -typedef struct { +typedef struct Gwn_AttrBinding { uint64_t loc_bits; // store 4 bits for each of the 16 attribs uint16_t enabled_bits; // 1 bit for each attrib } Gwn_AttrBinding; diff --git a/intern/gawain/gawain/attrib_binding_private.h b/intern/gawain/gawain/gwn_attr_binding_private.h index 53fdecff9ce..300945d464b 100644 --- a/intern/gawain/gawain/attrib_binding_private.h +++ b/intern/gawain/gawain/gwn_attr_binding_private.h @@ -11,8 +11,8 @@ #pragma once -#include "vertex_format.h" -#include "shader_interface.h" +#include "gwn_vertex_format.h" +#include "gwn_shader_interface.h" void AttribBinding_clear(Gwn_AttrBinding*); diff --git a/intern/gawain/gawain/batch.h b/intern/gawain/gawain/gwn_batch.h index 6e2f32c1996..ee1599845c8 100644 --- a/intern/gawain/gawain/batch.h +++ b/intern/gawain/gawain/gwn_batch.h @@ -11,9 +11,9 @@ #pragma once -#include "vertex_buffer.h" -#include "element.h" -#include "shader_interface.h" +#include "gwn_vertex_buffer.h" +#include "gwn_element.h" +#include "gwn_shader_interface.h" typedef enum { GWN_BATCH_READY_TO_FORMAT, @@ -36,21 +36,36 @@ typedef struct Gwn_Batch { Gwn_BatchPhase phase; bool program_dirty; bool program_in_use; + unsigned owns_flag; // state GLuint program; const Gwn_ShaderInterface* interface; } Gwn_Batch; -Gwn_Batch* GWN_batch_create(Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*); -void GWN_batch_init(Gwn_Batch*, Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*); +enum { + GWN_BATCH_OWNS_VBO = (1 << 0), + /* each vbo index gets bit-shifted */ + GWN_BATCH_OWNS_INDEX = (1 << 31), +}; + +Gwn_Batch* GWN_batch_create_ex(Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, unsigned owns_flag); +void GWN_batch_init_ex(Gwn_Batch*, Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, unsigned owns_flag); + +#define GWN_batch_create(prim, verts, elem) \ + GWN_batch_create_ex(prim, verts, elem, 0) +#define GWN_batch_init(batch, prim, verts, elem) \ + GWN_batch_init_ex(batch, prim, verts, elem, 0) void GWN_batch_discard(Gwn_Batch*); // verts & elem are not discarded -void GWN_batch_discard_all(Gwn_Batch*); // including verts & elem -int GWN_batch_vertbuf_add(Gwn_Batch*, Gwn_VertBuf*); +int GWN_batch_vertbuf_add_ex(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); + +#define GWN_batch_vertbuf_add(batch, verts) \ + GWN_batch_vertbuf_add_ex(batch, verts, false) void GWN_batch_program_set(Gwn_Batch*, GLuint program, const Gwn_ShaderInterface*); +void GWN_batch_program_unset(Gwn_Batch*); // Entire batch draws with one shader program, but can be redrawn later with another program. // Vertex shader's inputs must be compatible with the batch's vertex format. @@ -63,6 +78,7 @@ void GWN_batch_uniform_1f(Gwn_Batch*, const char* name, float value); void GWN_batch_uniform_2f(Gwn_Batch*, const char* name, float x, float y); void GWN_batch_uniform_3f(Gwn_Batch*, const char* name, float x, float y, float z); void GWN_batch_uniform_4f(Gwn_Batch*, const char* name, float x, float y, float z, float w); +void GWN_batch_uniform_2fv(Gwn_Batch*, const char* name, const float data[2]); void GWN_batch_uniform_3fv(Gwn_Batch*, const char* name, const float data[3]); void GWN_batch_uniform_4fv(Gwn_Batch*, const char* name, const float data[4]); @@ -87,17 +103,17 @@ void GWN_batch_draw_stupid_instanced_with_batch(Gwn_Batch*, Gwn_Batch*); // We often need a batch with its own data, to be created and discarded together. // WithOwn variants reduce number of system allocations. -typedef struct { +typedef struct BatchWithOwnVertexBuffer { Gwn_Batch batch; Gwn_VertBuf verts; // link batch.verts to this } BatchWithOwnVertexBuffer; -typedef struct { +typedef struct BatchWithOwnElementList { Gwn_Batch batch; Gwn_IndexBuf elem; // link batch.elem to this } BatchWithOwnElementList; -typedef struct { +typedef struct BatchWithOwnVertexBufferAndElementList { Gwn_Batch batch; Gwn_IndexBuf elem; // link batch.elem to this Gwn_VertBuf verts; // link batch.verts to this @@ -121,9 +137,3 @@ Gwn_Batch* create_BatchInGeneral(Gwn_PrimType, VertexBufferStuff, ElementListStu batch = NULL; \ } \ } while (0) -#define BATCH_DISCARD_ALL_SAFE(batch) do { \ - if (batch != NULL) { \ - GWN_batch_discard_all(batch); \ - batch = NULL; \ - } \ -} while (0) diff --git a/intern/gawain/gawain/buffer_id.h b/intern/gawain/gawain/gwn_buffer_id.h index e978eec67d8..db5df99f526 100644 --- a/intern/gawain/gawain/buffer_id.h +++ b/intern/gawain/gawain/gwn_buffer_id.h @@ -20,7 +20,7 @@ extern "C" { #endif -#include "common.h" +#include "gwn_common.h" GLuint GWN_buf_id_alloc(void); void GWN_buf_id_free(GLuint buffer_id); diff --git a/intern/gawain/gawain/common.h b/intern/gawain/gawain/gwn_common.h index e21b241160d..e96a3b5c2a2 100644 --- a/intern/gawain/gawain/common.h +++ b/intern/gawain/gawain/gwn_common.h @@ -25,3 +25,10 @@ #if TRUST_NO_ONE #include <assert.h> #endif + +/* GWN_INLINE */ +#if defined(_MSC_VER) +# define GWN_INLINE static __forceinline +#else +# define GWN_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) +#endif
\ No newline at end of file diff --git a/intern/gawain/gawain/element.h b/intern/gawain/gawain/gwn_element.h index 771462be7c5..3081305769f 100644 --- a/intern/gawain/gawain/element.h +++ b/intern/gawain/gawain/gwn_element.h @@ -11,7 +11,7 @@ #pragma once -#include "primitive.h" +#include "gwn_primitive.h" #define GWN_TRACK_INDEX_RANGE 1 @@ -21,7 +21,7 @@ typedef enum { GWN_INDEX_U32 } Gwn_IndexBufType; -typedef struct { +typedef struct Gwn_IndexBuf { unsigned index_ct; #if GWN_TRACK_INDEX_RANGE Gwn_IndexBufType index_type; @@ -37,7 +37,7 @@ typedef struct { void GWN_indexbuf_use(Gwn_IndexBuf*); unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf*); -typedef struct { +typedef struct Gwn_IndexBufBuilder { unsigned max_allowed_index; unsigned max_index_ct; unsigned index_ct; diff --git a/intern/gawain/gawain/imm_util.h b/intern/gawain/gawain/gwn_imm_util.h index 730bd7c1a3c..730bd7c1a3c 100644 --- a/intern/gawain/gawain/imm_util.h +++ b/intern/gawain/gawain/gwn_imm_util.h diff --git a/intern/gawain/gawain/immediate.h b/intern/gawain/gawain/gwn_immediate.h index 39ba76db931..386b26b63b1 100644 --- a/intern/gawain/gawain/immediate.h +++ b/intern/gawain/gawain/gwn_immediate.h @@ -11,9 +11,9 @@ #pragma once -#include "vertex_format.h" -#include "primitive.h" -#include "shader_interface.h" +#include "gwn_vertex_format.h" +#include "gwn_primitive.h" +#include "gwn_shader_interface.h" #define IMM_BATCH_COMBO 1 @@ -28,7 +28,7 @@ void immBeginAtMost(Gwn_PrimType, unsigned max_vertex_ct); // can supply fewer v void immEnd(void); // finishes and draws #if IMM_BATCH_COMBO -#include "batch.h" +#include "gwn_batch.h" // immBegin a batch, then use standard immFunctions as usual. // immEnd will finalize the batch instead of drawing. // Then you can draw it as many times as you like! Partially replaces the need for display lists. diff --git a/intern/gawain/gawain/primitive.h b/intern/gawain/gawain/gwn_primitive.h index c6786dc1993..5e5b8019889 100644 --- a/intern/gawain/gawain/primitive.h +++ b/intern/gawain/gawain/gwn_primitive.h @@ -11,7 +11,7 @@ #pragma once -#include "common.h" +#include "gwn_common.h" typedef enum { GWN_PRIM_POINTS, diff --git a/intern/gawain/gawain/primitive_private.h b/intern/gawain/gawain/gwn_primitive_private.h index d959cd89852..d959cd89852 100644 --- a/intern/gawain/gawain/primitive_private.h +++ b/intern/gawain/gawain/gwn_primitive_private.h diff --git a/intern/gawain/gawain/gwn_shader_interface.h b/intern/gawain/gawain/gwn_shader_interface.h new file mode 100644 index 00000000000..345ad8d389b --- /dev/null +++ b/intern/gawain/gawain/gwn_shader_interface.h @@ -0,0 +1,74 @@ + +// 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/. + +#pragma once + +#include "gwn_common.h" + +typedef enum { + GWN_UNIFORM_NONE = 0, // uninitialized/unknown + + GWN_UNIFORM_MODEL, // mat4 ModelMatrix + GWN_UNIFORM_VIEW, // mat4 ViewMatrix + GWN_UNIFORM_MODELVIEW, // mat4 ModelViewMatrix + GWN_UNIFORM_PROJECTION, // mat4 ProjectionMatrix + GWN_UNIFORM_VIEWPROJECTION, // mat4 ViewProjectionMatrix + GWN_UNIFORM_MVP, // mat4 ModelViewProjectionMatrix + + GWN_UNIFORM_MODEL_INV, // mat4 ModelMatrixInverse + GWN_UNIFORM_VIEW_INV, // mat4 ViewMatrixInverse + GWN_UNIFORM_MODELVIEW_INV, // mat4 ModelViewMatrixInverse + GWN_UNIFORM_PROJECTION_INV, // mat4 ProjectionMatrixInverse + GWN_UNIFORM_VIEWPROJECTION_INV, // mat4 ViewProjectionMatrixInverse + + GWN_UNIFORM_NORMAL, // mat3 NormalMatrix + GWN_UNIFORM_WORLDNORMAL, // mat3 WorldNormalMatrix + GWN_UNIFORM_CAMERATEXCO, // vec4 CameraTexCoFactors + GWN_UNIFORM_ORCO, // vec3 OrcoTexCoFactors[] + GWN_UNIFORM_CLIPPLANES, // vec4 ClipPlanes[] + + GWN_UNIFORM_COLOR, // vec4 color + GWN_UNIFORM_EYE, // vec3 eye + + GWN_UNIFORM_CUSTOM, // custom uniform, not one of the above built-ins + + GWN_NUM_UNIFORMS, // Special value, denotes number of builtin uniforms. +} Gwn_UniformBuiltin; + +typedef struct Gwn_ShaderInput { + struct Gwn_ShaderInput* next; + uint32_t name_offset; + unsigned name_hash; + Gwn_UniformBuiltin builtin_type; // only for uniform inputs + GLenum gl_type; // only for attrib inputs + GLint size; // only for attrib inputs + GLint location; +} Gwn_ShaderInput; + +#define GWN_NUM_SHADERINTERFACE_BUCKETS 257 + +typedef struct Gwn_ShaderInterface { + GLint program; + uint32_t name_buffer_offset; + Gwn_ShaderInput* attrib_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]; + Gwn_ShaderInput* uniform_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]; + Gwn_ShaderInput* ubo_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]; + Gwn_ShaderInput* builtin_uniforms[GWN_NUM_UNIFORMS]; + char* name_buffer; +} Gwn_ShaderInterface; + +Gwn_ShaderInterface* GWN_shaderinterface_create(GLint program_id); +void GWN_shaderinterface_discard(Gwn_ShaderInterface*); + +const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface*, const char* name); +const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface*, Gwn_UniformBuiltin); +const Gwn_ShaderInput* GWN_shaderinterface_ubo(const Gwn_ShaderInterface*, const char* name); +const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface*, const char* name); diff --git a/intern/gawain/gawain/vertex_buffer.h b/intern/gawain/gawain/gwn_vertex_buffer.h index 46f83f5c551..5ad82251e79 100644 --- a/intern/gawain/gawain/vertex_buffer.h +++ b/intern/gawain/gawain/gwn_vertex_buffer.h @@ -11,7 +11,7 @@ #pragma once -#include "vertex_format.h" +#include "gwn_vertex_format.h" // How to create a Gwn_VertBuf: // 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts) @@ -21,7 +21,7 @@ // Is Gwn_VertBuf always used as part of a Gwn_Batch? -typedef struct { +typedef struct Gwn_VertBuf { Gwn_VertFormat format; unsigned vertex_ct; GLubyte* data; // NULL indicates data in VRAM (unmapped) or not yet allocated @@ -31,6 +31,7 @@ typedef struct { Gwn_VertBuf* GWN_vertbuf_create(void); Gwn_VertBuf* GWN_vertbuf_create_with_format(const Gwn_VertFormat*); +void GWN_vertbuf_clear(Gwn_VertBuf* verts); void GWN_vertbuf_discard(Gwn_VertBuf*); void GWN_vertbuf_init(Gwn_VertBuf*); @@ -49,6 +50,35 @@ void GWN_vertbuf_attr_set(Gwn_VertBuf*, unsigned a_idx, unsigned v_idx, const vo void GWN_vertbuf_attr_fill(Gwn_VertBuf*, unsigned a_idx, const void* data); // tightly packed, non interleaved input data void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf*, unsigned a_idx, unsigned stride, const void* data); +// For low level access only +typedef struct Gwn_VertBufRaw { + unsigned size; + unsigned stride; + GLubyte* data; + GLubyte* data_init; +#if TRUST_NO_ONE + // Only for overflow check + GLubyte* _data_end; +#endif +} Gwn_VertBufRaw; + +GWN_INLINE void *GWN_vertbuf_raw_step(Gwn_VertBufRaw *a) + { + GLubyte* data = a->data; + a->data += a->stride; +#if TRUST_NO_ONE + assert(data < a->_data_end); +#endif + return (void *)data; + } + +GWN_INLINE unsigned GWN_vertbuf_raw_used(Gwn_VertBufRaw *a) + { + return ((a->data - a->data_init) / a->stride); + } + +void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf*, unsigned a_idx, Gwn_VertBufRaw *access); + // TODO: decide whether to keep the functions below // doesn't immediate mode satisfy these needs? diff --git a/intern/gawain/gawain/vertex_format.h b/intern/gawain/gawain/gwn_vertex_format.h index 3b2a3be4209..348e6399afa 100644 --- a/intern/gawain/gawain/vertex_format.h +++ b/intern/gawain/gawain/gwn_vertex_format.h @@ -11,7 +11,7 @@ #pragma once -#include "common.h" +#include "gwn_common.h" #define GWN_VERT_ATTR_MAX_LEN 16 #define MAX_ATTRIB_NAMES 3 @@ -38,7 +38,7 @@ typedef enum { GWN_FETCH_INT_TO_FLOAT // 127 (any int type) -> 127.0 } Gwn_VertFetchMode; -typedef struct { +typedef struct Gwn_VertAttr { Gwn_VertCompType comp_type; unsigned gl_comp_type; unsigned comp_ct; // 1 to 4 @@ -49,7 +49,7 @@ typedef struct { unsigned name_ct; } Gwn_VertAttr; -typedef struct { +typedef struct Gwn_VertFormat { unsigned attrib_ct; // 0 to 16 (GWN_VERT_ATTR_MAX_LEN) unsigned name_ct; // total count of active vertex attrib unsigned stride; // stride in bytes, 1 to 256 @@ -67,12 +67,12 @@ void GWN_vertformat_alias_add(Gwn_VertFormat*, const char* alias); // format conversion -typedef struct { +typedef struct Gwn_PackedNormal { int x : 10; int y : 10; int z : 10; int w : 2; // 0 by default, can manually set to { -2, -1, 0, 1 } -} PackedNormal; +} Gwn_PackedNormal; -PackedNormal convert_i10_v3(const float data[3]); -PackedNormal convert_i10_s3(const short data[3]); +Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3]); +Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3]); diff --git a/intern/gawain/gawain/vertex_format_private.h b/intern/gawain/gawain/gwn_vertex_format_private.h index c1a0f734eda..c1a0f734eda 100644 --- a/intern/gawain/gawain/vertex_format_private.h +++ b/intern/gawain/gawain/gwn_vertex_format_private.h diff --git a/intern/gawain/gawain/shader_interface.h b/intern/gawain/gawain/shader_interface.h deleted file mode 100644 index 5304cc9fa51..00000000000 --- a/intern/gawain/gawain/shader_interface.h +++ /dev/null @@ -1,53 +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/. - -#pragma once - -#include "common.h" - -typedef enum { - GWN_UNIFORM_NONE, // uninitialized/unknown - - GWN_UNIFORM_MODELVIEW, // mat4 ModelViewMatrix - GWN_UNIFORM_PROJECTION, // mat4 ProjectionMatrix - GWN_UNIFORM_MVP, // mat4 ModelViewProjectionMatrix - - GWN_UNIFORM_MODELVIEW_INV, // mat4 ModelViewInverseMatrix - GWN_UNIFORM_PROJECTION_INV, // mat4 ProjectionInverseMatrix - - GWN_UNIFORM_NORMAL, // mat3 NormalMatrix - - GWN_UNIFORM_COLOR, // vec4 color - - GWN_UNIFORM_CUSTOM // custom uniform, not one of the above built-ins -} Gwn_UniformBuiltin; - -typedef struct { - const char* name; - unsigned name_hash; - GLenum gl_type; - Gwn_UniformBuiltin builtin_type; // only for uniform inputs - GLint size; - GLint location; -} Gwn_ShaderInput; - -typedef struct { - uint16_t uniform_ct; - uint16_t attrib_ct; - Gwn_ShaderInput inputs[0]; // dynamic size, uniforms followed by attribs -} Gwn_ShaderInterface; - -Gwn_ShaderInterface* GWN_shaderinterface_create(GLint program_id); -void GWN_shaderinterface_discard(Gwn_ShaderInterface*); - -const Gwn_ShaderInput* GWN_shaderinterface_uniform(const Gwn_ShaderInterface*, const char* name); -const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface*, Gwn_UniformBuiltin); -const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface*, const char* name); 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 - } |