GWN: Port to GPU module: codestyle & licence
This commit is contained in:
parent
a28fd8fee2
commit
6329629bb9
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 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/.
|
||||
/** \file blender/gpu/gwn_batch.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Gawain geometry batch
|
||||
* Contains VAOs + VBOs + Shader representing a drawable entity.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 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/.
|
||||
/** \file blender/gpu/gwn_common.h
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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__ */
|
||||
|
|
|
@ -1,17 +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 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/.
|
||||
/** \file blender/gpu/gwn_context.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* This interface allow Gawain to manage VAOs for mutiple context and threads.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// 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__ */
|
||||
|
|
|
@ -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 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/.
|
||||
/** \file blender/gpu/gwn_element.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Gawain element list (AKA index buffer)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -1,88 +1,101 @@
|
|||
/*
|
||||
* ***** 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 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/.
|
||||
/** \file blender/gpu/gwn_immediate.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Gawain immediate mode work-alike
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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. */
|
||||
|
||||
// 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 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 immAttrib2i(unsigned attrib_id, int x, int y);
|
||||
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 immAttrib1u(unsigned attrib_id, unsigned x);
|
||||
/* 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 immAttrib2s(unsigned attrib_id, short x, short y);
|
||||
/* 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 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 immAttrib2i(uint attrib_id, int x, int y);
|
||||
|
||||
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 immAttrib1u(uint attrib_id, uint x);
|
||||
|
||||
void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]);
|
||||
void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]);
|
||||
void immAttrib2s(uint attrib_id, short x, short y);
|
||||
|
||||
// explicitly skip an attribute
|
||||
// this advanced option kills automatic value copying for this attrib_id
|
||||
void immSkipAttrib(unsigned attrib_id);
|
||||
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]);
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
void immAttrib3ubv(uint attrib_id, const unsigned char data[4]);
|
||||
void immAttrib4ubv(uint attrib_id, const unsigned char data[4]);
|
||||
|
||||
void immVertex2i(unsigned attrib_id, int x, int y);
|
||||
/* Explicitly skip an attribute. */
|
||||
/* This advanced option kills automatic value copying for this attrib_id. */
|
||||
void immSkipAttrib(uint attrib_id);
|
||||
|
||||
void immVertex2s(unsigned attrib_id, short x, short 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 immVertex2fv(unsigned attrib_id, const float data[2]);
|
||||
void immVertex3fv(unsigned attrib_id, const float data[3]);
|
||||
void immVertex2i(uint attrib_id, int x, int y);
|
||||
|
||||
void immVertex2iv(unsigned attrib_id, const int data[2]);
|
||||
void immVertex2s(uint attrib_id, short x, short y);
|
||||
|
||||
void immVertex2fv(uint attrib_id, const float data[2]);
|
||||
void immVertex3fv(uint attrib_id, const float data[3]);
|
||||
|
||||
// provide uniform values that don't change for the entire draw call
|
||||
void immVertex2iv(uint attrib_id, const int data[2]);
|
||||
|
||||
/* 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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -1,55 +1,76 @@
|
|||
/*
|
||||
* ***** 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 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/.
|
||||
/** \file blender/gpu/gwn_shader_interface.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Gawain shader interface (C --> GLSL)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -1,42 +1,63 @@
|
|||
/*
|
||||
* ***** 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 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/.
|
||||
/** \file blender/gpu/gwn_vertex_buffer.h
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Gawain vertex buffer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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);
|
||||
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?
|
||||
/* 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 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); */
|
||||
|
||||
/* 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*);
|
||||
|
||||
/* Metrics */
|
||||
uint GWN_vertbuf_get_memory_usage(void);
|
||||
|
||||
// Metrics
|
||||
|
||||
unsigned GWN_vertbuf_get_memory_usage(void);
|
||||
|
||||
|
||||
// Macros
|
||||
|
||||
/* Macros */
|
||||
#define GWN_VERTBUF_DISCARD_SAFE(verts) do { \
|
||||
if (verts != NULL) { \
|
||||
GWN_vertbuf_discard(verts); \
|
||||
verts = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* __GWN_VERTEX_BUFFER_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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,34 @@
|
|||
/*
|
||||
* ***** 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 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/.
|
||||
/** \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
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// just draw some vertices and let shader place them where we want.
|
||||
/* 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. */
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 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/.
|
||||
/** \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)
|
||||
{
|
||||
GWN_indexbuf_init_ex(builder, prim_type, prim_len * verts_per_prim, vertex_len, false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 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/.
|
||||
/** \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))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
return NULL; // not found
|
||||
if (match(name_buffer + input->name_offset, name)) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
GWN_INLINE void buckets_free(Gwn_ShaderInput* buckets[GWN_NUM_SHADERINTERFACE_BUCKETS])
|
||||
{
|
||||
for (unsigned bucket_index = 0; bucket_index < GWN_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index)
|
||||
{
|
||||
{
|
||||
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));
|
||||
|
||||
input->location = glGetUniformLocation(shaderface->program, 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)
|
||||
{
|
||||
Gwn_ShaderInput* input = malloc(sizeof(Gwn_ShaderInput));
|
||||
|
||||
input->location = glGetUniformLocation(shaderface->program, name);
|
||||
|
||||
unsigned name_len = strlen(name);
|
||||
shaderface->name_buffer = realloc(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); // include NULL terminator
|
||||
char* name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
|
||||
strcpy(name_buffer, name);
|
||||
|
||||
set_input_name(shaderface, input, name, name_len);
|
||||
setup_builtin_uniform(input, name);
|
||||
|
||||
shader_input_to_bucket(input, shaderface->uniform_buckets);
|
||||
if (input->builtin_type != GWN_UNIFORM_NONE &&
|
||||
input->builtin_type != GWN_UNIFORM_CUSTOM)
|
||||
{
|
||||
shaderface->builtin_uniforms[input->builtin_type] = input;
|
||||
}
|
||||
#if DEBUG_SHADER_INTERFACE
|
||||
printf("Gwn_ShaderInterface %p, program %d, uniform[] '%s' at location %d\n", shaderface, shaderface->program, name, input->location);
|
||||
#endif
|
||||
return input;
|
||||
shaderface->builtin_uniforms[input->builtin_type] = input;
|
||||
}
|
||||
#if DEBUG_SHADER_INTERFACE
|
||||
printf("Gwn_ShaderInterface %p, program %d, uniform[] '%s' at location %d\n", shaderface,
|
||||
shaderface->program,
|
||||
name,
|
||||
input->location);
|
||||
#endif
|
||||
return input;
|
||||
}
|
||||
|
||||
Gwn_ShaderInterface* GWN_shaderinterface_create(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(shaderface);
|
||||
}
|
||||
}
|
||||
free(shaderface->batches);
|
||||
/* 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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,38 @@
|
|||
/*
|
||||
* ***** 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 *****
|
||||
*/
|
||||
|
||||
// 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"
|
||||
/** \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)
|
||||
clear_orphans(ctx);
|
||||
active_ctx = ctx;
|
||||
}
|
||||
#endif
|
||||
if (ctx) {
|
||||
clear_orphans(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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, Clément Foucault
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
// 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/.
|
||||
/** \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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, Clément Foucault
|
||||
*
|
||||
* ***** 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/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
|
||||
|
||||
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_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 */
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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). */
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue