diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-07-17 15:46:44 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-07-18 01:17:57 +0300 |
commit | 6329629bb9eab86a989367a148154a7ebfa074df (patch) | |
tree | aafb933f0abe67c4ed24ade0c4675a1b63aa4c18 | |
parent | a28fd8fee2f7d0f953b0c3603edfa18669b6c5fe (diff) |
GWN: Port to GPU module: codestyle & licence
28 files changed, 2155 insertions, 1704 deletions
diff --git a/intern/gawain/gawain/gwn_attr_binding.h b/intern/gawain/gawain/gwn_attr_binding.h index a209e1c4f0f..8030e86ea92 100644 --- a/intern/gawain/gawain/gwn_attr_binding.h +++ b/intern/gawain/gawain/gwn_attr_binding.h @@ -1,19 +1,42 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain vertex attribute binding -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/gwn_attr_binding.h + * \ingroup gpu + * + * Gawain vertex attribute binding + */ -#pragma once +#ifndef __GWN_ATTR_BINDING_H__ +#define __GWN_ATTR_BINDING_H__ #include "gwn_common.h" 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 + uint64_t loc_bits; /* store 4 bits for each of the 16 attribs */ + uint16_t enabled_bits; /* 1 bit for each attrib */ } Gwn_AttrBinding; + +#endif /* __GWN_ATTR_BINDING_H__ */ diff --git a/intern/gawain/gawain/gwn_attr_binding_private.h b/intern/gawain/gawain/gwn_attr_binding_private.h index 300945d464b..cead1896ec7 100644 --- a/intern/gawain/gawain/gwn_attr_binding_private.h +++ b/intern/gawain/gawain/gwn_attr_binding_private.h @@ -1,15 +1,36 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain vertex attribute binding -// -// 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/. +/** \file blender/gpu/gwn_attr_binding_private.h + * \ingroup gpu + * + * Gawain vertex attribute binding + */ -#pragma once +#ifndef __GWN_ATTR_BINDING_PRIVATE_H__ +#define __GWN_ATTR_BINDING_PRIVATE_H__ #include "gwn_vertex_format.h" #include "gwn_shader_interface.h" @@ -18,3 +39,5 @@ void AttribBinding_clear(Gwn_AttrBinding*); void get_attrib_locations(const Gwn_VertFormat*, Gwn_AttrBinding*, const Gwn_ShaderInterface*); unsigned read_attrib_location(const Gwn_AttrBinding*, unsigned a_idx); + +#endif /* __GWN_ATTR_BINDING_PRIVATE_H__ */ diff --git a/intern/gawain/gawain/gwn_batch.h b/intern/gawain/gawain/gwn_batch.h index 734df3c91b6..a7a54502cc0 100644 --- a/intern/gawain/gawain/gwn_batch.h +++ b/intern/gawain/gawain/gwn_batch.h @@ -1,15 +1,37 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_batch.h + * \ingroup gpu + * + * Gawain geometry batch + * Contains VAOs + VBOs + Shader representing a drawable entity. + */ + +#ifndef __GWN_BATCH_H__ +#define __GWN_BATCH_H__ #include "gwn_vertex_buffer.h" #include "gwn_element.h" @@ -27,43 +49,43 @@ typedef enum { #define GWN_BATCH_VAO_DYN_ALLOC_COUNT 16 typedef struct Gwn_Batch { - // geometry - Gwn_VertBuf* verts[GWN_BATCH_VBO_MAX_LEN]; // verts[0] is required, others can be NULL - Gwn_VertBuf* inst; // instance attribs - Gwn_IndexBuf* elem; // NULL if element list not needed + /* geometry */ + Gwn_VertBuf* verts[GWN_BATCH_VBO_MAX_LEN]; /* verts[0] is required, others can be NULL */ + Gwn_VertBuf* inst; /* instance attribs */ + Gwn_IndexBuf* elem; /* NULL if element list not needed */ uint32_t gl_prim_type; - // cached values (avoid dereferencing later) + /* cached values (avoid dereferencing later) */ uint32_t vao_id; uint32_t program; const struct Gwn_ShaderInterface* interface; - // book-keeping - unsigned owns_flag; - struct Gwn_Context *context; // used to free all vaos. this implies all vaos were created under the same context. + /* book-keeping */ + uint owns_flag; + struct Gwn_Context *context; /* used to free all vaos. this implies all vaos were created under the same context. */ Gwn_BatchPhase phase; bool program_in_use; - // Vao management: remembers all geometry state (vertex attrib bindings & element buffer) - // for each shader interface. Start with a static number of vaos and fallback to dynamic count - // if necessary. Once a batch goes dynamic it does not go back. + /* Vao management: remembers all geometry state (vertex attrib bindings & element buffer) + * for each shader interface. Start with a static number of vaos and fallback to dynamic count + * if necessary. Once a batch goes dynamic it does not go back. */ bool is_dynamic_vao_count; union { - // Static handle count + /* Static handle count */ struct { const struct Gwn_ShaderInterface* interfaces[GWN_BATCH_VAO_STATIC_LEN]; uint32_t vao_ids[GWN_BATCH_VAO_STATIC_LEN]; } static_vaos; - // Dynamic handle count + /* Dynamic handle count */ struct { - unsigned count; + uint count; const struct Gwn_ShaderInterface** interfaces; uint32_t* vao_ids; } dynamic_vaos; }; - // XXX This is the only solution if we want to have some data structure using - // batches as key to identify nodes. We must destroy these nodes with this callback. + /* XXX This is the only solution if we want to have some data structure using + * batches as key to identify nodes. We must destroy these nodes with this callback. */ void (*free_callback)(struct Gwn_Batch*, void*); void* callback_data; } Gwn_Batch; @@ -75,8 +97,8 @@ enum { 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); +Gwn_Batch* GWN_batch_create_ex(Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, uint owns_flag); +void GWN_batch_init_ex(Gwn_Batch*, Gwn_PrimType, Gwn_VertBuf*, Gwn_IndexBuf*, uint owns_flag); Gwn_Batch* GWN_batch_duplicate(Gwn_Batch* batch_src); #define GWN_batch_create(prim, verts, elem) \ @@ -84,11 +106,11 @@ Gwn_Batch* GWN_batch_duplicate(Gwn_Batch* batch_src); #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(Gwn_Batch*); /* verts & elem are not discarded */ void GWN_batch_callback_free_set(Gwn_Batch*, void (*callback)(Gwn_Batch*, void*), void*); -void GWN_batch_instbuf_set(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); // Instancing +void GWN_batch_instbuf_set(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); /* Instancing */ int GWN_batch_vertbuf_add_ex(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); @@ -97,10 +119,10 @@ int GWN_batch_vertbuf_add_ex(Gwn_Batch*, Gwn_VertBuf*, bool own_vbo); void GWN_batch_program_set_no_use(Gwn_Batch*, uint32_t program, const Gwn_ShaderInterface*); void GWN_batch_program_set(Gwn_Batch*, uint32_t program, const Gwn_ShaderInterface*); -// 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. +/* 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. */ -void GWN_batch_program_use_begin(Gwn_Batch*); // call before Batch_Uniform (temp hack?) +void GWN_batch_program_use_begin(Gwn_Batch*); /* call before Batch_Uniform (temp hack?) */ void GWN_batch_program_use_end(Gwn_Batch*); void GWN_batch_uniform_1ui(Gwn_Batch*, const char* name, int value); @@ -119,44 +141,44 @@ void GWN_batch_uniform_mat4(Gwn_Batch*, const char* name, const float data[4][4] void GWN_batch_draw(Gwn_Batch*); -// This does not bind/unbind shader and does not call GPU_matrix_bind() +/* This does not bind/unbind shader and does not call GPU_matrix_bind() */ void GWN_batch_draw_range_ex(Gwn_Batch*, int v_first, int v_count, bool force_instance); -// Does not even need batch +/* Does not even need batch */ void GWN_draw_primitive(Gwn_PrimType, int v_count); -#if 0 // future plans +#if 0 /* future plans */ -// Can multiple batches share a Gwn_VertBuf? Use ref count? +/* Can multiple batches share a Gwn_VertBuf? Use ref count? */ -// We often need a batch with its own data, to be created and discarded together. -// WithOwn variants reduce number of system allocations. +/* We often need a batch with its own data, to be created and discarded together. */ +/* WithOwn variants reduce number of system allocations. */ typedef struct BatchWithOwnVertexBuffer { Gwn_Batch batch; - Gwn_VertBuf verts; // link batch.verts to this + Gwn_VertBuf verts; /* link batch.verts to this */ } BatchWithOwnVertexBuffer; typedef struct BatchWithOwnElementList { Gwn_Batch batch; - Gwn_IndexBuf elem; // link batch.elem to this + Gwn_IndexBuf elem; /* link batch.elem to this */ } BatchWithOwnElementList; typedef struct BatchWithOwnVertexBufferAndElementList { Gwn_Batch batch; - Gwn_IndexBuf elem; // link batch.elem to this - Gwn_VertBuf verts; // link batch.verts to this + Gwn_IndexBuf elem; /* link batch.elem to this */ + Gwn_VertBuf verts; /* link batch.verts to this */ } BatchWithOwnVertexBufferAndElementList; -Gwn_Batch* create_BatchWithOwnVertexBuffer(Gwn_PrimType, Gwn_VertFormat*, unsigned v_len, Gwn_IndexBuf*); -Gwn_Batch* create_BatchWithOwnElementList(Gwn_PrimType, Gwn_VertBuf*, unsigned prim_len); -Gwn_Batch* create_BatchWithOwnVertexBufferAndElementList(Gwn_PrimType, Gwn_VertFormat*, unsigned v_len, unsigned prim_len); -// verts: shared, own -// elem: none, shared, own +Gwn_Batch* create_BatchWithOwnVertexBuffer(Gwn_PrimType, Gwn_VertFormat*, uint v_len, Gwn_IndexBuf*); +Gwn_Batch* create_BatchWithOwnElementList(Gwn_PrimType, Gwn_VertBuf*, uint prim_len); +Gwn_Batch* create_BatchWithOwnVertexBufferAndElementList(Gwn_PrimType, Gwn_VertFormat*, uint v_len, uint prim_len); +/* verts: shared, own */ +/* elem: none, shared, own */ Gwn_Batch* create_BatchInGeneral(Gwn_PrimType, VertexBufferStuff, ElementListStuff); -#endif // future plans +#endif /* future plans */ /* Macros */ @@ -167,3 +189,5 @@ Gwn_Batch* create_BatchInGeneral(Gwn_PrimType, VertexBufferStuff, ElementListStu batch = NULL; \ } \ } while (0) + +#endif /* __GWN_BATCH_H__ */ diff --git a/intern/gawain/gawain/gwn_batch_private.h b/intern/gawain/gawain/gwn_batch_private.h index 6503429c237..e7d42ff0249 100644 --- a/intern/gawain/gawain/gwn_batch_private.h +++ b/intern/gawain/gawain/gwn_batch_private.h @@ -1,15 +1,37 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain context -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2018 Mike Erwin, Clément Foucault -// -// 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/. +/** \file blender/gpu/gwn_batch_private.h + * \ingroup gpu + * + * Gawain geometry batch + * Contains VAOs + VBOs + Shader representing a drawable entity. + */ -#pragma once +#ifndef __GWN_BATCH_PRIVATE_H__ +#define __GWN_BATCH_PRIVATE_H__ #ifdef __cplusplus extern "C" { @@ -28,3 +50,5 @@ void gwn_context_remove_batch(Gwn_Context*, Gwn_Batch*); #ifdef __cplusplus } #endif + +#endif /* __GWN_BATCH_PRIVATE_H__ */ diff --git a/intern/gawain/gawain/gwn_buffer_id.h b/intern/gawain/gawain/gwn_buffer_id.h index 6f51ca6905d..0c2537a5d5a 100644 --- a/intern/gawain/gawain/gwn_buffer_id.h +++ b/intern/gawain/gawain/gwn_buffer_id.h @@ -1,20 +1,41 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain buffer IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/gwn_buffer_id.h + * \ingroup gpu + * + * Gawain buffer IDs + */ -#pragma once +#ifndef __GWN_BUFFER_ID_H__ +#define __GWN_BUFFER_ID_H__ -// Manage GL buffer IDs in a thread-safe way -// Use these instead of glGenBuffers & its friends -// - alloc must be called from main thread -// - free can be called from any thread +/* Manage GL buffer IDs in a thread-safe way + * Use these instead of glGenBuffers & its friends + * - alloc must be called from main thread + * - free can be called from any thread */ #ifdef __cplusplus extern "C" { @@ -28,3 +49,5 @@ void GWN_buf_id_free(GLuint buffer_id); #ifdef __cplusplus } #endif + +#endif /* __GWN_BUFFER_ID_H__ */ diff --git a/intern/gawain/gawain/gwn_common.h b/intern/gawain/gawain/gwn_common.h index 6a56543da40..2587e8670a9 100644 --- a/intern/gawain/gawain/gwn_common.h +++ b/intern/gawain/gawain/gwn_common.h @@ -1,22 +1,41 @@ - -// Gawain common #defines and #includes -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_common.h + * \ingroup gpu + */ + +#ifndef __GWN_COMMON_H__ +#define __GWN_COMMON_H__ #define PROGRAM_NO_OPTI 0 #if defined(NDEBUG) #define TRUST_NO_ONE 0 #else - // strict error checking, enabled for debug builds during early development + /* strict error checking, enabled for debug builds during early development */ #define TRUST_NO_ONE 1 #endif @@ -24,6 +43,7 @@ #include <GL/glew.h> #endif +#include <stdlib.h> #include <stdbool.h> #include <stdint.h> @@ -37,3 +57,5 @@ #else # define GWN_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) #endif + +#endif /* __GWN_COMMON_H__ */ diff --git a/intern/gawain/gawain/gwn_context.h b/intern/gawain/gawain/gwn_context.h index 3addce762b3..7784fc30562 100644 --- a/intern/gawain/gawain/gwn_context.h +++ b/intern/gawain/gawain/gwn_context.h @@ -1,17 +1,36 @@ - -// Gawain context -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2018 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 - -// This interface allow Gawain to manage VAOs for mutiple context and threads. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_context.h + * \ingroup gpu + * + * This interface allow Gawain to manage VAOs for mutiple context and threads. + */ + +#ifndef __GWN_CONTEXT_H__ +#define __GWN_CONTEXT_H__ #ifdef __cplusplus extern "C" { @@ -32,3 +51,5 @@ Gwn_Context* GWN_context_active_get(void); #ifdef __cplusplus } #endif + +#endif /* __GWN_CONTEXT_H__ */ diff --git a/intern/gawain/gawain/gwn_element.h b/intern/gawain/gawain/gwn_element.h index 53a54cdfd76..2d5b6bb692b 100644 --- a/intern/gawain/gawain/gwn_element.h +++ b/intern/gawain/gawain/gwn_element.h @@ -1,15 +1,36 @@ - -// Gawain element list (AKA index buffer) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_element.h + * \ingroup gpu + * + * Gawain element list (AKA index buffer) + */ + +#ifndef __GWN_ELEMENT_H__ +#define __GWN_ELEMENT_H__ #include "gwn_primitive.h" @@ -18,50 +39,50 @@ #define GWN_PRIM_RESTART 0xFFFFFFFF typedef enum { - GWN_INDEX_U8, // GL has this, Vulkan does not + GWN_INDEX_U8, /* GL has this, Vulkan does not */ GWN_INDEX_U16, GWN_INDEX_U32 } Gwn_IndexBufType; typedef struct Gwn_IndexBuf { - unsigned index_len; + uint index_len; #if GWN_TRACK_INDEX_RANGE Gwn_IndexBufType index_type; uint32_t gl_index_type; - unsigned min_index; - unsigned max_index; - unsigned base_index; + uint min_index; + uint max_index; + uint base_index; #endif - uint32_t vbo_id; // 0 indicates not yet sent to VRAM + uint32_t vbo_id; /* 0 indicates not yet sent to VRAM */ bool use_prim_restart; } Gwn_IndexBuf; void GWN_indexbuf_use(Gwn_IndexBuf*); -unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf*); +uint GWN_indexbuf_size_get(const Gwn_IndexBuf*); typedef struct Gwn_IndexBufBuilder { - unsigned max_allowed_index; - unsigned max_index_len; - unsigned index_len; + uint max_allowed_index; + uint max_index_len; + uint index_len; Gwn_PrimType prim_type; - unsigned* data; + uint* data; bool use_prim_restart; } Gwn_IndexBufBuilder; -// supports all primitive types. -void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned index_len, unsigned vertex_len, bool use_prim_restart); +/* supports all primitive types. */ +void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder*, Gwn_PrimType, uint index_len, uint vertex_len, bool use_prim_restart); -// supports only GWN_PRIM_POINTS, GWN_PRIM_LINES and GWN_PRIM_TRIS. -void GWN_indexbuf_init(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned prim_len, unsigned vertex_len); +/* supports only GWN_PRIM_POINTS, GWN_PRIM_LINES and GWN_PRIM_TRIS. */ +void GWN_indexbuf_init(Gwn_IndexBufBuilder*, Gwn_PrimType, uint prim_len, uint vertex_len); -void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder*, unsigned v); +void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder*, uint v); void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder*); -void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder*, unsigned v); -void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2); -void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2, unsigned v3); -void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2, unsigned v3, unsigned v4); +void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder*, uint v); +void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder*, uint v1, uint v2); +void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder*, uint v1, uint v2, uint v3); +void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder*, uint v1, uint v2, uint v3, uint v4); Gwn_IndexBuf* GWN_indexbuf_build(Gwn_IndexBufBuilder*); void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder*, Gwn_IndexBuf*); @@ -77,3 +98,5 @@ void GWN_indexbuf_discard(Gwn_IndexBuf*); elem = NULL; \ } \ } while (0) + +#endif /* __GWN_ELEMENT_H__ */ diff --git a/intern/gawain/gawain/gwn_imm_util.h b/intern/gawain/gawain/gwn_imm_util.h index 5d17ec50669..e512d071dca 100644 --- a/intern/gawain/gawain/gwn_imm_util.h +++ b/intern/gawain/gawain/gwn_imm_util.h @@ -1,22 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain immediate mode drawing utilities -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/gwn_imm_util.h + * \ingroup gpu + * + * Gawain element list (AKA index buffer) + */ -#pragma once +#ifndef __GWN_IMM_UTIL_H__ +#define __GWN_IMM_UTIL_H__ +#include <stdlib.h> -// Draw 2D rectangles (replaces glRect functions) -// caller is reponsible for vertex format & shader -void immRectf(unsigned pos, float x1, float y1, float x2, float y2); -void immRecti(unsigned pos, int x1, int y1, int x2, int y2); +/* Draw 2D rectangles (replaces glRect functions) */ +/* caller is reponsible for vertex format & shader */ +void immRectf(uint pos, float x1, float y1, float x2, float y2); +void immRecti(uint pos, int x1, int y1, int x2, int y2); -// Same as immRectf/immRecti but does not call immBegin/immEnd. To use with GWN_PRIM_TRIS. -void immRectf_fast_with_color(unsigned pos, unsigned col, float x1, float y1, float x2, float y2, const float color[4]); -void immRecti_fast_with_color(unsigned pos, unsigned col, int x1, int y1, int x2, int y2, const float color[4]); +/* Same as immRectf/immRecti but does not call immBegin/immEnd. To use with GWN_PRIM_TRIS. */ +void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]); +void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]); + +#endif /* __GWN_IMM_UTIL_H__ */ diff --git a/intern/gawain/gawain/gwn_immediate.h b/intern/gawain/gawain/gwn_immediate.h index c3ea2b911a0..8231942d735 100644 --- a/intern/gawain/gawain/gwn_immediate.h +++ b/intern/gawain/gawain/gwn_immediate.h @@ -1,88 +1,101 @@ - -// Gawain immediate mode work-alike -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_immediate.h + * \ingroup gpu + * + * Gawain immediate mode work-alike + */ + +#ifndef __GWN_IMMEDIATE_H__ +#define __GWN_IMMEDIATE_H__ #include "gwn_vertex_format.h" #include "gwn_primitive.h" #include "gwn_shader_interface.h" - -#define IMM_BATCH_COMBO 1 - - -Gwn_VertFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib - -void immBindProgram(uint32_t program, const Gwn_ShaderInterface*); // every immBegin must have a program bound first -void immUnbindProgram(void); // call after your last immEnd, or before binding another program - -void immBegin(Gwn_PrimType, unsigned vertex_len); // must supply exactly vertex_len vertices -void immBeginAtMost(Gwn_PrimType, unsigned max_vertex_len); // can supply fewer vertices -void immEnd(void); // finishes and draws - -#if IMM_BATCH_COMBO #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. -Gwn_Batch* immBeginBatch(Gwn_PrimType, unsigned vertex_len); -Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType, unsigned vertex_len); -#endif +Gwn_VertFormat* immVertexFormat(void); /* returns a cleared vertex format, ready for add_attrib. */ + +void immBindProgram(uint32_t program, const Gwn_ShaderInterface*); /* every immBegin must have a program bound first. */ +void immUnbindProgram(void); /* call after your last immEnd, or before binding another program. */ -// provide attribute values that can change per vertex -// first vertex after immBegin must have all its attributes specified -// skipped attributes will continue using the previous value for that attrib_id -void immAttrib1f(unsigned attrib_id, float x); -void immAttrib2f(unsigned attrib_id, float x, float y); -void immAttrib3f(unsigned attrib_id, float x, float y, float z); -void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w); +void immBegin(Gwn_PrimType, uint vertex_len); /* must supply exactly vertex_len vertices. */ +void immBeginAtMost(Gwn_PrimType, uint max_vertex_len); /* can supply fewer vertices. */ +void immEnd(void); /* finishes and draws. */ -void immAttrib2i(unsigned attrib_id, int x, int y); +/* 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. */ +Gwn_Batch* immBeginBatch(Gwn_PrimType, uint vertex_len); +Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType, uint vertex_len); -void immAttrib1u(unsigned attrib_id, unsigned x); +/* Provide attribute values that can change per vertex. */ +/* First vertex after immBegin must have all its attributes specified. */ +/* Skipped attributes will continue using the previous value for that attrib_id. */ +void immAttrib1f(uint attrib_id, float x); +void immAttrib2f(uint attrib_id, float x, float y); +void immAttrib3f(uint attrib_id, float x, float y, float z); +void immAttrib4f(uint attrib_id, float x, float y, float z, float w); -void immAttrib2s(unsigned attrib_id, short x, short y); +void immAttrib2i(uint attrib_id, int x, int y); -void immAttrib2fv(unsigned attrib_id, const float data[2]); -void immAttrib3fv(unsigned attrib_id, const float data[3]); -void immAttrib4fv(unsigned attrib_id, const float data[4]); +void immAttrib1u(uint attrib_id, uint x); -void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b); -void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a); +void immAttrib2s(uint attrib_id, short x, short y); -void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]); -void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]); +void immAttrib2fv(uint attrib_id, const float data[2]); +void immAttrib3fv(uint attrib_id, const float data[3]); +void immAttrib4fv(uint attrib_id, const float data[4]); -// explicitly skip an attribute -// this advanced option kills automatic value copying for this attrib_id -void immSkipAttrib(unsigned attrib_id); +void immAttrib3ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b); +void immAttrib4ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a); +void immAttrib3ubv(uint attrib_id, const unsigned char data[4]); +void immAttrib4ubv(uint attrib_id, const unsigned char data[4]); -// provide one last attribute value & end the current vertex -// this is most often used for 2D or 3D position (similar to glVertex) -void immVertex2f(unsigned attrib_id, float x, float y); -void immVertex3f(unsigned attrib_id, float x, float y, float z); -void immVertex4f(unsigned attrib_id, float x, float y, float z, float w); +/* Explicitly skip an attribute. */ +/* This advanced option kills automatic value copying for this attrib_id. */ +void immSkipAttrib(uint attrib_id); -void immVertex2i(unsigned attrib_id, int x, int y); +/* Provide one last attribute value & end the current vertex. */ +/* This is most often used for 2D or 3D position (similar to glVertex). */ +void immVertex2f(uint attrib_id, float x, float y); +void immVertex3f(uint attrib_id, float x, float y, float z); +void immVertex4f(uint attrib_id, float x, float y, float z, float w); -void immVertex2s(unsigned attrib_id, short x, short y); +void immVertex2i(uint attrib_id, int x, int y); -void immVertex2fv(unsigned attrib_id, const float data[2]); -void immVertex3fv(unsigned attrib_id, const float data[3]); +void immVertex2s(uint attrib_id, short x, short y); -void immVertex2iv(unsigned attrib_id, const int data[2]); +void immVertex2fv(uint attrib_id, const float data[2]); +void immVertex3fv(uint attrib_id, const float data[3]); +void immVertex2iv(uint attrib_id, const int data[2]); -// provide uniform values that don't change for the entire draw call +/* Provide uniform values that don't change for the entire draw call. */ void immUniform1i(const char* name, int x); void immUniform4iv(const char* name, const int data[4]); void immUniform1f(const char* name, float x); @@ -96,9 +109,8 @@ void immUniform4fv(const char* name, const float data[4]); void immUniformArray4fv(const char* bare_name, const float *data, int count); void immUniformMatrix4fv(const char* name, const float data[4][4]); - -// convenience functions for setting "uniform vec4 color" -// the rgb functions have implicit alpha = 1.0 +/* Convenience functions for setting "uniform vec4 color". */ +/* The rgb functions have implicit alpha = 1.0. */ void immUniformColor4f(float r, float g, float b, float a); void immUniformColor4fv(const float rgba[4]); void immUniformColor3f(float r, float g, float b); @@ -111,10 +123,10 @@ void immUniformColor3ubv(const unsigned char rgb[3]); void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char a); void immUniformColor4ubv(const unsigned char rgba[4]); - -// these are called by the system -- not part of drawing API - +/* These are called by the system -- not part of drawing API. */ void immInit(void); void immActivate(void); void immDeactivate(void); void immDestroy(void); + +#endif /* __GWN_IMMEDIATE_H__ */ diff --git a/intern/gawain/gawain/gwn_primitive.h b/intern/gawain/gawain/gwn_primitive.h index 3359b3582bb..346f77441d3 100644 --- a/intern/gawain/gawain/gwn_primitive.h +++ b/intern/gawain/gawain/gwn_primitive.h @@ -1,15 +1,36 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain geometric primitives -// -// 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/. +/** \file blender/gpu/gwn_primitive.h + * \ingroup gpu + * + * Gawain geometric primitives + */ -#pragma once +#ifndef __GWN_PRIMITIVE_H__ +#define __GWN_PRIMITIVE_H__ #include "gwn_common.h" @@ -18,7 +39,7 @@ typedef enum { GWN_PRIM_LINES, GWN_PRIM_TRIS, GWN_PRIM_LINE_STRIP, - GWN_PRIM_LINE_LOOP, // GL has this, Vulkan does not + GWN_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */ GWN_PRIM_TRI_STRIP, GWN_PRIM_TRI_FAN, @@ -29,7 +50,7 @@ typedef enum { GWN_PRIM_NONE } Gwn_PrimType; -// what types of primitives does each shader expect? +/* what types of primitives does each shader expect? */ typedef enum { GWN_PRIM_CLASS_NONE = 0, GWN_PRIM_CLASS_POINT = (1 << 0), @@ -40,3 +61,5 @@ typedef enum { Gwn_PrimClass GWN_primtype_class(Gwn_PrimType); bool GWN_primtype_belongs_to_class(Gwn_PrimType, Gwn_PrimClass); + +#endif /* __GWN_PRIMITIVE_H__ */ diff --git a/intern/gawain/gawain/gwn_primitive_private.h b/intern/gawain/gawain/gwn_primitive_private.h index d959cd89852..6d3f1e20da7 100644 --- a/intern/gawain/gawain/gwn_primitive_private.h +++ b/intern/gawain/gawain/gwn_primitive_private.h @@ -1,14 +1,37 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain geometric primitives (private interface for use inside Gawain) -// -// 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/. +/** \file blender/gpu/gwn_primitive_private.h + * \ingroup gpu + * + * Gawain geometric primitives + */ -#pragma once +#ifndef __GWN_PRIMITIVE_PRIVATE_H__ +#define __GWN_PRIMITIVE_PRIVATE_H__ GLenum convert_prim_type_to_gl(Gwn_PrimType); + +#endif /* __GWN_PRIMITIVE_PRIVATE_H__ */ diff --git a/intern/gawain/gawain/gwn_shader_interface.h b/intern/gawain/gawain/gwn_shader_interface.h index b27b12c18d8..4b20719b329 100644 --- a/intern/gawain/gawain/gwn_shader_interface.h +++ b/intern/gawain/gawain/gwn_shader_interface.h @@ -1,55 +1,76 @@ - -// 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_shader_interface.h + * \ingroup gpu + * + * Gawain shader interface (C --> GLSL) + */ + +#ifndef __GWN_SHADER_INTERFACE_H__ +#define __GWN_SHADER_INTERFACE_H__ #include "gwn_common.h" typedef enum { - GWN_UNIFORM_NONE = 0, // uninitialized/unknown + 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, /* 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_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_NORMAL, /* mat3 NormalMatrix */ + GWN_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */ + GWN_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */ + GWN_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ - GWN_UNIFORM_COLOR, // vec4 color - GWN_UNIFORM_EYE, // vec3 eye - GWN_UNIFORM_CALLID, // int callId + GWN_UNIFORM_COLOR, /* vec4 color */ + GWN_UNIFORM_EYE, /* vec3 eye */ + GWN_UNIFORM_CALLID, /* int callId */ - GWN_UNIFORM_CUSTOM, // custom uniform, not one of the above built-ins + GWN_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */ - GWN_NUM_UNIFORMS, // Special value, denotes number of builtin uniforms. + 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 - uint32_t gl_type; // only for attrib inputs - int32_t size; // only for attrib inputs + uint name_hash; + Gwn_UniformBuiltin builtin_type; /* only for uniform inputs */ + uint32_t gl_type; /* only for attrib inputs */ + int32_t size; /* only for attrib inputs */ int32_t location; } Gwn_ShaderInput; @@ -64,8 +85,8 @@ typedef struct Gwn_ShaderInterface { Gwn_ShaderInput* ubo_buckets[GWN_NUM_SHADERINTERFACE_BUCKETS]; Gwn_ShaderInput* builtin_uniforms[GWN_NUM_UNIFORMS]; char* name_buffer; - struct Gwn_Batch** batches; // references to batches using this interface - unsigned batches_len; + struct Gwn_Batch** batches; /* references to batches using this interface */ + uint batches_len; } Gwn_ShaderInterface; Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program_id); @@ -76,6 +97,8 @@ const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInter const Gwn_ShaderInput* GWN_shaderinterface_ubo(const Gwn_ShaderInterface*, const char* name); const Gwn_ShaderInput* GWN_shaderinterface_attr(const Gwn_ShaderInterface*, const char* name); -// keep track of batches using this interface +/* keep track of batches using this interface */ void GWN_shaderinterface_add_batch_ref(Gwn_ShaderInterface*, struct Gwn_Batch*); void GWN_shaderinterface_remove_batch_ref(Gwn_ShaderInterface*, struct Gwn_Batch*); + +#endif /* __GWN_SHADER_INTERFACE_H__ */ diff --git a/intern/gawain/gawain/gwn_vertex_array_id.h b/intern/gawain/gawain/gwn_vertex_array_id.h index 1c093d428ce..6ba26612b4e 100644 --- a/intern/gawain/gawain/gwn_vertex_array_id.h +++ b/intern/gawain/gawain/gwn_vertex_array_id.h @@ -1,22 +1,41 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain buffer IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2018 Mike Erwin, Clément Foucault -// -// 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/. +/** \file blender/gpu/gwn_vertex_array_id.h + * \ingroup gpu + * + * Manage GL vertex array IDs in a thread-safe way + * Use these instead of glGenBuffers & its friends + * - alloc must be called from a thread that is bound + * to the context that will be used for drawing with + * this vao. + * - free can be called from any thread + */ -#pragma once - -// Manage GL vertex array IDs in a thread-safe way -// Use these instead of glGenBuffers & its friends -// - alloc must be called from a thread that is bound -// to the context that will be used for drawing with -// this vao. -// - free can be called from any thread +#ifndef __GWN_VERTEX_ARRAY_ID_H__ +#define __GWN_VERTEX_ARRAY_ID_H__ #ifdef __cplusplus extern "C" { @@ -32,3 +51,5 @@ void GWN_vao_free(GLuint vao_id, Gwn_Context*); #ifdef __cplusplus } #endif + +#endif /* __GWN_VERTEX_ARRAY_ID_H__ */ diff --git a/intern/gawain/gawain/gwn_vertex_buffer.h b/intern/gawain/gawain/gwn_vertex_buffer.h index 0eac4838e65..84ea12f86d1 100644 --- a/intern/gawain/gawain/gwn_vertex_buffer.h +++ b/intern/gawain/gawain/gwn_vertex_buffer.h @@ -1,42 +1,63 @@ - -// Gawain vertex buffer -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_vertex_buffer.h + * \ingroup gpu + * + * Gawain vertex buffer + */ + +#ifndef __GWN_VERTEX_BUFFER_H__ +#define __GWN_VERTEX_BUFFER_H__ #include "gwn_vertex_format.h" #define VRAM_USAGE 1 -// How to create a Gwn_VertBuf: -// 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts) -// 2) GWN_vertformat_attr_add(verts->format, ...) -// 3) GWN_vertbuf_data_alloc(verts, vertex_len) <-- finalizes/packs vertex format -// 4) GWN_vertbuf_attr_fill(verts, pos, application_pos_buffer) +/* How to create a Gwn_VertBuf: */ +/* 1) verts = GWN_vertbuf_create() or GWN_vertbuf_init(verts) */ +/* 2) GWN_vertformat_attr_add(verts->format, ...) */ +/* 3) GWN_vertbuf_data_alloc(verts, vertex_len) <-- finalizes/packs vertex format */ +/* 4) GWN_vertbuf_attr_fill(verts, pos, application_pos_buffer) */ -// Is Gwn_VertBuf always used as part of a Gwn_Batch? +/* Is Gwn_VertBuf always used as part of a Gwn_Batch? */ typedef enum { - // can be extended to support more types + /* can be extended to support more types */ GWN_USAGE_STREAM, - GWN_USAGE_STATIC, // do not keep data in memory + GWN_USAGE_STATIC, /* do not keep data in memory */ GWN_USAGE_DYNAMIC } Gwn_UsageType; typedef struct Gwn_VertBuf { Gwn_VertFormat format; - unsigned vertex_len; /* number of verts we want to draw */ - unsigned vertex_alloc; /* number of verts data */ + uint vertex_len; /* number of verts we want to draw */ + uint vertex_alloc; /* number of verts data */ bool dirty; - unsigned char* data; // NULL indicates data in VRAM (unmapped) - uint32_t vbo_id; // 0 indicates not yet allocated - Gwn_UsageType usage; // usage hint for GL optimisation + unsigned char* data; /* NULL indicates data in VRAM (unmapped) */ + uint32_t vbo_id; /* 0 indicates not yet allocated */ + Gwn_UsageType usage; /* usage hint for GL optimisation */ } Gwn_VertBuf; Gwn_VertBuf* GWN_vertbuf_create(Gwn_UsageType); @@ -53,73 +74,71 @@ void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf*, const Gwn_VertFormat*, Gwn_Us #define GWN_vertbuf_init_with_format(verts, format) \ GWN_vertbuf_init_with_format_ex(verts, format, GWN_USAGE_STATIC) -unsigned GWN_vertbuf_size_get(const Gwn_VertBuf*); -void GWN_vertbuf_data_alloc(Gwn_VertBuf*, unsigned v_len); -void GWN_vertbuf_data_resize(Gwn_VertBuf*, unsigned v_len); -void GWN_vertbuf_vertex_count_set(Gwn_VertBuf*, unsigned v_len); +uint GWN_vertbuf_size_get(const Gwn_VertBuf*); +void GWN_vertbuf_data_alloc(Gwn_VertBuf*, uint v_len); +void GWN_vertbuf_data_resize(Gwn_VertBuf*, uint v_len); +void GWN_vertbuf_vertex_count_set(Gwn_VertBuf*, uint v_len); -// The most important set_attrib variant is the untyped one. Get it right first. -// It takes a void* so the app developer is responsible for matching their app data types -// to the vertex attribute's type and component count. They're in control of both, so this -// should not be a problem. +/* The most important set_attrib variant is the untyped one. Get it right first. */ +/* It takes a void* so the app developer is responsible for matching their app data types */ +/* to the vertex attribute's type and component count. They're in control of both, so this */ +/* should not be a problem. */ -void GWN_vertbuf_attr_set(Gwn_VertBuf*, unsigned a_idx, unsigned v_idx, const void* data); -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); +void GWN_vertbuf_attr_set(Gwn_VertBuf*, uint a_idx, uint v_idx, const void* data); +void GWN_vertbuf_attr_fill(Gwn_VertBuf*, uint a_idx, const void* data); /* tightly packed, non interleaved input data */ +void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf*, uint a_idx, uint stride, const void* data); -// For low level access only +/* For low level access only */ typedef struct Gwn_VertBufRaw { - unsigned size; - unsigned stride; + uint size; + uint stride; unsigned char* data; unsigned char* data_init; #if TRUST_NO_ONE - // Only for overflow check + /* Only for overflow check */ unsigned char* _data_end; #endif } Gwn_VertBufRaw; GWN_INLINE void *GWN_vertbuf_raw_step(Gwn_VertBufRaw *a) - { +{ unsigned char* 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) - { +GWN_INLINE uint 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? +} -// void setAttrib1f(unsigned a_idx, unsigned v_idx, float x); -// void setAttrib2f(unsigned a_idx, unsigned v_idx, float x, float y); -// void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z); -// void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w); -// -// void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b); -// void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a); - -void GWN_vertbuf_use(Gwn_VertBuf*); +void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf*, uint a_idx, Gwn_VertBufRaw *access); +/* TODO: decide whether to keep the functions below */ +/* doesn't immediate mode satisfy these needs? */ -// Metrics +/* void setAttrib1f(uint a_idx, uint v_idx, float x); */ +/* void setAttrib2f(uint a_idx, unsigned v_idx, float x, float y); */ +/* void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z); */ +/* void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w); */ -unsigned GWN_vertbuf_get_memory_usage(void); +/* void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b); */ +/* void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a); */ +void GWN_vertbuf_use(Gwn_VertBuf*); -// Macros +/* Metrics */ +uint GWN_vertbuf_get_memory_usage(void); +/* Macros */ #define GWN_VERTBUF_DISCARD_SAFE(verts) do { \ if (verts != NULL) { \ GWN_vertbuf_discard(verts); \ verts = NULL; \ } \ } while (0) + +#endif /* __GWN_VERTEX_BUFFER_H__ */ diff --git a/intern/gawain/gawain/gwn_vertex_format.h b/intern/gawain/gawain/gwn_vertex_format.h index a4593e4615b..1197a8ef842 100644 --- a/intern/gawain/gawain/gwn_vertex_format.h +++ b/intern/gawain/gawain/gwn_vertex_format.h @@ -1,15 +1,36 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain vertex format -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/gwn_vertex_format.h + * \ingroup gpu + * + * Gawain vertex format + */ -#pragma once +#ifndef __GWN_VERTEX_FORMAT_H__ +#define __GWN_VERTEX_FORMAT_H__ #include "gwn_common.h" @@ -34,45 +55,47 @@ typedef enum { typedef enum { GWN_FETCH_FLOAT, GWN_FETCH_INT, - GWN_FETCH_INT_TO_FLOAT_UNIT, // 127 (ubyte) -> 0.5 (and so on for other int types) - GWN_FETCH_INT_TO_FLOAT // 127 (any int type) -> 127.0 + GWN_FETCH_INT_TO_FLOAT_UNIT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */ + GWN_FETCH_INT_TO_FLOAT /* 127 (any int type) -> 127.0 */ } Gwn_VertFetchMode; typedef struct Gwn_VertAttr { Gwn_VertFetchMode fetch_mode; Gwn_VertCompType comp_type; - unsigned gl_comp_type; - unsigned comp_len; // 1 to 4 or 8 or 12 or 16 - unsigned sz; // size in bytes, 1 to 64 - unsigned offset; // from beginning of vertex, in bytes - unsigned name_len; // up to GWN_VERT_ATTR_MAX_NAMES + uint gl_comp_type; + uint comp_len; /* 1 to 4 or 8 or 12 or 16 */ + uint sz; /* size in bytes, 1 to 64 */ + uint offset; /* from beginning of vertex, in bytes */ + uint name_len; /* up to GWN_VERT_ATTR_MAX_NAMES */ const char* name[GWN_VERT_ATTR_MAX_NAMES]; } Gwn_VertAttr; typedef struct Gwn_VertFormat { - unsigned attr_len; // 0 to 16 (GWN_VERT_ATTR_MAX_LEN) - unsigned name_len; // total count of active vertex attrib - unsigned stride; // stride in bytes, 1 to 256 - unsigned name_offset; + uint attr_len; /* 0 to 16 (GWN_VERT_ATTR_MAX_LEN) */ + uint name_len; /* total count of active vertex attrib */ + uint stride; /* stride in bytes, 1 to 256 */ + uint name_offset; bool packed; char names[GWN_VERT_ATTR_NAMES_BUF_LEN]; - Gwn_VertAttr attribs[GWN_VERT_ATTR_MAX_LEN]; // TODO: variable-size attribs array + Gwn_VertAttr attribs[GWN_VERT_ATTR_MAX_LEN]; /* TODO: variable-size attribs array */ } Gwn_VertFormat; void GWN_vertformat_clear(Gwn_VertFormat*); void GWN_vertformat_copy(Gwn_VertFormat* dest, const Gwn_VertFormat* src); -unsigned GWN_vertformat_attr_add(Gwn_VertFormat*, const char* name, Gwn_VertCompType, unsigned comp_len, Gwn_VertFetchMode); +uint GWN_vertformat_attr_add(Gwn_VertFormat*, const char* name, Gwn_VertCompType, uint comp_len, Gwn_VertFetchMode); void GWN_vertformat_alias_add(Gwn_VertFormat*, const char* alias); -// format conversion +/* format conversion */ 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 } + int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */ } Gwn_PackedNormal; Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3]); Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3]); + +#endif /* __GWN_VERTEX_FORMAT_H__ */ diff --git a/intern/gawain/gawain/gwn_vertex_format_private.h b/intern/gawain/gawain/gwn_vertex_format_private.h index 90cd8412e53..3cae9969fd8 100644 --- a/intern/gawain/gawain/gwn_vertex_format_private.h +++ b/intern/gawain/gawain/gwn_vertex_format_private.h @@ -1,16 +1,39 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain vertex format (private interface for use inside Gawain) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016-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/. +/** \file blender/gpu/gwn_vertex_format_private.h + * \ingroup gpu + * + * Gawain vertex format + */ -#pragma once +#ifndef __GWN_VERTEX_FORMAT_PRIVATE_H__ +#define __GWN_VERTEX_FORMAT_PRIVATE_H__ void VertexFormat_pack(Gwn_VertFormat*); -unsigned padding(unsigned offset, unsigned alignment); -unsigned vertex_buffer_size(const Gwn_VertFormat*, unsigned vertex_len); +uint padding(uint offset, uint alignment); +uint vertex_buffer_size(const Gwn_VertFormat*, uint vertex_len); + +#endif /* __GWN_VERTEX_FORMAT_PRIVATE_H__ */ diff --git a/intern/gawain/src/gwn_attr_binding.c b/intern/gawain/src/gwn_attr_binding.c index c702a0ae99d..727aceb0140 100644 --- a/intern/gawain/src/gwn_attr_binding.c +++ b/intern/gawain/src/gwn_attr_binding.c @@ -1,70 +1,85 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain vertex attribute binding -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/intern/gwn_attr_binding.c + * \ingroup gpu + * + * Gawain vertex attribute binding + */ #include "gwn_attr_binding.h" #include "gwn_attr_binding_private.h" #include <stddef.h> +#include <stdlib.h> #if GWN_VERT_ATTR_MAX_LEN != 16 #error "attrib binding code assumes GWN_VERT_ATTR_MAX_LEN = 16" #endif void AttribBinding_clear(Gwn_AttrBinding* binding) - { +{ binding->loc_bits = 0; binding->enabled_bits = 0; - } +} -unsigned read_attrib_location(const Gwn_AttrBinding* binding, unsigned a_idx) - { +uint read_attrib_location(const Gwn_AttrBinding* binding, uint a_idx) +{ #if TRUST_NO_ONE assert(a_idx < GWN_VERT_ATTR_MAX_LEN); assert(binding->enabled_bits & (1 << a_idx)); #endif - return (binding->loc_bits >> (4 * a_idx)) & 0xF; - } +} -static void write_attrib_location(Gwn_AttrBinding* binding, unsigned a_idx, unsigned location) - { +static void write_attrib_location(Gwn_AttrBinding* binding, uint a_idx, uint location) +{ #if TRUST_NO_ONE assert(a_idx < GWN_VERT_ATTR_MAX_LEN); assert(location < GWN_VERT_ATTR_MAX_LEN); #endif - - const unsigned shift = 4 * a_idx; + const uint shift = 4 * a_idx; const uint64_t mask = ((uint64_t)0xF) << shift; - // overwrite this attrib's previous location + /* overwrite this attrib's previous location */ binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift); - // mark this attrib as enabled + /* mark this attrib as enabled */ binding->enabled_bits |= 1 << a_idx; - } +} void get_attrib_locations(const Gwn_VertFormat* format, Gwn_AttrBinding* binding, const Gwn_ShaderInterface* shaderface) - { +{ AttribBinding_clear(binding); - for (unsigned a_idx = 0; a_idx < format->attr_len; ++a_idx) - { + for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) { const Gwn_VertAttr* a = format->attribs + a_idx; - for (unsigned n_idx = 0; n_idx < a->name_len; ++n_idx) - { + for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { const Gwn_ShaderInput* input = GWN_shaderinterface_attr(shaderface, a->name[n_idx]); - #if TRUST_NO_ONE assert(input != NULL); - // TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program + /* TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program */ #endif - write_attrib_location(binding, a_idx, input->location); - } } } +} diff --git a/intern/gawain/src/gwn_batch.c b/intern/gawain/src/gwn_batch.c index 4979d93b15e..5daf0e87aec 100644 --- a/intern/gawain/src/gwn_batch.c +++ b/intern/gawain/src/gwn_batch.c @@ -1,13 +1,34 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_batch.c + * \ingroup gpu + * + * Gawain geometry batch + * Contains VAOs + VBOs + Shader representing a drawable entity. + */ #include "gwn_batch.h" #include "gwn_batch_private.h" @@ -17,72 +38,68 @@ #include <stdlib.h> #include <string.h> -// necessary functions from matrix API +/* necessary functions from matrix API */ extern void GPU_matrix_bind(const Gwn_ShaderInterface* shaderface); -static void batch_update_program_bindings(Gwn_Batch* batch, unsigned int v_first); +static void batch_update_program_bindings(Gwn_Batch* batch, uint v_first); void gwn_batch_vao_cache_clear(Gwn_Batch* batch) - { - if (batch->context == NULL) +{ + if (batch->context == NULL) { return; - - if (batch->is_dynamic_vao_count) - { - for (int i = 0; i < batch->dynamic_vaos.count; ++i) - { - if (batch->dynamic_vaos.vao_ids[i]) + } + if (batch->is_dynamic_vao_count) { + for (int i = 0; i < batch->dynamic_vaos.count; ++i) { + if (batch->dynamic_vaos.vao_ids[i]) { GWN_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); - if (batch->dynamic_vaos.interfaces[i]) + } + if (batch->dynamic_vaos.interfaces[i]) { GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface *)batch->dynamic_vaos.interfaces[i], batch); } + } free(batch->dynamic_vaos.interfaces); free(batch->dynamic_vaos.vao_ids); - } - else - { - for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) - { - if (batch->static_vaos.vao_ids[i]) + } + else { + for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) { + if (batch->static_vaos.vao_ids[i]) { GWN_vao_free(batch->static_vaos.vao_ids[i], batch->context); - if (batch->static_vaos.interfaces[i]) + } + if (batch->static_vaos.interfaces[i]) { GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface *)batch->static_vaos.interfaces[i], batch); } } - + } batch->is_dynamic_vao_count = false; - for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) - { + for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) { batch->static_vaos.vao_ids[i] = 0; batch->static_vaos.interfaces[i] = NULL; - } - + } gwn_context_remove_batch(batch->context, batch); batch->context = NULL; - } +} Gwn_Batch* GWN_batch_create_ex( Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem, - unsigned owns_flag) - { + uint owns_flag) +{ Gwn_Batch* batch = calloc(1, sizeof(Gwn_Batch)); - GWN_batch_init_ex(batch, prim_type, verts, elem, owns_flag); - return batch; - } +} void GWN_batch_init_ex( Gwn_Batch* batch, Gwn_PrimType prim_type, Gwn_VertBuf* verts, Gwn_IndexBuf* elem, - unsigned owns_flag) - { + uint owns_flag) +{ #if TRUST_NO_ONE assert(verts != NULL); #endif batch->verts[0] = verts; - for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v) + for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v) { batch->verts[v] = NULL; + } batch->inst = NULL; batch->elem = elem; batch->gl_prim_type = convert_prim_type_to_gl(prim_type); @@ -90,184 +107,175 @@ void GWN_batch_init_ex( batch->is_dynamic_vao_count = false; batch->owns_flag = owns_flag; batch->free_callback = NULL; - } +} -// This will share the VBOs with the new batch +/* This will share the VBOs with the new batch. */ Gwn_Batch* GWN_batch_duplicate(Gwn_Batch* batch_src) - { +{ Gwn_Batch* batch = GWN_batch_create_ex(GWN_PRIM_POINTS, batch_src->verts[0], batch_src->elem, 0); batch->gl_prim_type = batch_src->gl_prim_type; - for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v) + for (int v = 1; v < GWN_BATCH_VBO_MAX_LEN; ++v) { batch->verts[v] = batch_src->verts[v]; - - return batch; } + return batch; +} void GWN_batch_discard(Gwn_Batch* batch) - { - if (batch->owns_flag & GWN_BATCH_OWNS_INDEX) +{ + if (batch->owns_flag & GWN_BATCH_OWNS_INDEX) { GWN_indexbuf_discard(batch->elem); - - if (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES) + } + if (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES) { GWN_vertbuf_discard(batch->inst); - - if ((batch->owns_flag & ~GWN_BATCH_OWNS_INDEX) != 0) - { - for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) - { - if (batch->verts[v] == NULL) + } + if ((batch->owns_flag & ~GWN_BATCH_OWNS_INDEX) != 0) { + for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) { + if (batch->verts[v] == NULL) { break; - if (batch->owns_flag & (1 << v)) + } + if (batch->owns_flag & (1 << v)) { GWN_vertbuf_discard(batch->verts[v]); } } - + } gwn_batch_vao_cache_clear(batch); - if (batch->free_callback) + if (batch->free_callback) { batch->free_callback(batch, batch->callback_data); - - free(batch); } + free(batch); +} void GWN_batch_callback_free_set(Gwn_Batch* batch, void (*callback)(Gwn_Batch*, void*), void* user_data) - { +{ batch->free_callback = callback; batch->callback_data = user_data; - } +} void GWN_batch_instbuf_set(Gwn_Batch* batch, Gwn_VertBuf* inst, bool own_vbo) - { +{ #if TRUST_NO_ONE assert(inst != NULL); #endif - // redo the bindings + /* redo the bindings */ gwn_batch_vao_cache_clear(batch); - if (batch->inst != NULL && (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES)) + if (batch->inst != NULL && (batch->owns_flag & GWN_BATCH_OWNS_INSTANCES)) { GWN_vertbuf_discard(batch->inst); - + } batch->inst = inst; - if (own_vbo) + if (own_vbo) { batch->owns_flag |= GWN_BATCH_OWNS_INSTANCES; - else + } + else { batch->owns_flag &= ~GWN_BATCH_OWNS_INSTANCES; } +} +/* Returns the index of verts in the batch. */ int GWN_batch_vertbuf_add_ex( Gwn_Batch* batch, Gwn_VertBuf* verts, bool own_vbo) - { - // redo the bindings +{ + /* redo the bindings */ gwn_batch_vao_cache_clear(batch); - for (unsigned v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) - { - if (batch->verts[v] == NULL) - { + for (uint v = 0; v < GWN_BATCH_VBO_MAX_LEN; ++v) { + if (batch->verts[v] == NULL) { #if TRUST_NO_ONE - // for now all VertexBuffers must have same vertex_len + /* for now all VertexBuffers must have same vertex_len */ assert(verts->vertex_len == batch->verts[0]->vertex_len); - // in the near future we will enable instanced attribs which have their own vertex_len #endif batch->verts[v] = verts; - // TODO: mark dirty so we can keep attrib bindings up-to-date + /* TODO: mark dirty so we can keep attrib bindings up-to-date */ if (own_vbo) batch->owns_flag |= (1 << v); return v; - } } + } - // we only make it this far if there is no room for another Gwn_VertBuf + /* we only make it this far if there is no room for another Gwn_VertBuf */ #if TRUST_NO_ONE assert(false); #endif return -1; - } +} static GLuint batch_vao_get(Gwn_Batch *batch) - { - // Search through cache - if (batch->is_dynamic_vao_count) - { +{ + /* Search through cache */ + if (batch->is_dynamic_vao_count) { for (int i = 0; i < batch->dynamic_vaos.count; ++i) if (batch->dynamic_vaos.interfaces[i] == batch->interface) return batch->dynamic_vaos.vao_ids[i]; - } - else - { + } + else { for (int i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) if (batch->static_vaos.interfaces[i] == batch->interface) return batch->static_vaos.vao_ids[i]; - } + } - // Set context of this batch. - // It will be bound to it until gwn_batch_vao_cache_clear is called. - // Until then it can only be drawn with this context. - if (batch->context == NULL) - { + /* Set context of this batch. + * It will be bound to it until gwn_batch_vao_cache_clear is called. + * Until then it can only be drawn with this context. */ + if (batch->context == NULL) { batch->context = GWN_context_active_get(); gwn_context_add_batch(batch->context, batch); - } + } #if TRUST_NO_ONE - else // Make sure you are not trying to draw this batch in another context. + else { + /* Make sure you are not trying to draw this batch in another context. */ assert(batch->context == GWN_context_active_get()); + } #endif - // Cache miss, time to add a new entry! + /* Cache miss, time to add a new entry! */ GLuint new_vao = 0; - if (!batch->is_dynamic_vao_count) - { - int i; // find first unused slot - for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) + if (!batch->is_dynamic_vao_count) { + int i; /* find first unused slot */ + for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) if (batch->static_vaos.vao_ids[i] == 0) break; - if (i < GWN_BATCH_VAO_STATIC_LEN) - { + if (i < GWN_BATCH_VAO_STATIC_LEN) { batch->static_vaos.interfaces[i] = batch->interface; batch->static_vaos.vao_ids[i] = new_vao = GWN_vao_alloc(); - } - else - { - // Not enough place switch to dynamic. + } + else { + /* Not enough place switch to dynamic. */ batch->is_dynamic_vao_count = true; - // Erase previous entries, they will be added back if drawn again. - for (int j = 0; j < GWN_BATCH_VAO_STATIC_LEN; ++j) - { + /* Erase previous entries, they will be added back if drawn again. */ + for (int j = 0; j < GWN_BATCH_VAO_STATIC_LEN; ++j) { GWN_shaderinterface_remove_batch_ref((Gwn_ShaderInterface*)batch->static_vaos.interfaces[j], batch); GWN_vao_free(batch->static_vaos.vao_ids[j], batch->context); - } - // Init dynamic arrays and let the branch below set the values. + } + /* Init dynamic arrays and let the branch below set the values. */ batch->dynamic_vaos.count = GWN_BATCH_VAO_DYN_ALLOC_COUNT; batch->dynamic_vaos.interfaces = calloc(batch->dynamic_vaos.count, sizeof(Gwn_ShaderInterface*)); batch->dynamic_vaos.vao_ids = calloc(batch->dynamic_vaos.count, sizeof(GLuint)); - } } + } - if (batch->is_dynamic_vao_count) - { - int i; // find first unused slot + if (batch->is_dynamic_vao_count) { + int i; /* find first unused slot */ for (i = 0; i < batch->dynamic_vaos.count; ++i) if (batch->dynamic_vaos.vao_ids[i] == 0) break; - if (i == batch->dynamic_vaos.count) - { - // Not enough place, realloc the array. + if (i == batch->dynamic_vaos.count) { + /* Not enough place, realloc the array. */ i = batch->dynamic_vaos.count; batch->dynamic_vaos.count += GWN_BATCH_VAO_DYN_ALLOC_COUNT; batch->dynamic_vaos.interfaces = realloc(batch->dynamic_vaos.interfaces, sizeof(Gwn_ShaderInterface*) * batch->dynamic_vaos.count); batch->dynamic_vaos.vao_ids = realloc(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count); memset(batch->dynamic_vaos.interfaces + i, 0, sizeof(Gwn_ShaderInterface*) * GWN_BATCH_VAO_DYN_ALLOC_COUNT); memset(batch->dynamic_vaos.vao_ids + i, 0, sizeof(GLuint) * GWN_BATCH_VAO_DYN_ALLOC_COUNT); - } - + } batch->dynamic_vaos.interfaces[i] = batch->interface; batch->dynamic_vaos.vao_ids[i] = new_vao = GWN_vao_alloc(); - } + } GWN_shaderinterface_add_batch_ref((Gwn_ShaderInterface*)batch->interface, batch); @@ -275,105 +283,94 @@ static GLuint batch_vao_get(Gwn_Batch *batch) assert(new_vao != 0); #endif - // We just got a fresh VAO we need to initialize it. + /* We just got a fresh VAO we need to initialize it. */ glBindVertexArray(new_vao); batch_update_program_bindings(batch, 0); glBindVertexArray(0); return new_vao; - } +} void GWN_batch_program_set_no_use(Gwn_Batch* batch, uint32_t program, const Gwn_ShaderInterface* shaderface) - { +{ #if TRUST_NO_ONE assert(glIsProgram(shaderface->program)); assert(batch->program_in_use == 0); #endif - batch->interface = shaderface; batch->program = program; batch->vao_id = batch_vao_get(batch); - } +} void GWN_batch_program_set(Gwn_Batch* batch, uint32_t program, const Gwn_ShaderInterface* shaderface) - { +{ GWN_batch_program_set_no_use(batch, program, shaderface); - GWN_batch_program_use_begin(batch); // hack! to make Batch_Uniform* simpler - } + GWN_batch_program_use_begin(batch); /* hack! to make Batch_Uniform* simpler */ +} void gwn_batch_remove_interface_ref(Gwn_Batch* batch, const Gwn_ShaderInterface* interface) - { - if (batch->is_dynamic_vao_count) - { - for (int i = 0; i < batch->dynamic_vaos.count; ++i) - { - if (batch->dynamic_vaos.interfaces[i] == interface) - { +{ + if (batch->is_dynamic_vao_count) { + for (int i = 0; i < batch->dynamic_vaos.count; ++i) { + if (batch->dynamic_vaos.interfaces[i] == interface) { GWN_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); batch->dynamic_vaos.vao_ids[i] = 0; batch->dynamic_vaos.interfaces[i] = NULL; - break; // cannot have duplicates - } + break; /* cannot have duplicates */ } } - else - { + } + else { int i; - for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) - { - if (batch->static_vaos.interfaces[i] == interface) - { + for (i = 0; i < GWN_BATCH_VAO_STATIC_LEN; ++i) { + if (batch->static_vaos.interfaces[i] == interface) { GWN_vao_free(batch->static_vaos.vao_ids[i], batch->context); batch->static_vaos.vao_ids[i] = 0; batch->static_vaos.interfaces[i] = NULL; - break; // cannot have duplicates - } + break; /* cannot have duplicates */ } } } +} -static void create_bindings(Gwn_VertBuf* verts, const Gwn_ShaderInterface* interface, unsigned int v_first, const bool use_instancing) - { +static void create_bindings( + Gwn_VertBuf* verts, const Gwn_ShaderInterface* interface, + uint v_first, const bool use_instancing) +{ const Gwn_VertFormat* format = &verts->format; - const unsigned attr_len = format->attr_len; - const unsigned stride = format->stride; + const uint attr_len = format->attr_len; + const uint stride = format->stride; GWN_vertbuf_use(verts); - for (unsigned a_idx = 0; a_idx < attr_len; ++a_idx) - { + for (uint a_idx = 0; a_idx < attr_len; ++a_idx) { const Gwn_VertAttr* a = format->attribs + a_idx; - const GLvoid* pointer = (const GLubyte*)0 + a->offset + v_first * stride; - for (unsigned n_idx = 0; n_idx < a->name_len; ++n_idx) - { + for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { const Gwn_ShaderInput* input = GWN_shaderinterface_attr(interface, a->name[n_idx]); if (input == NULL) continue; - if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) - { + if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) { #if TRUST_NO_ONE assert(a->fetch_mode == GWN_FETCH_FLOAT); assert(a->gl_comp_type == GL_FLOAT); #endif - for (int i = 0; i < a->comp_len / 4; ++i) - { + for (int i = 0; i < a->comp_len / 4; ++i) { glEnableVertexAttribArray(input->location + i); glVertexAttribDivisor(input->location + i, (use_instancing) ? 1 : 0); glVertexAttribPointer(input->location + i, 4, a->gl_comp_type, GL_FALSE, stride, (const GLubyte*)pointer + i * 16); - } } + } else { glEnableVertexAttribArray(input->location); glVertexAttribDivisor(input->location, (use_instancing) ? 1 : 0); - switch (a->fetch_mode) - { + switch (a->fetch_mode) { case GWN_FETCH_FLOAT: case GWN_FETCH_INT_TO_FLOAT: glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); @@ -383,47 +380,47 @@ static void create_bindings(Gwn_VertBuf* verts, const Gwn_ShaderInterface* inter break; case GWN_FETCH_INT: glVertexAttribIPointer(input->location, a->comp_len, a->gl_comp_type, stride, pointer); - } + break; } } } } +} -static void batch_update_program_bindings(Gwn_Batch* batch, unsigned int v_first) - { - for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) +static void batch_update_program_bindings(Gwn_Batch* batch, uint v_first) +{ + for (int v = 0; v < GWN_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) { create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false); - - if (batch->inst) + } + if (batch->inst) { create_bindings(batch->inst, batch->interface, v_first, true); - - if (batch->elem) + } + if (batch->elem) { GWN_indexbuf_use(batch->elem); } +} void GWN_batch_program_use_begin(Gwn_Batch* batch) - { - // NOTE: use_program & done_using_program are fragile, depend on staying in sync with - // the GL context's active program. use_program doesn't mark other programs as "not used". - // TODO: make not fragile (somehow) +{ + /* NOTE: use_program & done_using_program are fragile, depend on staying in sync with + * the GL context's active program. use_program doesn't mark other programs as "not used". */ + /* TODO: make not fragile (somehow) */ - if (!batch->program_in_use) - { + if (!batch->program_in_use) { glUseProgram(batch->program); batch->program_in_use = true; - } } +} void GWN_batch_program_use_end(Gwn_Batch* batch) - { - if (batch->program_in_use) - { +{ + if (batch->program_in_use) { #if PROGRAM_NO_OPTI glUseProgram(0); #endif batch->program_in_use = false; - } } +} #if TRUST_NO_ONE #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(batch->interface, name); assert(uniform); @@ -432,82 +429,82 @@ void GWN_batch_program_use_end(Gwn_Batch* batch) #endif void GWN_batch_uniform_1ui(Gwn_Batch* batch, const char* name, int value) - { +{ GET_UNIFORM glUniform1ui(uniform->location, value); - } +} void GWN_batch_uniform_1i(Gwn_Batch* batch, const char* name, int value) - { +{ GET_UNIFORM glUniform1i(uniform->location, value); - } +} void GWN_batch_uniform_1b(Gwn_Batch* batch, const char* name, bool value) - { +{ GET_UNIFORM glUniform1i(uniform->location, value ? GL_TRUE : GL_FALSE); - } +} void GWN_batch_uniform_2f(Gwn_Batch* batch, const char* name, float x, float y) - { +{ GET_UNIFORM glUniform2f(uniform->location, x, y); - } +} void GWN_batch_uniform_3f(Gwn_Batch* batch, const char* name, float x, float y, float z) - { +{ GET_UNIFORM glUniform3f(uniform->location, x, y, z); - } +} void GWN_batch_uniform_4f(Gwn_Batch* batch, const char* name, float x, float y, float z, float w) - { +{ GET_UNIFORM glUniform4f(uniform->location, x, y, z, w); - } +} void GWN_batch_uniform_1f(Gwn_Batch* batch, const char* name, float x) - { +{ GET_UNIFORM 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 glUniform3fv(uniform->location, 1, data); - } +} void GWN_batch_uniform_4fv(Gwn_Batch* batch, const char* name, const float data[4]) - { +{ GET_UNIFORM glUniform4fv(uniform->location, 1, data); - } +} void GWN_batch_uniform_2fv_array(Gwn_Batch* batch, const char* name, const int len, const float *data) - { +{ GET_UNIFORM glUniform2fv(uniform->location, len, data); - } +} void GWN_batch_uniform_4fv_array(Gwn_Batch* batch, const char* name, const int len, const float *data) - { +{ GET_UNIFORM glUniform4fv(uniform->location, len, data); - } +} void GWN_batch_uniform_mat4(Gwn_Batch* batch, const char* name, const float data[4][4]) - { +{ GET_UNIFORM glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data); - } +} static void primitive_restart_enable(const Gwn_IndexBuf *el) { @@ -531,7 +528,7 @@ static void primitive_restart_disable(void) } void GWN_batch_draw(Gwn_Batch* batch) - { +{ #if TRUST_NO_ONE assert(batch->phase == GWN_BATCH_READY_TO_DRAW); assert(batch->verts[0]->vbo_id != 0); @@ -542,91 +539,107 @@ void GWN_batch_draw(Gwn_Batch* batch) GWN_batch_draw_range_ex(batch, 0, 0, false); GWN_batch_program_use_end(batch); - } +} void GWN_batch_draw_range_ex(Gwn_Batch* batch, int v_first, int v_count, bool force_instance) - { +{ #if TRUST_NO_ONE assert(!(force_instance && (batch->inst == NULL)) || v_count > 0); // we cannot infer length if force_instance #endif const bool do_instance = (force_instance || batch->inst); // If using offset drawing, use the default VAO and redo bindings. - if (v_first != 0 && (do_instance || batch->elem)) - { + if (v_first != 0 && (do_instance || batch->elem)) { glBindVertexArray(GWN_vao_default()); batch_update_program_bindings(batch, v_first); - } - else + } + else { glBindVertexArray(batch->vao_id); + } - if (do_instance) - { - // Infer length if vertex count is not given - if (v_count == 0) + if (do_instance) { + /* Infer length if vertex count is not given */ + if (v_count == 0) { v_count = batch->inst->vertex_len; + } - if (batch->elem) - { + if (batch->elem) { const Gwn_IndexBuf* el = batch->elem; - if (el->use_prim_restart) + if (el->use_prim_restart) { primitive_restart_enable(el); - + } #if GWN_TRACK_INDEX_RANGE - glDrawElementsInstancedBaseVertex(batch->gl_prim_type, el->index_len, el->gl_index_type, 0, v_count, el->base_index); + glDrawElementsInstancedBaseVertex(batch->gl_prim_type, + el->index_len, + el->gl_index_type, + 0, + v_count, + el->base_index); #else glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count); #endif - if (el->use_prim_restart) + if (el->use_prim_restart) { primitive_restart_disable(); } - else + } + else { glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count); } - else - { - // Infer length if vertex count is not given - if (v_count == 0) + } + else { + /* Infer length if vertex count is not given */ + if (v_count == 0) { v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len; + } - if (batch->elem) - { + if (batch->elem) { const Gwn_IndexBuf* el = batch->elem; - if (el->use_prim_restart) + if (el->use_prim_restart) { primitive_restart_enable(el); + } #if GWN_TRACK_INDEX_RANGE - if (el->base_index) - glDrawRangeElementsBaseVertex(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0, el->base_index); - else + if (el->base_index) { + glDrawRangeElementsBaseVertex(batch->gl_prim_type, + el->min_index, + el->max_index, + v_count, + el->gl_index_type, + 0, + el->base_index); + } + else { glDrawRangeElements(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0); + } #else glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, 0); #endif - if (el->use_prim_restart) + if (el->use_prim_restart) { primitive_restart_disable(); } - else + } + else { glDrawArrays(batch->gl_prim_type, v_first, v_count); } + } - // Performance hog if you are drawing with the same vao multiple time. - // Only activate for debugging. + /* Performance hog if you are drawing with the same vao multiple time. + * Only activate for debugging. */ // glBindVertexArray(0); - } +} -// just draw some vertices and let shader place them where we want. +/* just draw some vertices and let shader place them where we want. */ void GWN_draw_primitive(Gwn_PrimType prim_type, int v_count) { - // we cannot draw without vao ... annoying ... + /* we cannot draw without vao ... annoying ... */ glBindVertexArray(GWN_vao_default()); GLenum type = convert_prim_type_to_gl(prim_type); glDrawArrays(type, 0, v_count); - // Performance hog if you are drawing with the same vao multiple time. - // Only activate for debugging. + /* Performance hog if you are drawing with the same vao multiple time. + * Only activate for debugging.*/ // glBindVertexArray(0); } diff --git a/intern/gawain/src/gwn_buffer_id.cpp b/intern/gawain/src/gwn_buffer_id.cpp index 13473f1f28d..2c267682f65 100644 --- a/intern/gawain/src/gwn_buffer_id.cpp +++ b/intern/gawain/src/gwn_buffer_id.cpp @@ -1,13 +1,33 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain buffer IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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 "buffer_id.h" +/** \file blender/gpu/intern/gwn_buffer_id.cpp + * \ingroup gpu + * + * Gawain buffer IDs + */ #include "gwn_buffer_id.h" #include <mutex> @@ -24,47 +44,46 @@ static std::vector<GLuint> orphaned_buffer_ids; static std::mutex orphan_mutex; extern "C" { -extern int BLI_thread_is_main(void); // Blender-specific function +extern int BLI_thread_is_main(void); /* Blender-specific function */ } static bool thread_is_main() - { - // "main" here means the GL context's thread +{ + /* "main" here means the GL context's thread */ return BLI_thread_is_main(); - } +} GLuint GWN_buf_id_alloc() - { - // delete orphaned IDs +{ + /* delete orphaned IDs */ orphan_mutex.lock(); - if (!orphaned_buffer_ids.empty()) - { - const auto orphaned_buffer_len = (unsigned)orphaned_buffer_ids.size(); + if (!orphaned_buffer_ids.empty()) { + const auto orphaned_buffer_len = (uint)orphaned_buffer_ids.size(); #if ORPHAN_DEBUG printf("deleting %u orphaned VBO%s\n", orphaned_buffer_len, orphaned_buffer_len == 1 ? "" : "s"); #endif glDeleteBuffers(orphaned_buffer_len, orphaned_buffer_ids.data()); orphaned_buffer_ids.clear(); - } + } orphan_mutex.unlock(); GLuint new_buffer_id = 0; glGenBuffers(1, &new_buffer_id); return new_buffer_id; - } +} void GWN_buf_id_free(GLuint buffer_id) - { - if (thread_is_main()) +{ + if (thread_is_main()) { glDeleteBuffers(1, &buffer_id); - else - { - // add this ID to the orphaned list + } + else { + /* add this ID to the orphaned list */ orphan_mutex.lock(); #if ORPHAN_DEBUG printf("orphaning VBO %u\n", buffer_id); #endif orphaned_buffer_ids.emplace_back(buffer_id); orphan_mutex.unlock(); - } } +} diff --git a/intern/gawain/src/gwn_element.c b/intern/gawain/src/gwn_element.c index 257338fe089..a8c99f20860 100644 --- a/intern/gawain/src/gwn_element.c +++ b/intern/gawain/src/gwn_element.c @@ -1,13 +1,33 @@ - -// Gawain element list (AKA index buffer) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_element.c + * \ingroup gpu + * + * Gawain element list (AKA index buffer) + */ #include "gwn_element.h" #include "gwn_buffer_id.h" @@ -16,44 +36,45 @@ #define KEEP_SINGLE_COPY 1 static GLenum convert_index_type_to_gl(Gwn_IndexBufType type) - { +{ static const GLenum table[] = { - [GWN_INDEX_U8] = GL_UNSIGNED_BYTE, // GL has this, Vulkan does not + [GWN_INDEX_U8] = GL_UNSIGNED_BYTE, /* GL has this, Vulkan does not */ [GWN_INDEX_U16] = GL_UNSIGNED_SHORT, [GWN_INDEX_U32] = GL_UNSIGNED_INT - }; + }; return table[type]; - } +} -unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf* elem) - { +uint GWN_indexbuf_size_get(const Gwn_IndexBuf* elem) +{ #if GWN_TRACK_INDEX_RANGE - static const unsigned table[] = { - [GWN_INDEX_U8] = sizeof(GLubyte), // GL has this, Vulkan does not + static const uint table[] = { + [GWN_INDEX_U8] = sizeof(GLubyte), /* GL has this, Vulkan does not */ [GWN_INDEX_U16] = sizeof(GLushort), [GWN_INDEX_U32] = sizeof(GLuint) - }; + }; return elem->index_len * table[elem->index_type]; #else return elem->index_len * sizeof(GLuint); #endif - } +} -void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned index_len, unsigned vertex_len, bool use_prim_restart) - { +void GWN_indexbuf_init_ex( + Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, + uint index_len, uint vertex_len, bool use_prim_restart) +{ builder->use_prim_restart = use_prim_restart; builder->max_allowed_index = vertex_len - 1; builder->max_index_len = index_len; builder->index_len = 0; // start empty builder->prim_type = prim_type; - builder->data = calloc(builder->max_index_len, sizeof(unsigned)); - } + builder->data = calloc(builder->max_index_len, sizeof(uint)); +} -void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned prim_len, unsigned vertex_len) - { - unsigned verts_per_prim = 0; - switch (prim_type) - { +void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, uint prim_len, uint vertex_len) +{ + uint verts_per_prim = 0; + switch (prim_type) { case GWN_PRIM_POINTS: verts_per_prim = 1; break; @@ -71,234 +92,216 @@ void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, uns assert(false); #endif return; - } + } GWN_indexbuf_init_ex(builder, prim_type, prim_len * verts_per_prim, vertex_len, false); - } +} -void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder* builder, unsigned v) - { +void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder* builder, uint v) +{ #if TRUST_NO_ONE assert(builder->data != NULL); assert(builder->index_len < builder->max_index_len); assert(v <= builder->max_allowed_index); #endif - builder->data[builder->index_len++] = v; - } +} void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder* builder) - { +{ #if TRUST_NO_ONE assert(builder->data != NULL); assert(builder->index_len < builder->max_index_len); assert(builder->use_prim_restart); #endif - builder->data[builder->index_len++] = GWN_PRIM_RESTART; - } +} -void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder* builder, unsigned v) - { +void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder* builder, uint v) +{ #if TRUST_NO_ONE assert(builder->prim_type == GWN_PRIM_POINTS); #endif - GWN_indexbuf_add_generic_vert(builder, v); - } +} -void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2) - { +void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder* builder, uint v1, uint v2) +{ #if TRUST_NO_ONE assert(builder->prim_type == GWN_PRIM_LINES); assert(v1 != v2); #endif - GWN_indexbuf_add_generic_vert(builder, v1); GWN_indexbuf_add_generic_vert(builder, v2); - } +} -void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2, unsigned v3) - { +void GWN_indexbuf_add_tri_verts(Gwn_IndexBufBuilder* builder, uint v1, uint v2, uint v3) +{ #if TRUST_NO_ONE assert(builder->prim_type == GWN_PRIM_TRIS); assert(v1 != v2 && v2 != v3 && v3 != v1); #endif - GWN_indexbuf_add_generic_vert(builder, v1); GWN_indexbuf_add_generic_vert(builder, v2); GWN_indexbuf_add_generic_vert(builder, v3); - } +} -void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder* builder, unsigned v1, unsigned v2, unsigned v3, unsigned v4) - { +void GWN_indexbuf_add_line_adj_verts(Gwn_IndexBufBuilder* builder, uint v1, uint v2, uint v3, uint v4) +{ #if TRUST_NO_ONE assert(builder->prim_type == GWN_PRIM_LINES_ADJ); assert(v2 != v3); /* only the line need diff indices */ #endif - GWN_indexbuf_add_generic_vert(builder, v1); GWN_indexbuf_add_generic_vert(builder, v2); GWN_indexbuf_add_generic_vert(builder, v3); GWN_indexbuf_add_generic_vert(builder, v4); - } +} #if GWN_TRACK_INDEX_RANGE -// Everything remains 32 bit while building to keep things simple. -// Find min/max after, then convert to smallest index type possible. +/* Everything remains 32 bit while building to keep things simple. + * Find min/max after, then convert to smallest index type possible. */ -static unsigned index_range(const unsigned values[], unsigned value_len, unsigned* min_out, unsigned* max_out) - { - if (value_len == 0) - { +static uint index_range(const uint values[], uint value_len, uint* min_out, uint* max_out) +{ + if (value_len == 0) { *min_out = 0; *max_out = 0; return 0; - } - unsigned min_value = values[0]; - unsigned max_value = values[0]; - for (unsigned i = 1; i < value_len; ++i) - { - const unsigned value = values[i]; + } + uint min_value = values[0]; + uint max_value = values[0]; + for (uint i = 1; i < value_len; ++i) { + const uint value = values[i]; if (value == GWN_PRIM_RESTART) continue; else if (value < min_value) min_value = value; else if (value > max_value) max_value = value; - } + } *min_out = min_value; *max_out = max_value; return max_value - min_value; - } +} static void squeeze_indices_byte(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem) - { - const unsigned *values = builder->data; - const unsigned index_len = elem->index_len; +{ + const uint *values = builder->data; + const uint index_len = elem->index_len; - // data will never be *larger* than builder->data... - // converting in place to avoid extra allocation + /* data will never be *larger* than builder->data... + * converting in place to avoid extra allocation */ GLubyte *data = (GLubyte *)builder->data; - if (elem->max_index > 0xFF) - { - const unsigned base = elem->min_index; - + if (elem->max_index > 0xFF) { + const uint base = elem->min_index; elem->base_index = base; elem->min_index = 0; elem->max_index -= base; - - for (unsigned i = 0; i < index_len; ++i) + for (uint i = 0; i < index_len; ++i) { data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base); } - else - { + } + else { elem->base_index = 0; - - for (unsigned i = 0; i < index_len; ++i) + for (uint i = 0; i < index_len; ++i) { data[i] = (GLubyte)(values[i]); } } +} static void squeeze_indices_short(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem) - { - const unsigned *values = builder->data; - const unsigned index_len = elem->index_len; +{ + const uint *values = builder->data; + const uint index_len = elem->index_len; - // data will never be *larger* than builder->data... - // converting in place to avoid extra allocation + /* data will never be *larger* than builder->data... + * converting in place to avoid extra allocation */ GLushort *data = (GLushort *)builder->data; - if (elem->max_index > 0xFFFF) - { - const unsigned base = elem->min_index; - + if (elem->max_index > 0xFFFF) { + const uint base = elem->min_index; elem->base_index = base; elem->min_index = 0; elem->max_index -= base; - - for (unsigned i = 0; i < index_len; ++i) + for (uint i = 0; i < index_len; ++i) { data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base); } - else - { + } + else { elem->base_index = 0; - - for (unsigned i = 0; i < index_len; ++i) + for (uint i = 0; i < index_len; ++i) { data[i] = (GLushort)(values[i]); } } +} -#endif // GWN_TRACK_INDEX_RANGE +#endif /* GWN_TRACK_INDEX_RANGE */ Gwn_IndexBuf* GWN_indexbuf_build(Gwn_IndexBufBuilder* builder) - { +{ Gwn_IndexBuf* elem = calloc(1, sizeof(Gwn_IndexBuf)); GWN_indexbuf_build_in_place(builder, elem); return elem; - } +} void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder* builder, Gwn_IndexBuf* elem) - { +{ #if TRUST_NO_ONE assert(builder->data != NULL); #endif - elem->index_len = builder->index_len; elem->use_prim_restart = builder->use_prim_restart; #if GWN_TRACK_INDEX_RANGE - unsigned range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index); + uint range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index); - // count the primitive restart index. - if (elem->use_prim_restart) + /* count the primitive restart index. */ + if (elem->use_prim_restart) { range += 1; + } - if (range <= 0xFF) - { + if (range <= 0xFF) { elem->index_type = GWN_INDEX_U8; squeeze_indices_byte(builder, elem); - } - else if (range <= 0xFFFF) - { + } + else if (range <= 0xFFFF) { elem->index_type = GWN_INDEX_U16; squeeze_indices_short(builder, elem); - } - else - { + } + else { elem->index_type = GWN_INDEX_U32; elem->base_index = 0; - } - + } elem->gl_index_type = convert_index_type_to_gl(elem->index_type); #endif - if (elem->vbo_id == 0) + if (elem->vbo_id == 0) { elem->vbo_id = GWN_buf_id_alloc(); - - // send data to GPU - // GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound, - // so we use the GL_ARRAY_BUFFER here to create a buffer without - // interfering in the VAO state. + } + /* send data to GPU */ + /* GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound, + * so we use the GL_ARRAY_BUFFER here to create a buffer without + * interfering in the VAO state. */ glBindBuffer(GL_ARRAY_BUFFER, elem->vbo_id); glBufferData(GL_ARRAY_BUFFER, GWN_indexbuf_size_get(elem), builder->data, GL_STATIC_DRAW); - // discard builder (one-time use) + /* discard builder (one-time use) */ free(builder->data); builder->data = NULL; - // other fields are safe to leave - } + /* other fields are safe to leave */ +} void GWN_indexbuf_use(Gwn_IndexBuf* elem) - { +{ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); - } +} void GWN_indexbuf_discard(Gwn_IndexBuf* elem) - { - if (elem->vbo_id) +{ + if (elem->vbo_id) { GWN_buf_id_free(elem->vbo_id); - - free(elem); } + free(elem); +} diff --git a/intern/gawain/src/gwn_imm_util.c b/intern/gawain/src/gwn_imm_util.c index a8d2b05c8a3..cdf55c3dfc4 100644 --- a/intern/gawain/src/gwn_imm_util.c +++ b/intern/gawain/src/gwn_imm_util.c @@ -1,40 +1,60 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain immediate mode drawing utilities -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/** \file blender/gpu/intern/gwn_imm_util.c + * \ingroup gpu + * + * Gawain immediate mode drawing utilities + */ #include "gwn_imm_util.h" #include "gwn_immediate.h" +#include <stdlib.h> - -void immRectf(unsigned pos, float x1, float y1, float x2, float y2) - { +void immRectf(uint pos, float x1, float y1, float x2, float y2) +{ immBegin(GWN_PRIM_TRI_FAN, 4); immVertex2f(pos, x1, y1); immVertex2f(pos, x2, y1); immVertex2f(pos, x2, y2); immVertex2f(pos, x1, y2); immEnd(); - } +} -void immRecti(unsigned pos, int x1, int y1, int x2, int y2) - { +void immRecti(uint pos, int x1, int y1, int x2, int y2) +{ immBegin(GWN_PRIM_TRI_FAN, 4); immVertex2i(pos, x1, y1); immVertex2i(pos, x2, y1); immVertex2i(pos, x2, y2); immVertex2i(pos, x1, y2); immEnd(); - } +} -void immRectf_fast_with_color(unsigned pos, unsigned col, float x1, float y1, float x2, float y2, const float color[4]) - { +void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]) +{ immAttrib4fv(col, color); immVertex2f(pos, x1, y1); immAttrib4fv(col, color); @@ -48,10 +68,10 @@ void immRectf_fast_with_color(unsigned pos, unsigned col, float x1, float y1, fl immVertex2f(pos, x2, y2); immAttrib4fv(col, color); immVertex2f(pos, x1, y2); - } +} -void immRecti_fast_with_color(unsigned pos, unsigned col, int x1, int y1, int x2, int y2, const float color[4]) - { +void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]) +{ immAttrib4fv(col, color); immVertex2i(pos, x1, y1); immAttrib4fv(col, color); @@ -65,16 +85,16 @@ void immRecti_fast_with_color(unsigned pos, unsigned col, int x1, int y1, int x2 immVertex2i(pos, x2, y2); immAttrib4fv(col, color); immVertex2i(pos, x1, y2); - } +} -#if 0 // more complete version in case we want that +#if 0 /* more complete version in case we want that */ void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4]) - { +{ Gwn_VertFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + uint pos = add_attrib(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor4fv(color); immRecti(pos, x1, y1, x2, y2); immUnbindProgram(); - } +} #endif diff --git a/intern/gawain/src/gwn_immediate.c b/intern/gawain/src/gwn_immediate.c index f6760b0e9da..442aa85ece4 100644 --- a/intern/gawain/src/gwn_immediate.c +++ b/intern/gawain/src/gwn_immediate.c @@ -1,13 +1,33 @@ - -// Gawain immediate mode work-alike -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_immediate.c + * \ingroup gpu + * + * Gawain immediate mode work-alike + */ #include "gwn_immediate.h" #include "gwn_buffer_id.h" @@ -17,33 +37,32 @@ #include "gwn_vertex_array_id.h" #include "gwn_primitive_private.h" #include <string.h> +#include <stdlib.h> -// necessary functions from matrix API +/* necessary functions from matrix API */ extern void GPU_matrix_bind(const Gwn_ShaderInterface*); extern bool GPU_matrix_dirty_get(void); typedef struct { - // TODO: organize this struct by frequency of change (run-time) + /* TODO: organize this struct by frequency of change (run-time) */ -#if IMM_BATCH_COMBO Gwn_Batch* batch; -#endif Gwn_Context* context; - // current draw call + /* current draw call */ GLubyte* buffer_data; - unsigned buffer_offset; - unsigned buffer_bytes_mapped; - unsigned vertex_len; + uint buffer_offset; + uint buffer_bytes_mapped; + uint vertex_len; bool strict_vertex_len; Gwn_PrimType prim_type; Gwn_VertFormat vertex_format; - // current vertex - unsigned vertex_idx; + /* current vertex */ + uint vertex_idx; GLubyte* vertex_data; - uint16_t unassigned_attrib_bits; // which attributes of current vertex have not been given values? + uint16_t unassigned_attrib_bits; /* which attributes of current vertex have not been given values? */ GLuint vbo_id; GLuint vao_id; @@ -51,21 +70,20 @@ typedef struct { GLuint bound_program; const Gwn_ShaderInterface* shader_interface; Gwn_AttrBinding attrib_binding; - uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok + uint16_t prev_enabled_attrib_bits; /* <-- only affects this VAO, so we're ok */ } Immediate; -// size of internal buffer -- make this adjustable? +/* size of internal buffer -- make this adjustable? */ #define IMM_BUFFER_SIZE (4 * 1024 * 1024) static bool initialized = false; static Immediate imm; void immInit(void) - { +{ #if TRUST_NO_ONE assert(!initialized); #endif - memset(&imm, 0, sizeof(Immediate)); imm.vbo_id = GWN_buf_id_alloc(); @@ -77,45 +95,45 @@ void immInit(void) glBindBuffer(GL_ARRAY_BUFFER, 0); initialized = true; - } +} void immActivate(void) - { +{ #if TRUST_NO_ONE assert(initialized); - assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair + assert(imm.prim_type == GWN_PRIM_NONE); /* make sure we're not between a Begin/End pair */ assert(imm.vao_id == 0); #endif imm.vao_id = GWN_vao_alloc(); imm.context = GWN_context_active_get(); - } +} void immDeactivate(void) - { +{ #if TRUST_NO_ONE assert(initialized); - assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair + assert(imm.prim_type == GWN_PRIM_NONE); /* make sure we're not between a Begin/End pair */ assert(imm.vao_id != 0); #endif GWN_vao_free(imm.vao_id, imm.context); imm.vao_id = 0; imm.prev_enabled_attrib_bits = 0; - } +} void immDestroy(void) - { +{ GWN_buf_id_free(imm.vbo_id); initialized = false; - } +} Gwn_VertFormat* immVertexFormat(void) - { +{ GWN_vertformat_clear(&imm.vertex_format); return &imm.vertex_format; - } +} void immBindProgram(GLuint program, const Gwn_ShaderInterface* shaderface) - { +{ #if TRUST_NO_ONE assert(imm.bound_program == 0); assert(glIsProgram(program)); @@ -130,10 +148,10 @@ void immBindProgram(GLuint program, const Gwn_ShaderInterface* shaderface) glUseProgram(program); get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, shaderface); GPU_matrix_bind(shaderface); - } +} void immUnbindProgram(void) - { +{ #if TRUST_NO_ONE assert(imm.bound_program != 0); #endif @@ -141,17 +159,17 @@ void immUnbindProgram(void) glUseProgram(0); #endif imm.bound_program = 0; - } +} #if TRUST_NO_ONE -static bool vertex_count_makes_sense_for_primitive(unsigned vertex_len, Gwn_PrimType prim_type) - { - // does vertex_len make sense for this primitive type? - if (vertex_len == 0) +static bool vertex_count_makes_sense_for_primitive(uint vertex_len, Gwn_PrimType prim_type) +{ + /* does vertex_len make sense for this primitive type? */ + if (vertex_len == 0) { return false; + } - switch (prim_type) - { + switch (prim_type) { case GWN_PRIM_POINTS: return true; case GWN_PRIM_LINES: @@ -168,25 +186,24 @@ static bool vertex_count_makes_sense_for_primitive(unsigned vertex_len, Gwn_Prim return vertex_len >= 3; default: return false; - } } +} #endif -void immBegin(Gwn_PrimType prim_type, unsigned vertex_len) - { +void immBegin(Gwn_PrimType prim_type, uint vertex_len) +{ #if TRUST_NO_ONE assert(initialized); - assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun + assert(imm.prim_type == GWN_PRIM_NONE); /* make sure we haven't already begun */ assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); #endif - imm.prim_type = prim_type; imm.vertex_len = vertex_len; imm.vertex_idx = 0; imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits; - // how many bytes do we need for this draw call? - const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len); + /* how many bytes do we need for this draw call? */ + const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len); #if TRUST_NO_ONE assert(bytes_needed <= IMM_BUFFER_SIZE); @@ -194,41 +211,22 @@ void immBegin(Gwn_PrimType prim_type, unsigned vertex_len) glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - // does the current buffer have enough room? - const unsigned available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset; - // ensure vertex data is aligned - const unsigned pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); // might waste a little space, but it's safe - if ((bytes_needed + pre_padding) <= available_bytes) + /* does the current buffer have enough room? */ + const uint available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset; + /* ensure vertex data is aligned */ + const uint pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); /* might waste a little space, but it's safe */ + if ((bytes_needed + pre_padding) <= available_bytes) { imm.buffer_offset += pre_padding; - else - { - // orphan this buffer & start with a fresh one -#if 1 - // this method works on all platforms, old & new + } + else { + /* orphan this buffer & start with a fresh one */ + /* this method works on all platforms, old & new */ glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); -#else - // TODO: use other (more recent) methods after thorough testing - if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata) - glInvalidateBufferData(imm.vbo_id); - else - { - // glitches! -// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT); - - // works -// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, -// GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); -// glUnmapBuffer(GL_ARRAY_BUFFER); - - // also works - glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); - } -#endif imm.buffer_offset = 0; - } + } -// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); +/* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); @@ -239,28 +237,26 @@ void immBegin(Gwn_PrimType prim_type, unsigned vertex_len) imm.buffer_bytes_mapped = bytes_needed; imm.vertex_data = imm.buffer_data; - } +} -void immBeginAtMost(Gwn_PrimType prim_type, unsigned vertex_len) - { +void immBeginAtMost(Gwn_PrimType prim_type, uint vertex_len) +{ #if TRUST_NO_ONE assert(vertex_len > 0); #endif imm.strict_vertex_len = false; immBegin(prim_type, vertex_len); - } +} -#if IMM_BATCH_COMBO -Gwn_Batch* immBeginBatch(Gwn_PrimType prim_type, unsigned vertex_len) - { +Gwn_Batch* immBeginBatch(Gwn_PrimType prim_type, uint vertex_len) +{ #if TRUST_NO_ONE assert(initialized); - assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun + assert(imm.prim_type == GWN_PRIM_NONE); /* make sure we haven't already begun */ assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); #endif - imm.prim_type = prim_type; imm.vertex_len = vertex_len; imm.vertex_idx = 0; @@ -276,59 +272,47 @@ Gwn_Batch* immBeginBatch(Gwn_PrimType prim_type, unsigned vertex_len) imm.batch->phase = GWN_BATCH_BUILDING; return imm.batch; - } +} -Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType prim_type, unsigned vertex_len) - { +Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType prim_type, uint vertex_len) +{ imm.strict_vertex_len = false; return immBeginBatch(prim_type, vertex_len); - } - -#endif // IMM_BATCH_COMBO +} static void immDrawSetup(void) - { - // set up VAO -- can be done during Begin or End really +{ + /* set up VAO -- can be done during Begin or End really */ glBindVertexArray(imm.vao_id); - // enable/disable vertex attribs as needed - if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits) - { - for (unsigned loc = 0; loc < GWN_VERT_ATTR_MAX_LEN; ++loc) - { + /* enable/disable vertex attribs as needed */ + if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits) { + for (uint loc = 0; loc < GWN_VERT_ATTR_MAX_LEN; ++loc) { bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc); bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc); - if (is_enabled && !was_enabled) - { -// printf("enabling attrib %u\n", loc); + if (is_enabled && !was_enabled) { glEnableVertexAttribArray(loc); - } - else if (was_enabled && !is_enabled) - { -// printf("disabling attrib %u\n", loc); + } + else if (was_enabled && !is_enabled) { glDisableVertexAttribArray(loc); - } } + } imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits; - } + } - const unsigned stride = imm.vertex_format.stride; + const uint stride = imm.vertex_format.stride; - for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) - { + for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx; - const unsigned offset = imm.buffer_offset + a->offset; + const uint offset = imm.buffer_offset + a->offset; const GLvoid* pointer = (const GLubyte*)0 + offset; - const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx); - -// printf("specifying attrib %u '%s' with offset %u, stride %u\n", loc, a->name, offset, stride); + const uint loc = read_attrib_location(&imm.attrib_binding, a_idx); - switch (a->fetch_mode) - { + switch (a->fetch_mode) { case GWN_FETCH_FLOAT: case GWN_FETCH_INT_TO_FLOAT: glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); @@ -338,414 +322,372 @@ static void immDrawSetup(void) break; case GWN_FETCH_INT: glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer); - } } + } - if (GPU_matrix_dirty_get()) + if (GPU_matrix_dirty_get()) { GPU_matrix_bind(imm.shader_interface); } +} void immEnd(void) - { +{ #if TRUST_NO_ONE - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - unsigned buffer_bytes_used; - if (imm.strict_vertex_len) - { + uint buffer_bytes_used; + if (imm.strict_vertex_len) { #if TRUST_NO_ONE - assert(imm.vertex_idx == imm.vertex_len); // with all vertices defined + assert(imm.vertex_idx == imm.vertex_len); /* with all vertices defined */ #endif buffer_bytes_used = imm.buffer_bytes_mapped; - } - else - { + } + else { #if TRUST_NO_ONE assert(imm.vertex_idx <= imm.vertex_len); #endif - // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_len); - if (imm.vertex_idx == imm.vertex_len) - { + if (imm.vertex_idx == imm.vertex_len) { buffer_bytes_used = imm.buffer_bytes_mapped; - } - else - { + } + else { #if TRUST_NO_ONE assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type)); #endif imm.vertex_len = imm.vertex_idx; buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len); - // unused buffer bytes are available to the next immBegin - // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped); - } - - // tell OpenGL what range was modified so it doesn't copy the whole mapped range - // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1); - glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); + /* unused buffer bytes are available to the next immBegin */ } + /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */ + glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); + } -#if IMM_BATCH_COMBO - if (imm.batch) - { - if (buffer_bytes_used != imm.buffer_bytes_mapped) - { + if (imm.batch) { + if (buffer_bytes_used != imm.buffer_bytes_mapped) { GWN_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len); - // TODO: resize only if vertex count is much smaller - } - + /* TODO: resize only if vertex count is much smaller */ + } GWN_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface); imm.batch->phase = GWN_BATCH_READY_TO_DRAW; - imm.batch = NULL; // don't free, batch belongs to caller - } - else -#endif - { + imm.batch = NULL; /* don't free, batch belongs to caller */ + } + else { glUnmapBuffer(GL_ARRAY_BUFFER); - - if (imm.vertex_len > 0) - { + if (imm.vertex_len > 0) { immDrawSetup(); glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len); - } - + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - - // prep for next immBegin + /* prep for next immBegin */ imm.buffer_offset += buffer_bytes_used; - } + } - // prep for next immBegin + /* prep for next immBegin */ imm.prim_type = GWN_PRIM_NONE; imm.strict_vertex_len = true; - } +} -static void setAttribValueBit(unsigned attrib_id) - { +static void setAttribValueBit(uint attrib_id) +{ uint16_t mask = 1 << attrib_id; - #if TRUST_NO_ONE - assert(imm.unassigned_attrib_bits & mask); // not already set + assert(imm.unassigned_attrib_bits & mask); /* not already set */ #endif - imm.unassigned_attrib_bits &= ~mask; - } +} -// --- generic attribute functions --- +/* --- generic attribute functions --- */ -void immAttrib1f(unsigned attrib_id, float x) - { +void immAttrib1f(uint attrib_id, float x) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_F32); assert(attrib->comp_len == 1); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ data[0] = x; - } +} -void immAttrib2f(unsigned attrib_id, float x, float y) - { +void immAttrib2f(uint attrib_id, float x, float y) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_F32); assert(attrib->comp_len == 2); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ data[0] = x; data[1] = y; - } +} -void immAttrib3f(unsigned attrib_id, float x, float y, float z) - { +void immAttrib3f(uint attrib_id, float x, float y, float z) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_F32); assert(attrib->comp_len == 3); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ data[0] = x; data[1] = y; data[2] = z; - } +} -void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w) - { +void immAttrib4f(uint attrib_id, float x, float y, float z, float w) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_F32); assert(attrib->comp_len == 4); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ data[0] = x; data[1] = y; data[2] = z; data[3] = w; - } +} -void immAttrib1u(unsigned attrib_id, unsigned x) - { +void immAttrib1u(uint attrib_id, uint x) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_U32); assert(attrib->comp_len == 1); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); - unsigned* data = (unsigned*)(imm.vertex_data + attrib->offset); + uint* data = (uint*)(imm.vertex_data + attrib->offset); data[0] = x; - } +} -void immAttrib2i(unsigned attrib_id, int x, int y) - { +void immAttrib2i(uint attrib_id, int x, int y) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_I32); assert(attrib->comp_len == 2); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); int* data = (int*)(imm.vertex_data + attrib->offset); data[0] = x; data[1] = y; - } +} -void immAttrib2s(unsigned attrib_id, short x, short y) - { +void immAttrib2s(uint attrib_id, short x, short y) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_I16); assert(attrib->comp_len == 2); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); short* data = (short*)(imm.vertex_data + attrib->offset); data[0] = x; data[1] = y; - } +} -void immAttrib2fv(unsigned attrib_id, const float data[2]) - { +void immAttrib2fv(uint attrib_id, const float data[2]) +{ immAttrib2f(attrib_id, data[0], data[1]); - } +} -void immAttrib3fv(unsigned attrib_id, const float data[3]) - { +void immAttrib3fv(uint attrib_id, const float data[3]) +{ immAttrib3f(attrib_id, data[0], data[1], data[2]); - } +} -void immAttrib4fv(unsigned attrib_id, const float data[4]) - { +void immAttrib4fv(uint attrib_id, const float data[4]) +{ immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]); - } +} -void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b) - { +void immAttrib3ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_U8); assert(attrib->comp_len == 3); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); GLubyte* data = imm.vertex_data + attrib->offset; -// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ data[0] = r; data[1] = g; data[2] = b; - } +} -void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a) - { +void immAttrib4ub(uint attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id; - #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(attrib->comp_type == GWN_COMP_U8); assert(attrib->comp_len == 4); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); GLubyte* data = imm.vertex_data + attrib->offset; -// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); +/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ data[0] = r; data[1] = g; data[2] = b; data[3] = a; - } +} -void immAttrib3ubv(unsigned attrib_id, const unsigned char data[3]) - { +void immAttrib3ubv(uint attrib_id, const unsigned char data[3]) +{ immAttrib3ub(attrib_id, data[0], data[1], data[2]); - } +} -void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]) - { +void immAttrib4ubv(uint attrib_id, const unsigned char data[4]) +{ immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]); - } +} -void immSkipAttrib(unsigned attrib_id) - { +void immSkipAttrib(uint attrib_id) +{ #if TRUST_NO_ONE assert(attrib_id < imm.vertex_format.attr_len); assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttribValueBit(attrib_id); - } +} -static void immEndVertex(void) // and move on to the next vertex - { +static void immEndVertex(void) /* and move on to the next vertex */ +{ #if TRUST_NO_ONE - assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair + assert(imm.prim_type != GWN_PRIM_NONE); /* make sure we're between a Begin/End pair */ assert(imm.vertex_idx < imm.vertex_len); #endif - // have all attribs been assigned values? - // if not, copy value from previous vertex - if (imm.unassigned_attrib_bits) - { + /* have all attribs been assigned values? + * if not, copy value from previous vertex */ + if (imm.unassigned_attrib_bits) { #if TRUST_NO_ONE - assert(imm.vertex_idx > 0); // first vertex must have all attribs specified + assert(imm.vertex_idx > 0); /* first vertex must have all attribs specified */ #endif - - for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) - { - if ((imm.unassigned_attrib_bits >> a_idx) & 1) - { + for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { + if ((imm.unassigned_attrib_bits >> a_idx) & 1) { const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx; -// printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx); +/* printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx); */ GLubyte* data = imm.vertex_data + a->offset; memcpy(data, data - imm.vertex_format.stride, a->sz); - // TODO: consolidate copy of adjacent attributes - } + /* TODO: consolidate copy of adjacent attributes */ } } + } imm.vertex_idx++; imm.vertex_data += imm.vertex_format.stride; imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits; - } +} -void immVertex2f(unsigned attrib_id, float x, float y) - { +void immVertex2f(uint attrib_id, float x, float y) +{ immAttrib2f(attrib_id, x, y); immEndVertex(); - } +} -void immVertex3f(unsigned attrib_id, float x, float y, float z) - { +void immVertex3f(uint attrib_id, float x, float y, float z) +{ immAttrib3f(attrib_id, x, y, z); immEndVertex(); - } +} -void immVertex4f(unsigned attrib_id, float x, float y, float z, float w) - { +void immVertex4f(uint attrib_id, float x, float y, float z, float w) +{ immAttrib4f(attrib_id, x, y, z, w); immEndVertex(); - } +} -void immVertex2i(unsigned attrib_id, int x, int y) - { +void immVertex2i(uint attrib_id, int x, int y) +{ immAttrib2i(attrib_id, x, y); immEndVertex(); - } +} -void immVertex2s(unsigned attrib_id, short x, short y) - { +void immVertex2s(uint attrib_id, short x, short y) +{ immAttrib2s(attrib_id, x, y); immEndVertex(); - } +} -void immVertex2fv(unsigned attrib_id, const float data[2]) - { +void immVertex2fv(uint attrib_id, const float data[2]) +{ immAttrib2f(attrib_id, data[0], data[1]); immEndVertex(); - } +} -void immVertex3fv(unsigned attrib_id, const float data[3]) - { +void immVertex3fv(uint attrib_id, const float data[3]) +{ immAttrib3f(attrib_id, data[0], data[1], data[2]); immEndVertex(); - } +} -void immVertex2iv(unsigned attrib_id, const int data[2]) - { +void immVertex2iv(uint attrib_id, const int data[2]) +{ immAttrib2i(attrib_id, data[0], data[1]); immEndVertex(); - } +} -// --- generic uniform functions --- +/* --- generic uniform functions --- */ #if 0 #if TRUST_NO_ONE @@ -754,49 +696,49 @@ void immVertex2iv(unsigned attrib_id, const int data[2]) #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); #endif #else - // NOTE: It is possible to have uniform fully optimized out from the shader. - // In this case we can't assert failure or allow NULL-pointer dereference. - // TODO(sergey): How can we detect existing-but-optimized-out uniform but still - // catch typos in uniform names passed to immUniform*() functions? + /* NOTE: It is possible to have uniform fully optimized out from the shader. + * In this case we can't assert failure or allow NULL-pointer dereference. + * TODO(sergey): How can we detect existing-but-optimized-out uniform but still + * catch typos in uniform names passed to immUniform*() functions? */ #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); if (uniform == NULL) return; #endif void immUniform1f(const char* name, float x) - { +{ GET_UNIFORM glUniform1f(uniform->location, x); - } +} void immUniform2f(const char* name, float x, float y) - { +{ GET_UNIFORM glUniform2f(uniform->location, x, y); - } +} void immUniform2fv(const char* name, const float data[2]) - { +{ GET_UNIFORM glUniform2fv(uniform->location, 1, data); - } +} void immUniform3f(const char* name, float x, float y, float z) - { +{ GET_UNIFORM glUniform3f(uniform->location, x, y, z); - } +} void immUniform3fv(const char* name, const float data[3]) - { +{ GET_UNIFORM glUniform3fv(uniform->location, 1, data); - } +} -// can increase this limit or move to another file +/* can increase this limit or move to another file */ #define MAX_UNIFORM_NAME_LEN 60 void immUniformArray3fv(const char* bare_name, const float *data, int count) - { - // look up "name[0]" when given "name" +{ + /* look up "name[0]" when given "name" */ const size_t len = strlen(bare_name); #if TRUST_NO_ONE assert(len <= MAX_UNIFORM_NAME_LEN); @@ -810,23 +752,23 @@ void immUniformArray3fv(const char* bare_name, const float *data, int count) GET_UNIFORM glUniform3fv(uniform->location, count, data); - } +} void immUniform4f(const char* name, float x, float y, float z, float w) - { +{ GET_UNIFORM glUniform4f(uniform->location, x, y, z, w); - } +} void immUniform4fv(const char* name, const float data[4]) - { +{ GET_UNIFORM glUniform4fv(uniform->location, 1, data); - } +} void immUniformArray4fv(const char* bare_name, const float *data, int count) - { - // look up "name[0]" when given "name" +{ + /* look up "name[0]" when given "name" */ const size_t len = strlen(bare_name); #if TRUST_NO_ONE assert(len <= MAX_UNIFORM_NAME_LEN); @@ -840,84 +782,82 @@ void immUniformArray4fv(const char* bare_name, const float *data, int count) GET_UNIFORM glUniform4fv(uniform->location, count, data); - } +} void immUniformMatrix4fv(const char* name, const float data[4][4]) - { +{ GET_UNIFORM glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data); - } +} void immUniform1i(const char* name, int x) - { +{ GET_UNIFORM glUniform1i(uniform->location, x); - } +} void immUniform4iv(const char* name, const int data[4]) - { +{ GET_UNIFORM glUniform4iv(uniform->location, 1, data); - } +} -// --- convenience functions for setting "uniform vec4 color" --- +/* --- convenience functions for setting "uniform vec4 color" --- */ void immUniformColor4f(float r, float g, float b, float a) - { +{ const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform_builtin(imm.shader_interface, GWN_UNIFORM_COLOR); - #if TRUST_NO_ONE assert(uniform != NULL); #endif - glUniform4f(uniform->location, r, g, b, a); - } +} void immUniformColor4fv(const float rgba[4]) - { +{ immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]); - } +} void immUniformColor3f(float r, float g, float b) - { +{ immUniformColor4f(r, g, b, 1.0f); - } +} void immUniformColor3fv(const float rgb[3]) - { +{ immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f); - } +} void immUniformColor3fvAlpha(const float rgb[3], float a) - { +{ immUniformColor4f(rgb[0], rgb[1], rgb[2], a); - } +} -// TODO: v-- treat as sRGB? --v +/* TODO: v-- treat as sRGB? --v */ void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b) - { +{ const float scale = 1.0f / 255.0f; immUniformColor4f(scale * r, scale * g, scale * b, 1.0f); - } +} void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) - { +{ const float scale = 1.0f / 255.0f; immUniformColor4f(scale * r, scale * g, scale * b, scale * a); - } +} void immUniformColor3ubv(const unsigned char rgb[3]) - { +{ immUniformColor3ub(rgb[0], rgb[1], rgb[2]); - } +} void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char alpha) - { +{ immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha); - } +} void immUniformColor4ubv(const unsigned char rgba[4]) - { +{ immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]); - } +} diff --git a/intern/gawain/src/gwn_primitive.c b/intern/gawain/src/gwn_primitive.c index c2638bcc8c8..bec638a4972 100644 --- a/intern/gawain/src/gwn_primitive.c +++ b/intern/gawain/src/gwn_primitive.c @@ -1,21 +1,40 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ -// Gawain geometric primitives -// -// 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/. +/** \file blender/gpu/intern/gwn_primitive.c + * \ingroup gpu + * + * Gawain geometric primitives + */ #include "gwn_primitive.h" #include "gwn_primitive_private.h" Gwn_PrimClass GWN_primtype_class(Gwn_PrimType prim_type) - { - static const Gwn_PrimClass classes[] = - { +{ + static const Gwn_PrimClass classes[] = { [GWN_PRIM_POINTS] = GWN_PRIM_CLASS_POINT, [GWN_PRIM_LINES] = GWN_PRIM_CLASS_LINE, [GWN_PRIM_LINE_STRIP] = GWN_PRIM_CLASS_LINE, @@ -29,27 +48,25 @@ Gwn_PrimClass GWN_primtype_class(Gwn_PrimType prim_type) [GWN_PRIM_TRIS_ADJ] = GWN_PRIM_CLASS_SURFACE, [GWN_PRIM_NONE] = GWN_PRIM_CLASS_NONE - }; + }; return classes[prim_type]; - } +} bool GWN_primtype_belongs_to_class(Gwn_PrimType prim_type, Gwn_PrimClass prim_class) - { - if (prim_class == GWN_PRIM_CLASS_NONE && prim_type == GWN_PRIM_NONE) +{ + if (prim_class == GWN_PRIM_CLASS_NONE && prim_type == GWN_PRIM_NONE) { return true; - - return prim_class & GWN_primtype_class(prim_type); } + return prim_class & GWN_primtype_class(prim_type); +} GLenum convert_prim_type_to_gl(Gwn_PrimType prim_type) - { +{ #if TRUST_NO_ONE assert(prim_type != GWN_PRIM_NONE); #endif - - static const GLenum table[] = - { + static const GLenum table[] = { [GWN_PRIM_POINTS] = GL_POINTS, [GWN_PRIM_LINES] = GL_LINES, [GWN_PRIM_LINE_STRIP] = GL_LINE_STRIP, @@ -61,7 +78,7 @@ GLenum convert_prim_type_to_gl(Gwn_PrimType prim_type) [GWN_PRIM_LINES_ADJ] = GL_LINES_ADJACENCY, [GWN_PRIM_LINE_STRIP_ADJ] = GL_LINE_STRIP_ADJACENCY, [GWN_PRIM_TRIS_ADJ] = GL_TRIANGLES_ADJACENCY, - }; + }; return table[prim_type]; - } +} diff --git a/intern/gawain/src/gwn_shader_interface.c b/intern/gawain/src/gwn_shader_interface.c index d18af234fb0..997d5215d5b 100644 --- a/intern/gawain/src/gwn_shader_interface.c +++ b/intern/gawain/src/gwn_shader_interface.c @@ -1,13 +1,33 @@ - -// 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_shader_interface.c + * \ingroup gpu + * + * Gawain shader interface (C --> GLSL) + */ #include "gwn_batch_private.h" #include "gwn_shader_interface.h" @@ -23,9 +43,8 @@ #endif static const char* BuiltinUniform_name(Gwn_UniformBuiltin u) - { - static const char* names[] = - { +{ + static const char* names[] = { [GWN_UNIFORM_NONE] = NULL, [GWN_UNIFORM_MODEL] = "ModelMatrix", @@ -52,154 +71,142 @@ static const char* BuiltinUniform_name(Gwn_UniformBuiltin u) [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++)) - { +GWN_INLINE uint hash_string(const char *str) +{ + uint i = 0, c; + while ((c = *str++)) { i = i * 37 + c; - } - - return i; } + 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 - } + 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; +{ + const uint 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 uint name_hash = hash_string(name); + const uint 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 (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)); + assert(match(name_buffer + input->name_offset, name)); #endif - return input; - } - return NULL; + return input; } - // Work through possible collisions. + return NULL; + } + /* Work through possible collisions. */ const Gwn_ShaderInput* next = input; - while (next != NULL) - { + while (next != NULL) { input = next; next = input->next; - - if (input->name_hash != name_hash) - { + if (input->name_hash != name_hash) { continue; - } - if (match(name_buffer + input->name_offset, name)) - { + } + if (match(name_buffer + input->name_offset, name)) { return input; - } } - return NULL; // not found } + 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) - { +{ + for (uint bucket_index = 0; bucket_index < GWN_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) { Gwn_ShaderInput *input = buckets[bucket_index]; - while (input != NULL) - { + 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 +{ + /* 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) - { + /* 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)) - { + 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)); +{ + Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput)); - input->location = glGetUniformLocation(shaderface->program, name); + 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); + uint 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; - } + 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); + printf("Gwn_ShaderInterface %p, program %d, uniform[] '%s' at location %d\n", shaderface, + shaderface->program, + name, + input->location); #endif - return input; - } + return input; +} Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program) - { +{ Gwn_ShaderInterface* shaderface = calloc(1, sizeof(Gwn_ShaderInterface)); shaderface->program = program; #if DEBUG_SHADER_INTERFACE - printf("%s {\n", __func__); // enter function + printf("%s {\n", __func__); /* enter function */ printf("Gwn_ShaderInterface %p, program %d\n", shaderface, program); #endif @@ -214,9 +221,8 @@ Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program) const uint32_t name_buffer_len = attr_len * max_attrib_name_len + ubo_len * max_ubo_name_len; shaderface->name_buffer = malloc(name_buffer_len); - // Attributes - for (uint32_t i = 0; i < attr_len; ++i) - { + /* Attributes */ + for (uint32_t i = 0; i < attr_len; ++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; @@ -224,14 +230,13 @@ Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program) glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); - // remove "[0]" from array name - if (name[name_len-1] == ']') - { + /* remove "[0]" from array name */ + if (name[name_len-1] == ']') { name[name_len-3] = '\0'; name_len -= 3; - } + } - // TODO: reject DOUBLE gl_types + /* TODO: reject DOUBLE gl_types */ input->location = glGetAttribLocation(program, name); @@ -242,11 +247,9 @@ Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program) #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_len; ++i) - { + } + /* Uniform Blocks */ + for (uint32_t i = 0; i < ubo_len; ++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; @@ -263,100 +266,96 @@ Gwn_ShaderInterface* GWN_shaderinterface_create(int32_t program) #if DEBUG_SHADER_INTERFACE printf("ubo '%s' at location %d\n", name, input->location); #endif - } - - // Builtin Uniforms - for (Gwn_UniformBuiltin u = GWN_UNIFORM_NONE + 1; u < GWN_UNIFORM_CUSTOM; ++u) - { + } + /* Builtin Uniforms */ + for (Gwn_UniformBuiltin u = GWN_UNIFORM_NONE + 1; u < GWN_UNIFORM_CUSTOM; ++u) { const char* builtin_name = BuiltinUniform_name(u); - if (glGetUniformLocation(program, builtin_name) != -1) + if (glGetUniformLocation(program, builtin_name) != -1) { add_uniform((Gwn_ShaderInterface*)shaderface, builtin_name); } - - // Batches ref buffer + } + /* Batches ref buffer */ shaderface->batches_len = GWN_SHADERINTERFACE_REF_ALLOC_COUNT; shaderface->batches = calloc(shaderface->batches_len, sizeof(Gwn_Batch*)); return shaderface; - } +} void GWN_shaderinterface_discard(Gwn_ShaderInterface* shaderface) - { - // Free memory used by buckets and has entries. +{ + /* 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 memory used by name_buffer. */ free(shaderface->name_buffer); - // Remove this interface from all linked Batches vao cache. - for (int i = 0; i < shaderface->batches_len; ++i) - if (shaderface->batches[i] != NULL) + /* Remove this interface from all linked Batches vao cache. */ + for (int i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] != NULL) { gwn_batch_remove_interface_ref(shaderface->batches[i], shaderface); - + } + } free(shaderface->batches); - // Free memory used by shader interface by its self. + /* 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. +{ + /* 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) + /* 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; } + return (input->location != -1) ? input : NULL; +} -const Gwn_ShaderInput* GWN_shaderinterface_uniform_builtin(const Gwn_ShaderInterface* shaderface, Gwn_UniformBuiltin builtin) - { +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 return shaderface->builtin_uniforms[builtin]; - } +} 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); - } +} void GWN_shaderinterface_add_batch_ref(Gwn_ShaderInterface* shaderface, Gwn_Batch* batch) - { - int i; // find first unused slot - for (i = 0; i < shaderface->batches_len; ++i) - if (shaderface->batches[i] == NULL) +{ + int i; /* find first unused slot */ + for (i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] == NULL) { break; - - if (i == shaderface->batches_len) - { - // Not enough place, realloc the array. + } + } + if (i == shaderface->batches_len) { + /* Not enough place, realloc the array. */ i = shaderface->batches_len; shaderface->batches_len += GWN_SHADERINTERFACE_REF_ALLOC_COUNT; shaderface->batches = realloc(shaderface->batches, sizeof(Gwn_Batch*) * shaderface->batches_len); memset(shaderface->batches + i, 0, sizeof(Gwn_Batch*) * GWN_SHADERINTERFACE_REF_ALLOC_COUNT); - } - - shaderface->batches[i] = batch; } + shaderface->batches[i] = batch; +} void GWN_shaderinterface_remove_batch_ref(Gwn_ShaderInterface* shaderface, Gwn_Batch* batch) - { - for (int i = 0; i < shaderface->batches_len; ++i) - { - if (shaderface->batches[i] == batch) - { +{ + for (int i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] == batch) { shaderface->batches[i] = NULL; - break; // cannot have duplicates - } + break; /* cannot have duplicates */ } } +} diff --git a/intern/gawain/src/gwn_vertex_array_id.cpp b/intern/gawain/src/gwn_vertex_array_id.cpp index 70294565e6a..04470bf6844 100644 --- a/intern/gawain/src/gwn_vertex_array_id.cpp +++ b/intern/gawain/src/gwn_vertex_array_id.cpp @@ -1,13 +1,38 @@ - -// Gawain vertex array IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin, Clément Foucault -// -// 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" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Clément Foucault + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/gwn_vertex_array_id.cpp + * \ingroup gpu + * + * Manage GL vertex array IDs in a thread-safe way + * Use these instead of glGenBuffers & its friends + * - alloc must be called from a thread that is bound + * to the context that will be used for drawing with + * this vao. + * - free can be called from any thread + */ #include "gwn_batch_private.h" #include "gwn_vertex_array_id.h" @@ -21,30 +46,28 @@ #if TRUST_NO_ONE #if 0 extern "C" { -extern int BLI_thread_is_main(void); // Blender-specific function +extern int BLI_thread_is_main(void); /* Blender-specific function */ } -static bool thread_is_main() - { - // "main" here means the GL context's thread +static bool thread_is_main() { + /* "main" here means the GL context's thread */ return BLI_thread_is_main(); - } +} #endif #endif struct Gwn_Context { GLuint default_vao; - std::unordered_set<Gwn_Batch*> batches; // Batches that have VAOs from this context + std::unordered_set<Gwn_Batch*> batches; /* Batches that have VAOs from this context */ std::vector<GLuint> orphaned_vertarray_ids; - std::mutex orphans_mutex; // todo: try spinlock instead + std::mutex orphans_mutex; /* todo: try spinlock instead */ #if TRUST_NO_ONE - pthread_t thread; // Thread on which this context is active. + pthread_t thread; /* Thread on which this context is active. */ bool thread_is_used; - Gwn_Context() - { + Gwn_Context() { thread_is_used = false; - } + } #endif }; @@ -56,119 +79,118 @@ static thread_local Gwn_Context* active_ctx = NULL; #endif static void clear_orphans(Gwn_Context* ctx) - { +{ ctx->orphans_mutex.lock(); - if (!ctx->orphaned_vertarray_ids.empty()) - { - unsigned orphan_len = (unsigned)ctx->orphaned_vertarray_ids.size(); + if (!ctx->orphaned_vertarray_ids.empty()) { + uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size(); glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data()); ctx->orphaned_vertarray_ids.clear(); - } - ctx->orphans_mutex.unlock(); } + ctx->orphans_mutex.unlock(); +} Gwn_Context* GWN_context_create(void) - { +{ #if TRUST_NO_ONE - // assert(thread_is_main()); + /* assert(thread_is_main()); */ #endif Gwn_Context* ctx = new Gwn_Context; glGenVertexArrays(1, &ctx->default_vao); GWN_context_active_set(ctx); return ctx; - } +} -// to be called after GWN_context_active_set(ctx_to_destroy) +/* to be called after GWN_context_active_set(ctx_to_destroy) */ void GWN_context_discard(Gwn_Context* ctx) - { +{ #if TRUST_NO_ONE - // Make sure no other thread has locked it. + /* Make sure no other thread has locked it. */ assert(ctx == active_ctx); assert(pthread_equal(pthread_self(), ctx->thread)); assert(ctx->orphaned_vertarray_ids.empty()); #endif - // delete remaining vaos - while (!ctx->batches.empty()) - { - // this removes the array entry + /* delete remaining vaos */ + while (!ctx->batches.empty()) { + /* this removes the array entry */ gwn_batch_vao_cache_clear(*ctx->batches.begin()); - } + } glDeleteVertexArrays(1, &ctx->default_vao); delete ctx; active_ctx = NULL; - } +} -// ctx can be NULL +/* ctx can be NULL */ void GWN_context_active_set(Gwn_Context* ctx) - { +{ #if TRUST_NO_ONE - if (active_ctx) + if (active_ctx) { active_ctx->thread_is_used = false; - // Make sure no other context is already bound to this thread. - if (ctx) - { - // Make sure no other thread has locked it. + } + /* Make sure no other context is already bound to this thread. */ + if (ctx) { + /* Make sure no other thread has locked it. */ assert(ctx->thread_is_used == false); ctx->thread = pthread_self(); ctx->thread_is_used = true; - } + } #endif - if (ctx) + if (ctx) { clear_orphans(ctx); - active_ctx = ctx; } + active_ctx = ctx; +} Gwn_Context* GWN_context_active_get(void) - { +{ return active_ctx; - } +} GLuint GWN_vao_default(void) - { +{ #if TRUST_NO_ONE - assert(active_ctx); // need at least an active context - assert(pthread_equal(pthread_self(), active_ctx->thread)); // context has been activated by another thread! + assert(active_ctx); /* need at least an active context */ + assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ #endif return active_ctx->default_vao; - } +} GLuint GWN_vao_alloc(void) - { +{ #if TRUST_NO_ONE - assert(active_ctx); // need at least an active context - assert(pthread_equal(pthread_self(), active_ctx->thread)); // context has been activated by another thread! + assert(active_ctx); /* need at least an active context */ + assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ #endif clear_orphans(active_ctx); GLuint new_vao_id = 0; glGenVertexArrays(1, &new_vao_id); return new_vao_id; - } +} -// this can be called from multiple thread +/* this can be called from multiple thread */ void GWN_vao_free(GLuint vao_id, Gwn_Context* ctx) - { +{ #if TRUST_NO_ONE assert(ctx); #endif - if (ctx == active_ctx) + if (ctx == active_ctx) { glDeleteVertexArrays(1, &vao_id); - else - { + } + else { ctx->orphans_mutex.lock(); ctx->orphaned_vertarray_ids.emplace_back(vao_id); ctx->orphans_mutex.unlock(); - } } +} void gwn_context_add_batch(Gwn_Context* ctx, Gwn_Batch* batch) - { +{ ctx->batches.emplace(batch); - } +} void gwn_context_remove_batch(Gwn_Context* ctx, Gwn_Batch* batch) - { +{ ctx->orphans_mutex.lock(); ctx->batches.erase(batch); ctx->orphans_mutex.unlock(); - } +} diff --git a/intern/gawain/src/gwn_vertex_buffer.c b/intern/gawain/src/gwn_vertex_buffer.c index a372c62bd0a..c3440b25da2 100644 --- a/intern/gawain/src/gwn_vertex_buffer.c +++ b/intern/gawain/src/gwn_vertex_buffer.c @@ -1,13 +1,33 @@ - -// Gawain vertex buffer -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Clément Foucault + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_vertex_buffer.c + * \ingroup gpu + * + * Gawain vertex buffer + */ #include "gwn_vertex_buffer.h" #include "gwn_buffer_id.h" @@ -17,141 +37,137 @@ #define KEEP_SINGLE_COPY 1 -static unsigned vbo_memory_usage; +static uint vbo_memory_usage; static GLenum convert_usage_type_to_gl(Gwn_UsageType type) - { +{ static const GLenum table[] = { [GWN_USAGE_STREAM] = GL_STREAM_DRAW, [GWN_USAGE_STATIC] = GL_STATIC_DRAW, [GWN_USAGE_DYNAMIC] = GL_DYNAMIC_DRAW - }; + }; return table[type]; - } +} Gwn_VertBuf* GWN_vertbuf_create(Gwn_UsageType usage) - { +{ Gwn_VertBuf* verts = malloc(sizeof(Gwn_VertBuf)); GWN_vertbuf_init(verts, usage); return verts; - } +} Gwn_VertBuf* GWN_vertbuf_create_with_format_ex(const Gwn_VertFormat* format, Gwn_UsageType usage) - { +{ Gwn_VertBuf* verts = GWN_vertbuf_create(usage); GWN_vertformat_copy(&verts->format, format); - if (!format->packed) + if (!format->packed) { VertexFormat_pack(&verts->format); + } return verts; - // this function might seem redundant, but there is potential for memory savings here... - // TODO: implement those memory savings - } + /* this function might seem redundant, but there is potential for memory savings here... */ + /* TODO: implement those memory savings */ +} void GWN_vertbuf_init(Gwn_VertBuf* verts, Gwn_UsageType usage) - { +{ memset(verts, 0, sizeof(Gwn_VertBuf)); verts->usage = usage; verts->dirty = true; - } +} void GWN_vertbuf_init_with_format_ex(Gwn_VertBuf* verts, const Gwn_VertFormat* format, Gwn_UsageType usage) - { +{ GWN_vertbuf_init(verts, usage); GWN_vertformat_copy(&verts->format, format); - if (!format->packed) + if (!format->packed) { VertexFormat_pack(&verts->format); } +} void GWN_vertbuf_discard(Gwn_VertBuf* verts) - { - if (verts->vbo_id) - { +{ + if (verts->vbo_id) { GWN_buf_id_free(verts->vbo_id); #if VRAM_USAGE vbo_memory_usage -= GWN_vertbuf_size_get(verts); #endif - } - - if (verts->data) + } + if (verts->data) { free(verts->data); - - free(verts); } + free(verts); +} -unsigned GWN_vertbuf_size_get(const Gwn_VertBuf* verts) - { +uint GWN_vertbuf_size_get(const Gwn_VertBuf* verts) +{ return vertex_buffer_size(&verts->format, verts->vertex_len); - } +} -// create a new allocation, discarding any existing data -void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, unsigned v_len) - { +/* create a new allocation, discarding any existing data */ +void GWN_vertbuf_data_alloc(Gwn_VertBuf* verts, uint v_len) +{ Gwn_VertFormat* format = &verts->format; - if (!format->packed) + if (!format->packed) { VertexFormat_pack(format); - + } #if TRUST_NO_ONE - // catch any unnecessary use + /* catch any unnecessary use */ assert(verts->vertex_alloc != v_len || verts->data == NULL); #endif - - // only create the buffer the 1st time - if (verts->vbo_id == 0) + /* only create the buffer the 1st time */ + if (verts->vbo_id == 0) { verts->vbo_id = GWN_buf_id_alloc(); - - // discard previous data if any - if (verts->data) + } + /* discard previous data if any */ + if (verts->data) { free(verts->data); - + } #if VRAM_USAGE - unsigned new_size = vertex_buffer_size(&verts->format, v_len); + uint new_size = vertex_buffer_size(&verts->format, v_len); vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts); #endif - verts->dirty = true; verts->vertex_len = verts->vertex_alloc = v_len; verts->data = malloc(sizeof(GLubyte) * GWN_vertbuf_size_get(verts)); - } +} -// resize buffer keeping existing data -void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, unsigned v_len) - { +/* resize buffer keeping existing data */ +void GWN_vertbuf_data_resize(Gwn_VertBuf* verts, uint v_len) +{ #if TRUST_NO_ONE assert(verts->data != NULL); assert(verts->vertex_alloc != v_len); #endif #if VRAM_USAGE - unsigned new_size = vertex_buffer_size(&verts->format, v_len); + uint new_size = vertex_buffer_size(&verts->format, v_len); vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts); #endif - verts->dirty = true; verts->vertex_len = verts->vertex_alloc = v_len; verts->data = realloc(verts->data, sizeof(GLubyte) * GWN_vertbuf_size_get(verts)); - } +} -// set vertex count but does not change allocation -// only this many verts will be uploaded to the GPU and rendered -// this is usefull for streaming data -void GWN_vertbuf_vertex_count_set(Gwn_VertBuf* verts, unsigned v_len) - { +/* Set vertex count but does not change allocation. + * Only this many verts will be uploaded to the GPU and rendered. + * This is usefull for streaming data. */ +void GWN_vertbuf_vertex_count_set(Gwn_VertBuf* verts, uint v_len) +{ #if TRUST_NO_ONE - assert(verts->data != NULL); // only for dynamic data + assert(verts->data != NULL); /* only for dynamic data */ assert(v_len <= verts->vertex_alloc); #endif #if VRAM_USAGE - unsigned new_size = vertex_buffer_size(&verts->format, v_len); + uint new_size = vertex_buffer_size(&verts->format, v_len); vbo_memory_usage += new_size - GWN_vertbuf_size_get(verts); #endif - verts->vertex_len = v_len; - } +} -void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, const void* data) - { +void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, uint a_idx, uint v_idx, const void* data) +{ const Gwn_VertFormat* format = &verts->format; const Gwn_VertAttr* a = format->attribs + a_idx; @@ -160,27 +176,25 @@ void GWN_vertbuf_attr_set(Gwn_VertBuf* verts, unsigned a_idx, unsigned v_idx, co assert(v_idx < verts->vertex_alloc); assert(verts->data != NULL); #endif - verts->dirty = true; memcpy((GLubyte*)verts->data + a->offset + v_idx * format->stride, data, a->sz); - } +} -void GWN_vertbuf_attr_fill(Gwn_VertBuf* verts, unsigned a_idx, const void* data) - { +void GWN_vertbuf_attr_fill(Gwn_VertBuf* verts, uint a_idx, const void* data) +{ const Gwn_VertFormat* format = &verts->format; const Gwn_VertAttr* a = format->attribs + a_idx; #if TRUST_NO_ONE assert(a_idx < format->attr_len); #endif - - const unsigned stride = a->sz; // tightly packed input data + const uint stride = a->sz; /* tightly packed input data */ GWN_vertbuf_attr_fill_stride(verts, a_idx, stride, data); - } +} -void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned stride, const void* data) - { +void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, uint a_idx, uint stride, const void* data) +{ const Gwn_VertFormat* format = &verts->format; const Gwn_VertAttr* a = format->attribs + a_idx; @@ -188,25 +202,23 @@ void GWN_vertbuf_attr_fill_stride(Gwn_VertBuf* verts, unsigned a_idx, unsigned s assert(a_idx < format->attr_len); assert(verts->data != NULL); #endif - verts->dirty = true; - const unsigned vertex_len = verts->vertex_len; + const uint vertex_len = verts->vertex_len; - if (format->attr_len == 1 && stride == format->stride) - { - // we can copy it all at once + if (format->attr_len == 1 && stride == format->stride) { + /* we can copy it all at once */ memcpy(verts->data, data, vertex_len * a->sz); - } - else - { - // we must copy it per vertex - for (unsigned v = 0; v < vertex_len; ++v) + } + else { + /* we must copy it per vertex */ + for (uint v = 0; v < vertex_len; ++v) { memcpy((GLubyte*)verts->data + a->offset + v * format->stride, (const GLubyte*)data + v * stride, a->sz); } } +} -void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertBufRaw *access) - { +void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, uint a_idx, Gwn_VertBufRaw *access) +{ const Gwn_VertFormat* format = &verts->format; const Gwn_VertAttr* a = format->attribs + a_idx; @@ -224,35 +236,33 @@ void GWN_vertbuf_attr_get_raw_data(Gwn_VertBuf* verts, unsigned a_idx, Gwn_VertB #if TRUST_NO_ONE access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride); #endif - } +} static void VertBuffer_upload_data(Gwn_VertBuf* verts) - { - unsigned buffer_sz = GWN_vertbuf_size_get(verts); +{ + uint buffer_sz = GWN_vertbuf_size_get(verts); - // orphan the vbo to avoid sync + /* orphan the vbo to avoid sync */ glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage)); - // upload data + /* upload data */ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); - if (verts->usage == GWN_USAGE_STATIC) - { + if (verts->usage == GWN_USAGE_STATIC) { free(verts->data); verts->data = NULL; - } - - verts->dirty = false; } + verts->dirty = false; +} void GWN_vertbuf_use(Gwn_VertBuf* verts) - { +{ glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); - - if (verts->dirty) + if (verts->dirty) { VertBuffer_upload_data(verts); } +} -unsigned GWN_vertbuf_get_memory_usage(void) - { +uint GWN_vertbuf_get_memory_usage(void) +{ return vbo_memory_usage; - } +} diff --git a/intern/gawain/src/gwn_vertex_format.c b/intern/gawain/src/gwn_vertex_format.c index 122de12ec6e..41179ae21eb 100644 --- a/intern/gawain/src/gwn_vertex_format.c +++ b/intern/gawain/src/gwn_vertex_format.c @@ -1,13 +1,33 @@ - -// Gawain vertex format -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 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/. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2016 by Mike Erwin. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Clément Foucault + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gwn_vertex_format.c + * \ingroup gpu + * + * Gawain vertex format + */ #include "gwn_vertex_format.h" #include "gwn_vertex_format_private.h" @@ -21,7 +41,7 @@ #endif void GWN_vertformat_clear(Gwn_VertFormat* format) - { +{ #if TRUST_NO_ONE memset(format, 0, sizeof(Gwn_VertFormat)); #else @@ -30,23 +50,26 @@ void GWN_vertformat_clear(Gwn_VertFormat* format) format->name_offset = 0; format->name_len = 0; - for (unsigned i = 0; i < GWN_VERT_ATTR_MAX_LEN; i++) + for (unsigned i = 0; i < GWN_VERT_ATTR_MAX_LEN; i++) { format->attribs[i].name_len = 0; -#endif } +#endif +} void GWN_vertformat_copy(Gwn_VertFormat* dest, const Gwn_VertFormat* src) - { - // copy regular struct fields +{ + /* copy regular struct fields */ memcpy(dest, src, sizeof(Gwn_VertFormat)); - for (unsigned i = 0; i < dest->attr_len; i++) - for (unsigned j = 0; j < dest->attribs[i].name_len; j++) + for (unsigned i = 0; i < dest->attr_len; i++) { + for (unsigned j = 0; j < dest->attribs[i].name_len; j++) { dest->attribs[i].name[j] = (char *)dest + (src->attribs[i].name[j] - ((char *)src)); + } } +} static GLenum convert_comp_type_to_gl(Gwn_VertCompType type) - { +{ static const GLenum table[] = { [GWN_COMP_I8] = GL_BYTE, [GWN_COMP_U8] = GL_UNSIGNED_BYTE, @@ -58,105 +81,101 @@ static GLenum convert_comp_type_to_gl(Gwn_VertCompType type) [GWN_COMP_F32] = GL_FLOAT, [GWN_COMP_I10] = GL_INT_2_10_10_10_REV - }; + }; return table[type]; - } +} static unsigned comp_sz(Gwn_VertCompType type) - { +{ #if TRUST_NO_ONE - assert(type <= GWN_COMP_F32); // other types have irregular sizes (not bytes) + assert(type <= GWN_COMP_F32); /* other types have irregular sizes (not bytes) */ #endif - const GLubyte sizes[] = {1,1,2,2,4,4,4}; return sizes[type]; - } +} static unsigned attrib_sz(const Gwn_VertAttr *a) - { - if (a->comp_type == GWN_COMP_I10) - return 4; // always packed as 10_10_10_2 - - return a->comp_len * comp_sz(a->comp_type); +{ + if (a->comp_type == GWN_COMP_I10) { + return 4; /* always packed as 10_10_10_2 */ } + return a->comp_len * comp_sz(a->comp_type); +} static unsigned attrib_align(const Gwn_VertAttr *a) - { - if (a->comp_type == GWN_COMP_I10) - return 4; // always packed as 10_10_10_2 - +{ + if (a->comp_type == GWN_COMP_I10) { + return 4; /* always packed as 10_10_10_2 */ + } unsigned c = comp_sz(a->comp_type); - if (a->comp_len == 3 && c <= 2) - return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?) - else - return c; // most fetches are ok if components are naturally aligned + if (a->comp_len == 3 && c <= 2) { + return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */ + } + else { + return c; /* most fetches are ok if components are naturally aligned */ } +} unsigned vertex_buffer_size(const Gwn_VertFormat* format, unsigned vertex_len) - { +{ #if TRUST_NO_ONE assert(format->packed && format->stride > 0); #endif - return format->stride * vertex_len; - } +} static const char* copy_attrib_name(Gwn_VertFormat* format, const char* name) - { - // strncpy does 110% of what we need; let's do exactly 100% +{ + /* strncpy does 110% of what we need; let's do exactly 100% */ char* name_copy = format->names + format->name_offset; unsigned available = GWN_VERT_ATTR_NAMES_BUF_LEN - format->name_offset; bool terminated = false; - for (unsigned i = 0; i < available; ++i) - { + for (unsigned i = 0; i < available; ++i) { const char c = name[i]; name_copy[i] = c; - if (c == '\0') - { + if (c == '\0') { terminated = true; format->name_offset += (i + 1); break; - } } - + } #if TRUST_NO_ONE assert(terminated); assert(format->name_offset <= GWN_VERT_ATTR_NAMES_BUF_LEN); #else (void)terminated; #endif - return name_copy; - } +} unsigned GWN_vertformat_attr_add(Gwn_VertFormat* format, const char* name, Gwn_VertCompType comp_type, unsigned comp_len, Gwn_VertFetchMode fetch_mode) - { +{ #if TRUST_NO_ONE - assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more - assert(format->attr_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more - assert(!format->packed); // packed means frozen/locked + assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(format->attr_len < GWN_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(!format->packed); /* packed means frozen/locked */ assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16); - switch (comp_type) - { + + switch (comp_type) { case GWN_COMP_F32: - // float type can only kept as float + /* float type can only kept as float */ assert(fetch_mode == GWN_FETCH_FLOAT); break; case GWN_COMP_I10: - // 10_10_10 format intended for normals (xyz) or colors (rgb) - // extra component packed.w can be manually set to { -2, -1, 0, 1 } + /* 10_10_10 format intended for normals (xyz) or colors (rgb) + * extra component packed.w can be manually set to { -2, -1, 0, 1 } */ assert(comp_len == 3 || comp_len == 4); - assert(fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT); // not strictly required, may relax later + assert(fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT); /* not strictly required, may relax later */ break; default: - // integer types can be kept as int or converted/normalized to float + /* integer types can be kept as int or converted/normalized to float */ assert(fetch_mode != GWN_FETCH_FLOAT); - // only support float matrices (see Batch_update_program_bindings) + /* only support float matrices (see Batch_update_program_bindings) */ assert(comp_len != 8 && comp_len != 12 && comp_len != 16); - } + } #endif - format->name_len++; // multiname support + format->name_len++; /* multiname support */ const unsigned attrib_id = format->attr_len++; Gwn_VertAttr* attrib = format->attribs + attrib_id; @@ -164,53 +183,53 @@ unsigned GWN_vertformat_attr_add(Gwn_VertFormat* format, const char* name, Gwn_V attrib->name[attrib->name_len++] = copy_attrib_name(format, name); attrib->comp_type = comp_type; attrib->gl_comp_type = convert_comp_type_to_gl(comp_type); - attrib->comp_len = (comp_type == GWN_COMP_I10) ? 4 : comp_len; // system needs 10_10_10_2 to be 4 or BGRA + attrib->comp_len = (comp_type == GWN_COMP_I10) ? 4 : comp_len; /* system needs 10_10_10_2 to be 4 or BGRA */ attrib->sz = attrib_sz(attrib); - attrib->offset = 0; // offsets & stride are calculated later (during pack) + attrib->offset = 0; /* offsets & stride are calculated later (during pack) */ attrib->fetch_mode = fetch_mode; return attrib_id; - } +} void GWN_vertformat_alias_add(Gwn_VertFormat* format, const char* alias) - { +{ Gwn_VertAttr* attrib = format->attribs + (format->attr_len - 1); #if TRUST_NO_ONE - assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); // there's room for more + assert(format->name_len < GWN_VERT_ATTR_MAX_LEN); /* there's room for more */ assert(attrib->name_len < GWN_VERT_ATTR_MAX_NAMES); #endif - format->name_len++; // multiname support + format->name_len++; /* multiname support */ attrib->name[attrib->name_len++] = copy_attrib_name(format, alias); - } +} unsigned padding(unsigned offset, unsigned alignment) - { +{ const unsigned mod = offset % alignment; return (mod == 0) ? 0 : (alignment - mod); - } +} #if PACK_DEBUG static void show_pack(unsigned a_idx, unsigned sz, unsigned pad) - { +{ const char c = 'A' + a_idx; - for (unsigned i = 0; i < pad; ++i) + for (unsigned i = 0; i < pad; ++i) { putchar('-'); - for (unsigned i = 0; i < sz; ++i) + } + for (unsigned i = 0; i < sz; ++i) { putchar(c); } +} #endif void VertexFormat_pack(Gwn_VertFormat* format) - { - // for now, attributes are packed in the order they were added, - // making sure each attrib is naturally aligned (add padding where necessary) - - // later we can implement more efficient packing w/ reordering - // (keep attrib ID order, adjust their offsets to reorder in buffer) +{ + /* For now, attributes are packed in the order they were added, + * making sure each attrib is naturally aligned (add padding where necessary) + * Later we can implement more efficient packing w/ reordering + * (keep attrib ID order, adjust their offsets to reorder in buffer). */ - // TODO: - // realloc just enough to hold the final combo string. And just enough to - // hold used attribs, not all 16. + /* TODO: realloc just enough to hold the final combo string. And just enough to + * hold used attribs, not all 16. */ Gwn_VertAttr* a0 = format->attribs + 0; a0->offset = 0; @@ -220,8 +239,7 @@ void VertexFormat_pack(Gwn_VertFormat* format) show_pack(0, a0->sz, 0); #endif - for (unsigned a_idx = 1; a_idx < format->attr_len; ++a_idx) - { + for (unsigned a_idx = 1; a_idx < format->attr_len; ++a_idx) { Gwn_VertAttr* a = format->attribs + a_idx; unsigned mid_padding = padding(offset, attrib_align(a)); offset += mid_padding; @@ -231,7 +249,7 @@ void VertexFormat_pack(Gwn_VertFormat* format) #if PACK_DEBUG show_pack(a_idx, a->sz, mid_padding); #endif - } + } unsigned end_padding = padding(offset, attrib_align(a0)); @@ -239,53 +257,54 @@ void VertexFormat_pack(Gwn_VertFormat* format) show_pack(0, 0, end_padding); putchar('\n'); #endif - format->stride = offset + end_padding; format->packed = true; - } +} -// OpenGL ES packs in a different order as desktop GL but component conversion is the same. -// Of the code here, only struct Gwn_PackedNormal needs to change. +/* OpenGL ES packs in a different order as desktop GL but component conversion is the same. + * Of the code here, only struct Gwn_PackedNormal needs to change. */ #define SIGNED_INT_10_MAX 511 #define SIGNED_INT_10_MIN -512 static int clampi(int x, int min_allowed, int max_allowed) - { +{ #if TRUST_NO_ONE assert(min_allowed <= max_allowed); #endif - - if (x < min_allowed) + if (x < min_allowed) { return min_allowed; - else if (x > max_allowed) + } + else if (x > max_allowed) { return max_allowed; - else + } + else { return x; } +} static int quantize(float x) - { +{ int qx = x * 511.0f; return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX); - } +} static int convert_i16(short x) - { - // 16-bit signed --> 10-bit signed +{ + /* 16-bit signed --> 10-bit signed */ + /* TODO: round? */ return x >> 6; - // TODO: round? - } +} Gwn_PackedNormal GWN_normal_convert_i10_v3(const float data[3]) - { +{ Gwn_PackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) }; return n; - } +} Gwn_PackedNormal GWN_normal_convert_i10_s3(const short data[3]) - { +{ Gwn_PackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]) }; return n; - } +} |