Implement hardware index buffers; some renderer refactoring

Too lazy for detailed comments, read the code
This commit is contained in:
Andrei Alexeyev 2018-10-02 23:14:24 +03:00
parent 5548b6d65a
commit a6d0ab565f
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
24 changed files with 733 additions and 405 deletions

View file

@ -13,11 +13,13 @@
#include "list.h"
#include "stageobjects.h"
#include "renderer/api.h"
#include "resource/model.h"
static struct {
VertexArray *varr;
VertexBuffer *vbuf;
ShaderProgram *shader_generic;
Model quad_generic;
} lasers;
typedef struct LaserInstancedAttribs {
@ -54,10 +56,16 @@ void lasers_preload(void) {
lasers.varr = r_vertex_array_create();
r_vertex_array_set_debug_label(lasers.varr, "Lasers vertex array");
r_vertex_array_layout(lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
r_vertex_array_attach_buffer(lasers.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_buffer(lasers.varr, lasers.vbuf, 1);
r_vertex_array_attach_vertex_buffer(lasers.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_vertex_buffer(lasers.varr, lasers.vbuf, 1);
r_vertex_array_layout(lasers.varr, sizeof(fmt)/sizeof(VertexAttribFormat), fmt);
lasers.quad_generic.indexed = false;
lasers.quad_generic.num_vertices = 4;
lasers.quad_generic.offset = 0;
lasers.quad_generic.primitive = PRIM_TRIANGLE_STRIP;
lasers.quad_generic.vertex_array = lasers.varr;
lasers.shader_generic = r_shader_get("laser_generic");
}
@ -150,6 +158,7 @@ static void draw_laser_curve_specialized(Laser *l) {
return;
}
r_shader_ptr(l->shader);
r_color(&l->color);
r_uniform_sampler("tex", "part/lasercurve");
r_uniform_vec2_complex("origin", l->pos);
@ -158,7 +167,7 @@ static void draw_laser_curve_specialized(Laser *l) {
r_uniform_float("width", l->width);
r_uniform_float("width_exponent", l->width_exponent);
r_uniform_int("span", instances);
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, instances, 0);
r_draw_quad_instanced(instances);
}
static void draw_laser_curve_generic(Laser *l) {
@ -169,6 +178,7 @@ static void draw_laser_curve_generic(Laser *l) {
return;
}
r_shader_ptr(lasers.shader_generic);
r_color(&l->color);
r_uniform_sampler("tex", "part/lasercurve");
r_uniform_float("timeshift", timeshift);
@ -176,46 +186,30 @@ static void draw_laser_curve_generic(Laser *l) {
r_uniform_float("width_exponent", l->width_exponent);
r_uniform_int("span", instances);
LaserInstancedAttribs attrs[instances], *aptr = attrs;
SDL_RWops *stream = r_vertex_buffer_get_stream(lasers.vbuf);
r_vertex_buffer_invalidate(lasers.vbuf);
for(uint i = 0; i < instances; ++i, ++aptr) {
for(uint i = 0; i < instances; ++i) {
complex pos = l->prule(l, i * 0.5 + timeshift);
complex delta = pos - l->prule(l, i * 0.5 + timeshift - 0.1);
aptr->pos[0] = creal(pos);
aptr->pos[1] = cimag(pos);
aptr->delta[0] = creal(delta);
aptr->delta[1] = cimag(delta);
LaserInstancedAttribs attr;
attr.pos[0] = creal(pos);
attr.pos[1] = cimag(pos);
attr.delta[0] = creal(delta);
attr.delta[1] = cimag(delta);
SDL_RWwrite(stream, &attr, sizeof(attr), 1);
}
SDL_RWops *stream = r_vertex_buffer_get_stream(lasers.vbuf);
SDL_RWseek(stream, 0, RW_SEEK_SET);
SDL_RWwrite(stream, &attrs, sizeof(attrs), 1);
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, instances, 0);
r_draw_model_ptr(&lasers.quad_generic, instances, 0);
}
static void ent_draw_laser(EntityInterface *ent) {
Laser *laser = ENT_CAST(ent, Laser);
if(laser->shader) {
// Specialized lasers work with either vertex array,
// provided that the static models buffer is attached to it.
// We'll only ever draw the first quad, and only care about
// attributes 0 and 2 (vec3 position, vec2 uv)
VertexArray *va = r_vertex_array_current();
if(va != lasers.varr && va != r_vertex_array_static_models()) {
r_vertex_array(lasers.varr);
}
r_shader_ptr(laser->shader);
draw_laser_curve_specialized(laser);
} else {
r_vertex_array(lasers.varr);
r_shader_ptr(lasers.shader_generic);
draw_laser_curve_generic(laser);
}
}

View file

@ -203,11 +203,9 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
Uniform *u_length = r_shader_uniform(shader, "laser_length");
Texture *tex0 = get_tex("part/marisa_laser0");
Texture *tex1 = get_tex("part/marisa_laser1");
VertexArray *varr_saved = r_vertex_array_current();
FBPair *fbp_aux = stage_get_fbpair(FBPAIR_FG_AUX);
FBPair *fbp_fg = stage_get_fbpair(FBPAIR_FG);
r_vertex_array(r_vertex_array_static_models());
r_shader_ptr(shader);
r_uniform_vec4(u_clr0, 0.5, 0.5, 0.5, 0.0);
r_uniform_vec4(u_clr1, 0.8, 0.8, 0.8, 0.0);
@ -265,7 +263,6 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
}
r_shader("sprite_default");
r_vertex_array(varr_saved);
}
static int marisa_laser_fader(Enemy *e, int t) {

View file

@ -16,6 +16,8 @@
#include "common/state.h"
#include "util/glm.h"
#include "util/graphics.h"
#include "resource/texture.h"
#include "resource/sprite.h"
#define B _r_backend.funcs
@ -377,8 +379,12 @@ UniformType r_uniform_type(Uniform *uniform) {
return B.uniform_type(uniform);
}
void r_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint instances, uint base_instance) {
B.draw(prim, first, count, indices, instances, base_instance);
void r_draw(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance) {
B.draw(varr, prim, firstvert, count, instances, base_instance);
}
void r_draw_indexed(VertexArray* varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance) {
B.draw_indexed(varr, prim, firstidx, count, instances, base_instance);
}
Texture* r_texture_create(const TextureParams *params) {
@ -520,6 +526,38 @@ SDL_RWops* r_vertex_buffer_get_stream(VertexBuffer *vbuf) {
return B.vertex_buffer_get_stream(vbuf);
}
IndexBuffer* r_index_buffer_create(size_t max_elements) {
return B.index_buffer_create(max_elements);
}
size_t r_index_buffer_get_capacity(IndexBuffer *ibuf) {
return B.index_buffer_get_capacity(ibuf);
}
const char* r_index_buffer_get_debug_label(IndexBuffer *ibuf) {
return B.index_buffer_get_debug_label(ibuf);
}
void r_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label) {
B.index_buffer_set_debug_label(ibuf, label);
}
void r_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset) {
B.index_buffer_set_offset(ibuf, offset);
}
size_t r_index_buffer_get_offset(IndexBuffer *ibuf) {
return B.index_buffer_get_offset(ibuf);
}
void r_index_buffer_add_indices(IndexBuffer *ibuf, uint index_ofs, size_t num_indices, uint indices[num_indices]) {
B.index_buffer_add_indices(ibuf, index_ofs, num_indices, indices);
}
void r_index_buffer_destroy(IndexBuffer *ibuf) {
B.index_buffer_destroy(ibuf);
}
VertexArray* r_vertex_array_create(void) {
return B.vertex_array_create();
}
@ -536,27 +574,26 @@ void r_vertex_array_destroy(VertexArray *varr) {
B.vertex_array_destroy(varr);
}
void r_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) {
B.vertex_array_attach_buffer(varr, vbuf, attachment);
void r_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) {
B.vertex_array_attach_vertex_buffer(varr, vbuf, attachment);
}
VertexBuffer* r_vertex_array_get_attachment(VertexArray *varr, uint attachment) {
return B.vertex_array_get_attachment(varr, attachment);
VertexBuffer* r_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment) {
return B.vertex_array_get_vertex_attachment(varr, attachment);
}
void r_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf) {
B.vertex_array_attach_index_buffer(varr, ibuf);
}
IndexBuffer* r_vertex_array_get_index_attachment(VertexArray *varr) {
return B.vertex_array_get_index_attachment(varr);
}
void r_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) {
B.vertex_array_layout(varr, nattribs, attribs);
}
void r_vertex_array(VertexArray *varr) {
_r_state_touch_vertex_array();
B.vertex_array(varr);
}
VertexArray* r_vertex_array_current(void) {
return B.vertex_array_current();
}
void r_vsync(VsyncMode mode) {
_r_state_touch_vsync();
B.vsync(mode);

View file

@ -12,19 +12,18 @@
#include "util.h"
#include "util/pixmap.h"
#include "color.h"
#include "resource/resource.h"
#include "resource/shader_program.h"
#include "resource/texture.h"
#include "resource/model.h"
#include "resource/sprite.h"
#include "common/shader.h"
#include "resource/resource.h"
typedef struct Texture Texture;
typedef struct Framebuffer Framebuffer;
typedef struct VertexBuffer VertexBuffer;
typedef struct VertexArray VertexArray;
typedef struct IndexBuffer IndexBuffer;
typedef struct ShaderObject ShaderObject;
typedef struct ShaderProgram ShaderProgram;
typedef struct Sprite Sprite;
typedef struct Model Model;
enum {
R_DEBUG_LABEL_SIZE = 128,
@ -581,7 +580,8 @@ void _r_uniform_sampler_array(const char *uniform, uint offset, uint count, cons
) \
))(uniform, offset, count, values)
void r_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint instances, uint base_instance);
void r_draw(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance);
void r_draw_indexed(VertexArray *varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance);
Texture* r_texture_create(const TextureParams *params) attr_nonnull(1);
void r_texture_get_size(Texture *tex, uint mipmap, uint *width, uint *height) attr_nonnull(1);
@ -620,16 +620,26 @@ void r_vertex_buffer_destroy(VertexBuffer *vbuf) attr_nonnull(1);
void r_vertex_buffer_invalidate(VertexBuffer *vbuf) attr_nonnull(1);
SDL_RWops* r_vertex_buffer_get_stream(VertexBuffer *vbuf) attr_nonnull(1);
IndexBuffer* r_index_buffer_create(size_t max_elements);
size_t r_index_buffer_get_capacity(IndexBuffer *ibuf) attr_nonnull(1);
const char* r_index_buffer_get_debug_label(IndexBuffer *ibuf) attr_nonnull(1);
void r_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label) attr_nonnull(1);
void r_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset) attr_nonnull(1);
size_t r_index_buffer_get_offset(IndexBuffer *ibuf) attr_nonnull(1);
void r_index_buffer_add_indices(IndexBuffer *ibuf, uint index_ofs, size_t num_indices, uint indices[num_indices]) attr_nonnull(1, 4);
void r_index_buffer_destroy(IndexBuffer *ibuf) attr_nonnull(1);
VertexArray* r_vertex_array_create(void);
const char* r_vertex_array_get_debug_label(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_set_debug_label(VertexArray *varr, const char* label) attr_nonnull(1);
void r_vertex_array_destroy(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) attr_nonnull(1, 2);
VertexBuffer* r_vertex_array_get_attachment(VertexArray *varr, uint attachment) attr_nonnull(1);
void r_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) attr_nonnull(1, 2);
VertexBuffer* r_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment) attr_nonnull(1);
void r_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf) attr_nonnull(1);
IndexBuffer* r_vertex_array_get_index_attachment(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) attr_nonnull(1, 3);
void r_vertex_array(VertexArray *varr) attr_nonnull(1);
VertexArray* r_vertex_array_current(void);
void r_model_add_static(Model *out_mdl, Primitive prim, size_t num_vertices, GenericModelVertex vertices[num_vertices], uint indices[num_vertices]);
void r_vsync(VsyncMode mode);
VsyncMode r_vsync_current(void);
@ -664,7 +674,7 @@ void r_state_pop(void);
void r_draw_quad(void);
void r_draw_quad_instanced(uint instances);
void r_draw_model_ptr(Model *model) attr_nonnull(1);
void r_draw_model_ptr(Model *model, uint instances, uint base_instance) attr_nonnull(1);
void r_draw_sprite(const SpriteParams *params) attr_nonnull(1);
void r_flush_sprites(void);
@ -774,7 +784,12 @@ void r_clear(ClearBufferFlags flags, const Color *colorval, float depthval) {
static inline attr_must_inline attr_nonnull(1)
void r_draw_model(const char *model) {
r_draw_model_ptr(get_resource_data(RES_MODEL, model, RESF_UNSAFE));
r_draw_model_ptr(get_resource_data(RES_MODEL, model, RESF_UNSAFE), 0, 0);
}
static inline attr_must_inline attr_nonnull(1)
void r_draw_model_instanced(const char *model, uint instances, uint base_instance) {
r_draw_model_ptr(get_resource_data(RES_MODEL, model, RESF_UNSAFE), instances, base_instance);
}
static inline attr_must_inline

View file

@ -23,7 +23,8 @@ typedef struct RendererFuncs {
void (*capabilities)(r_capability_bits_t capbits);
r_capability_bits_t (*capabilities_current)(void);
void (*draw)(Primitive prim, uint first, uint count, uint32_t * indices, uint instances, uint base_instance);
void (*draw)(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance);
void (*draw_indexed)(VertexArray *varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance);
void (*color4)(float r, float g, float b, float a);
const Color* (*color_current)(void);
@ -90,16 +91,24 @@ typedef struct RendererFuncs {
void (*vertex_buffer_invalidate)(VertexBuffer *vbuf);
SDL_RWops* (*vertex_buffer_get_stream)(VertexBuffer *vbuf);
IndexBuffer* (*index_buffer_create)(size_t max_elements);
size_t (*index_buffer_get_capacity)(IndexBuffer *ibuf);
const char* (*index_buffer_get_debug_label)(IndexBuffer *ibuf);
void (*index_buffer_set_debug_label)(IndexBuffer *ibuf, const char *label);
void (*index_buffer_set_offset)(IndexBuffer *ibuf, size_t offset);
size_t (*index_buffer_get_offset)(IndexBuffer *ibuf);
void (*index_buffer_add_indices)(IndexBuffer *ibuf, uint index_ofs, size_t num_indices, uint indices[num_indices]);
void (*index_buffer_destroy)(IndexBuffer *ibuf);
VertexArray* (*vertex_array_create)(void);
const char* (*vertex_array_get_debug_label)(VertexArray *varr);
void (*vertex_array_set_debug_label)(VertexArray *varr, const char *label);
void (*vertex_array_destroy)(VertexArray *varr);
void (*vertex_array_layout)(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]);
void (*vertex_array_attach_buffer)(VertexArray *varr, VertexBuffer *vbuf, uint attachment);
VertexBuffer* (*vertex_array_get_attachment)(VertexArray *varr, uint attachment);
void (*vertex_array)(VertexArray *varr) attr_nonnull(1);
VertexArray* (*vertex_array_current)(void);
void (*vertex_array_attach_vertex_buffer)(VertexArray *varr, VertexBuffer *vbuf, uint attachment);
void (*vertex_array_attach_index_buffer)(VertexArray *varr, IndexBuffer *ibuf);
VertexBuffer* (*vertex_array_get_vertex_attachment)(VertexArray *varr, uint attachment);
IndexBuffer* (*vertex_array_get_index_attachment)(VertexArray *varr);
void (*vsync)(VsyncMode mode);
VsyncMode (*vsync_current)(void);

View file

@ -10,10 +10,13 @@
#include "models.h"
#include "../api.h"
#include "resource/model.h"
static struct {
VertexBuffer *vbuf;
IndexBuffer *ibuf;
VertexArray *varr;
Model quad;
} _r_models;
void _r_models_init(void) {
@ -32,18 +35,21 @@ void _r_models_init(void) {
{ { -0.5, 0.5, 0.0 }, { 0, 0, 1 }, { 0, 0 } },
};
_r_models.vbuf = r_vertex_buffer_create(8192 * sizeof(GenericModelVertex), NULL);
const size_t max_vertices = 8192;
_r_models.vbuf = r_vertex_buffer_create(max_vertices * sizeof(GenericModelVertex), NULL);
r_vertex_buffer_set_debug_label(_r_models.vbuf, "Static models vertex buffer");
_r_models.ibuf = r_index_buffer_create(max_vertices);
r_index_buffer_set_debug_label(_r_models.ibuf, "Static models index buffer");
_r_models.varr = r_vertex_array_create();
r_vertex_array_set_debug_label(_r_models.varr, "Static models vertex array");
r_vertex_array_layout(_r_models.varr, 3, fmt);
r_vertex_array_attach_buffer(_r_models.varr, _r_models.vbuf, 0);
r_vertex_array_attach_vertex_buffer(_r_models.varr, _r_models.vbuf, 0);
r_vertex_array_attach_index_buffer(_r_models.varr, _r_models.ibuf);
SDL_RWops *stream = r_vertex_buffer_get_stream(_r_models.vbuf);
SDL_RWwrite(stream, quad, sizeof(quad), 1);
r_vertex_array(_r_models.varr);
r_model_add_static(&_r_models.quad, PRIM_TRIANGLE_STRIP, 4, quad, NULL);
}
void _r_models_shutdown(void) {
@ -51,6 +57,26 @@ void _r_models_shutdown(void) {
r_vertex_buffer_destroy(_r_models.vbuf);
}
void r_model_add_static(Model *out_mdl, Primitive prim, size_t num_vertices, GenericModelVertex vertices[num_vertices], uint indices[num_vertices]) {
out_mdl->vertex_array = _r_models.varr;
out_mdl->num_vertices = num_vertices;
out_mdl->primitive = prim;
SDL_RWops *vert_stream = r_vertex_buffer_get_stream(_r_models.vbuf);
size_t vert_ofs = SDL_RWtell(vert_stream) / sizeof(GenericModelVertex);
if(indices != NULL) {
out_mdl->offset = r_index_buffer_get_offset(_r_models.ibuf);
r_index_buffer_add_indices(_r_models.ibuf, vert_ofs, num_vertices, indices);
out_mdl->indexed = true;
} else {
out_mdl->offset = vert_ofs;
out_mdl->indexed = false;
}
SDL_RWwrite(vert_stream, vertices, sizeof(GenericModelVertex), num_vertices);
}
VertexBuffer* r_vertex_buffer_static_models(void) {
return _r_models.vbuf;
}
@ -60,22 +86,19 @@ VertexArray* r_vertex_array_static_models(void) {
}
void r_draw_quad(void) {
VertexArray *varr_saved = r_vertex_array_current();
r_vertex_array(_r_models.varr);
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, 0, 0);
r_vertex_array(varr_saved);
r_draw_model_ptr(&_r_models.quad, 0, 0);
}
void r_draw_quad_instanced(uint instances) {
VertexArray *varr_saved = r_vertex_array_current();
r_vertex_array(_r_models.varr);
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, instances, 0);
r_vertex_array(varr_saved);
r_draw_model_ptr(&_r_models.quad, instances, 0);
}
void r_draw_model_ptr(Model *model) {
VertexArray *varr_saved = r_vertex_array_current();
r_vertex_array(_r_models.varr);
r_draw(PRIM_TRIANGLES, 0, model->icount, model->indices, 0, 0);
r_vertex_array(varr_saved);
void r_draw_model_ptr(Model *model, uint instances, uint base_instance) {
(model->indexed ? r_draw_indexed : r_draw)(
model->vertex_array,
model->primitive,
model->offset, model->num_vertices,
instances,
base_instance
);
}

View file

@ -11,6 +11,8 @@
#include "sprite_batch.h"
#include "../api.h"
#include "util/glm.h"
#include "resource/sprite.h"
#include "resource/model.h"
typedef struct SpriteAttribs {
mat4 transform;
@ -43,6 +45,8 @@ static struct SpriteBatchState {
uint depth_write_enabled : 1;
uint num_pending;
Model quad;
struct {
uint flushes;
uint sprites;
@ -101,8 +105,14 @@ void _r_sprite_batch_init(void) {
_r_sprite_batch.varr = r_vertex_array_create();
r_vertex_array_set_debug_label(_r_sprite_batch.varr, "Sprite batch vertex array");
r_vertex_array_layout(_r_sprite_batch.varr, sizeof(fmt)/sizeof(*fmt), fmt);
r_vertex_array_attach_buffer(_r_sprite_batch.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_buffer(_r_sprite_batch.varr, _r_sprite_batch.vbuf, 1);
r_vertex_array_attach_vertex_buffer(_r_sprite_batch.varr, r_vertex_buffer_static_models(), 0);
r_vertex_array_attach_vertex_buffer(_r_sprite_batch.varr, _r_sprite_batch.vbuf, 1);
_r_sprite_batch.quad.indexed = false;
_r_sprite_batch.quad.num_vertices = 4;
_r_sprite_batch.quad.offset = 0;
_r_sprite_batch.quad.primitive = PRIM_TRIANGLE_STRIP;
_r_sprite_batch.quad.vertex_array = _r_sprite_batch.varr;
}
void _r_sprite_batch_shutdown(void) {
@ -140,7 +150,6 @@ void r_flush_sprites(void) {
r_mat_push();
glm_mat4_copy(_r_sprite_batch.projection, *r_mat_current_ptr(MM_PROJECTION));
r_vertex_array(_r_sprite_batch.varr);
r_shader_ptr(_r_sprite_batch.shader);
r_uniform_sampler("tex", _r_sprite_batch.primary_texture);
r_uniform_sampler_array("tex_aux[0]", 0, R_NUM_SPRITE_AUX_TEXTURES, _r_sprite_batch.aux_textures);
@ -153,7 +162,7 @@ void r_flush_sprites(void) {
r_cull(_r_sprite_batch.cull_mode);
if(r_supports(RFEAT_DRAW_INSTANCED_BASE_INSTANCE)) {
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, pending, _r_sprite_batch.base_instance);
r_draw_model_ptr(&_r_sprite_batch.quad, pending, _r_sprite_batch.base_instance);
_r_sprite_batch.base_instance += pending;
SDL_RWops *stream = r_vertex_buffer_get_stream(_r_sprite_batch.vbuf);
@ -165,7 +174,7 @@ void r_flush_sprites(void) {
_r_sprite_batch.base_instance = 0;
}
} else {
r_draw(PRIM_TRIANGLE_STRIP, 0, 4, NULL, pending, 0);
r_draw_model_ptr(&_r_sprite_batch.quad, pending, 0);
r_vertex_buffer_invalidate(_r_sprite_batch.vbuf);
}

View file

@ -89,10 +89,6 @@ void r_state_pop(void) {
B.framebuffer(S.framebuffer);
}
RESTORE(RSTATE_VERTEXARRAY) {
B.vertex_array(S.varr);
}
RESTORE(RSTATE_VSYNC) {
B.vsync(S.vsync);
}
@ -155,12 +151,6 @@ void _r_state_touch_framebuffer(void) {
});
}
void _r_state_touch_vertex_array(void) {
TAINT(RSTATE_VERTEXARRAY, {
S.varr = B.vertex_array_current();
});
}
void _r_state_touch_vsync(void) {
TAINT(RSTATE_VSYNC, {
S.vsync = B.vsync_current();

View file

@ -21,7 +21,6 @@
RSTATE(SHADER) \
RSTATE(SHADER_UNIFORMS) \
RSTATE(RENDERTARGET) \
RSTATE(VERTEXARRAY) \
RSTATE(VSYNC) \
typedef enum RendererStateID {
@ -51,8 +50,6 @@ typedef struct RendererStateRollback {
ShaderProgram *shader;
// TODO uniforms
Framebuffer *framebuffer;
// TODO framebuffer viewports, if we actually ever need to modify them at render time
VertexArray *varr;
VsyncMode vsync;
} RendererStateRollback;
@ -65,7 +62,6 @@ void _r_state_touch_depth_func(void);
void _r_state_touch_shader(void);
void _r_state_touch_uniform(Uniform *uniform);
void _r_state_touch_framebuffer(void);
void _r_state_touch_vertex_array(void);
void _r_state_touch_vsync(void);
void _r_state_init(void);

View file

@ -0,0 +1,132 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
*/
#include "taisei.h"
#include "common_buffer.h"
#include "core.h"
#define STREAM_CBUF(rw) ((CommonBuffer*)rw)
static int64_t gl33_buffer_stream_seek(SDL_RWops *rw, int64_t offset, int whence) {
CommonBuffer *cbuf = STREAM_CBUF(rw);
switch(whence) {
case RW_SEEK_CUR: {
cbuf->offset += offset;
break;
}
case RW_SEEK_END: {
cbuf->offset = cbuf->size + offset;
break;
}
case RW_SEEK_SET: {
cbuf->offset = offset;
break;
}
}
assert(cbuf->offset < cbuf->size);
return cbuf->offset;
}
static int64_t gl33_buffer_stream_size(SDL_RWops *rw) {
return STREAM_CBUF(rw)->size;
}
static size_t gl33_buffer_stream_write(SDL_RWops *rw, const void *data, size_t size, size_t num) {
CommonBuffer *cbuf = STREAM_CBUF(rw);
size_t total_size = size * num;
assert(cbuf->offset + total_size <= cbuf->size);
if(total_size > 0) {
memcpy(cbuf->cache.buffer + cbuf->offset, data, total_size);
cbuf->cache.update_begin = min(cbuf->offset, cbuf->cache.update_begin);
cbuf->cache.update_end = max(cbuf->offset + total_size, cbuf->cache.update_end);
cbuf->offset += total_size;
}
return num;
}
static size_t gl33_buffer_stream_read(SDL_RWops *rw, void *data, size_t size, size_t num) {
SDL_SetError("Can't read from an OpenGL buffer stream");
return 0;
}
static int gl33_buffer_stream_close(SDL_RWops *rw) {
SDL_SetError("Can't close an OpenGL buffer stream");
return -1;
}
SDL_RWops* gl33_buffer_get_stream(CommonBuffer *cbuf) {
return &cbuf->stream;
}
CommonBuffer* gl33_buffer_create(uint bindidx, size_t capacity, GLenum usage_hint, void *data) {
CommonBuffer *cbuf = calloc(1, sizeof(CommonBuffer));
cbuf->size = capacity = topow2(capacity);
cbuf->cache.buffer = calloc(1, capacity);
cbuf->cache.update_begin = capacity;
cbuf->bindidx = bindidx;
glGenBuffers(1, &cbuf->gl_handle);
GL33_BUFFER_TEMP_BIND(cbuf, {
assert(glIsBuffer(cbuf->gl_handle));
glBufferData(gl33_bindidx_to_glenum(bindidx), capacity, data, usage_hint);
});
cbuf->stream.type = SDL_RWOPS_UNKNOWN;
cbuf->stream.close = gl33_buffer_stream_close;
cbuf->stream.read = gl33_buffer_stream_read;
cbuf->stream.write = gl33_buffer_stream_write;
cbuf->stream.seek = gl33_buffer_stream_seek;
cbuf->stream.size = gl33_buffer_stream_size;
return cbuf;
}
void gl33_buffer_destroy(CommonBuffer *cbuf) {
free(cbuf->cache.buffer);
gl33_buffer_deleted(cbuf);
glDeleteBuffers(1, &cbuf->gl_handle);
free(cbuf);
}
void gl33_buffer_invalidate(CommonBuffer *cbuf) {
GL33_BUFFER_TEMP_BIND(cbuf, {
glBufferData(gl33_bindidx_to_glenum(cbuf->bindidx), cbuf->size, NULL, GL_DYNAMIC_DRAW);
});
cbuf->offset = 0;
}
void gl33_buffer_flush(CommonBuffer *cbuf) {
if(cbuf->cache.update_begin >= cbuf->cache.update_end) {
return;
}
size_t update_size = cbuf->cache.update_end - cbuf->cache.update_begin;
assert(update_size > 0);
GL33_BUFFER_TEMP_BIND(cbuf, {
glBufferSubData(
gl33_bindidx_to_glenum(cbuf->bindidx),
cbuf->cache.update_begin,
update_size,
cbuf->cache.buffer + cbuf->cache.update_begin
);
});
cbuf->cache.update_begin = cbuf->size;
cbuf->cache.update_end = 0;
}

View file

@ -0,0 +1,55 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
*/
#pragma once
#include "taisei.h"
#include "opengl.h"
#include "../api.h"
typedef struct CommonBuffer {
union {
SDL_RWops stream;
struct {
char padding[offsetof(SDL_RWops, hidden)];
struct {
char *buffer;
size_t update_begin;
size_t update_end;
} cache;
size_t offset;
size_t size;
GLuint gl_handle;
uint bindidx;
char debug_label[R_DEBUG_LABEL_SIZE];
};
};
} CommonBuffer;
static_assert(
offsetof(CommonBuffer, stream) == 0,
"stream should be the first member in CommonBuffer for simplicity"
);
CommonBuffer* gl33_buffer_create(uint bindidx, size_t capacity, GLenum usage_hint, void *data);
void gl33_buffer_destroy(CommonBuffer *cbuf);
void gl33_buffer_invalidate(CommonBuffer *cbuf);
SDL_RWops* gl33_buffer_get_stream(CommonBuffer *cbuf);
void gl33_buffer_flush(CommonBuffer *cbuf);
#define GL33_BUFFER_TEMP_BIND(cbuf, code) do { \
CommonBuffer *_tempbind_cbuf = (cbuf); \
BufferBindingIndex _tempbind_bindidx = _tempbind_cbuf->bindidx; \
GLuint _tempbind_buf_saved = gl33_buffer_current(_tempbind_bindidx); \
gl33_bind_buffer(_tempbind_bindidx, _tempbind_cbuf->gl_handle); \
gl33_sync_buffer(_tempbind_bindidx); \
{ code } \
gl33_bind_buffer(_tempbind_bindidx, _tempbind_buf_saved); \
} while(0)

View file

@ -17,7 +17,9 @@
#include "shader_object.h"
#include "shader_program.h"
#include "framebuffer.h"
#include "common_buffer.h"
#include "vertex_buffer.h"
#include "index_buffer.h"
#include "vertex_array.h"
#include "../glcommon/debug.h"
#include "../glcommon/vtable.h"
@ -53,15 +55,10 @@ static struct {
Framebuffer *pending;
} framebuffer;
struct {
VertexArray *active;
VertexArray *pending;
} vertex_array;
struct {
GLuint active;
GLuint pending;
} vbo;
} buffer_objects[GL33_NUM_BUFFER_BINDINGS];
struct {
GLuint active;
@ -109,7 +106,6 @@ static struct {
Color color;
Color clear_color;
float clear_depth;
GLuint pbo;
r_feature_bits_t features;
SDL_GLContext *gl_context;
@ -333,7 +329,7 @@ static void gl33_sync_state(void) {
gl33_sync_texunits(true);
gl33_sync_framebuffer();
gl33_sync_viewport();
gl33_sync_vertex_array();
gl33_sync_vao();
gl33_sync_blend_mode();
if(R.capabilities.active & r_capability_bit(RCAP_CULL_FACE)) {
@ -513,23 +509,6 @@ void gl33_sync_texunits(bool prepare_rendering) {
}
}
void gl33_sync_vertex_array(void) {
R.vertex_array.active = R.vertex_array.pending;
if(R.vertex_array.active != NULL) {
gl33_vertex_array_flush_buffers(R.vertex_array.active);
}
gl33_sync_vao();
}
void gl33_sync_vbo(void) {
if(R.vbo.active != R.vbo.pending) {
R.vbo.active = R.vbo.pending;
glBindBuffer(GL_ARRAY_BUFFER, R.vbo.active);
}
}
void gl33_sync_vao(void) {
if(R.vao.active != R.vao.pending) {
R.vao.active = R.vao.pending;
@ -537,6 +516,25 @@ void gl33_sync_vao(void) {
}
}
GLenum gl33_bindidx_to_glenum(BufferBindingIndex bindidx) {
static GLenum map[] = {
[GL33_BUFFER_BINDING_ARRAY] = GL_ARRAY_BUFFER,
[GL33_BUFFER_BINDING_COPY_WRITE] = GL_COPY_WRITE_BUFFER,
[GL33_BUFFER_BINDING_PIXEL_UNPACK] = GL_PIXEL_UNPACK_BUFFER,
};
static_assert(sizeof(map) == sizeof(GLenum) * GL33_NUM_BUFFER_BINDINGS, "Fix the lookup table");
assert((uint)bindidx < GL33_NUM_BUFFER_BINDINGS);
return map[bindidx];
}
void gl33_sync_buffer(BufferBindingIndex bindidx) {
if(R.buffer_objects[bindidx].active != R.buffer_objects[bindidx].pending) {
R.buffer_objects[bindidx].active = R.buffer_objects[bindidx].pending;
glBindBuffer(gl33_bindidx_to_glenum(bindidx), R.buffer_objects[bindidx].active);
}
}
void gl33_sync_cull_face_mode(void) {
if(R.cull_face.mode.pending != R.cull_face.mode.active) {
GLenum glcull = r_cull_to_gl_cull(R.cull_face.mode.pending);
@ -656,28 +654,16 @@ uint gl33_bind_texture(Texture *texture, bool for_rendering) {
return TU_INDEX(texture->binding_unit);
}
void gl33_bind_vbo(GLuint vbo) {
R.vbo.pending = vbo;
void gl33_bind_buffer(BufferBindingIndex bindidx, GLuint gl_handle) {
R.buffer_objects[bindidx].pending = gl_handle;
}
void gl33_bind_vao(GLuint vao) {
R.vao.pending = vao;
}
void gl33_bind_pbo(GLuint pbo) {
if(!glext.pixel_buffer_object) {
return;
}
if(pbo != R.pbo) {
// r_flush_sprites();
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
R.pbo = pbo;
}
}
GLuint gl33_vbo_current(void) {
return R.vbo.pending;
GLuint gl33_buffer_current(BufferBindingIndex bindidx) {
return R.buffer_objects[bindidx].pending;
}
GLuint gl33_vao_current(void) {
@ -711,8 +697,12 @@ void gl33_texture_deleted(Texture *tex) {
}
}
if(R.pbo == tex->pbo) {
R.pbo = 0;
if(R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].pending == tex->pbo) {
R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].pending = 0;
}
if(R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].active == tex->pbo) {
R.buffer_objects[GL33_BUFFER_BINDING_PIXEL_UNPACK].active = 0;
}
}
@ -741,26 +731,27 @@ void gl33_shader_deleted(ShaderProgram *prog) {
}
}
void gl33_vertex_buffer_deleted(VertexBuffer *vbuf) {
if(R.vbo.active == vbuf->gl_handle) {
R.vbo.active = 0;
void gl33_buffer_deleted(CommonBuffer *cbuf) {
if(R.buffer_objects[cbuf->bindidx].active == cbuf->gl_handle) {
R.buffer_objects[cbuf->bindidx].active = 0;
}
if(R.vbo.pending == vbuf->gl_handle) {
R.vbo.pending = 0;
if(R.buffer_objects[cbuf->bindidx].pending == cbuf->gl_handle) {
R.buffer_objects[cbuf->bindidx].pending = 0;
}
}
void gl33_vertex_buffer_deleted(VertexBuffer *vbuf) {
if(R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].active == vbuf->cbuf.gl_handle) {
R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].active = 0;
}
if(R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].pending == vbuf->cbuf.gl_handle) {
R.buffer_objects[GL33_BUFFER_BINDING_ARRAY].pending = 0;
}
}
void gl33_vertex_array_deleted(VertexArray *varr) {
if(R.vertex_array.active == varr) {
R.vertex_array.active = NULL;
}
if(R.vertex_array.pending == varr) {
R.vertex_array.pending = NULL;
r_vertex_array(r_vertex_array_static_models());
}
if(R.vao.active == varr->gl_handle) {
R.vao.active = 0;
}
@ -862,53 +853,69 @@ static const Color* gl33_color_current(void) {
return &R.color;
}
static void gl33_vertex_array(VertexArray *varr) {
R.vertex_array.pending = varr;
gl33_bind_vao(varr->gl_handle);
}
static VertexArray* gl33_vertex_array_current(void) {
return R.vertex_array.pending;
}
static void gl33_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint instances, uint base_instance) {
static void gl33_draw(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance) {
assert(count > 0);
assert((uint)prim < sizeof(prim_to_gl_prim)/sizeof(GLenum));
r_flush_sprites();
GLuint gl_prim = prim_to_gl_prim[prim];
gl33_sync_state();
gl33_stats_pre_draw();
if(indices == NULL) {
if(instances) {
if(base_instance) {
glDrawArraysInstancedBaseInstance(gl_prim, first, count, instances, base_instance);
} else {
glDrawArraysInstanced(gl_prim, first, count, instances);
}
} else {
glDrawArrays(gl_prim, first, count);
}
} else {
if(instances) {
if(base_instance) {
glDrawElementsInstancedBaseInstance(gl_prim, count, GL_UNSIGNED_INT, indices, instances, base_instance);
} else {
glDrawElementsInstanced(gl_prim, count, GL_UNSIGNED_INT, indices, instances);
}
} else {
glDrawElements(gl_prim, count, GL_UNSIGNED_INT, indices);
}
}
gl33_stats_post_draw();
gl33_stats_pre_draw();
r_flush_sprites();
GLuint prev_vao = gl33_vao_current();
gl33_bind_vao(varr->gl_handle);
gl33_sync_state();
gl33_vertex_array_flush_buffers(varr);
if(instances) {
if(base_instance) {
glDrawArraysInstancedBaseInstance(gl_prim, firstvert, count, instances, base_instance);
} else {
glDrawArraysInstanced(gl_prim, firstvert, count, instances);
}
} else {
glDrawArrays(gl_prim, firstvert, count);
}
if(R.framebuffer.active) {
gl33_framebuffer_taint(R.framebuffer.active);
}
gl33_bind_vao(prev_vao);
gl33_stats_post_draw();
}
static void gl33_draw_indexed(VertexArray *varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance) {
assert(count > 0);
assert((uint)prim < sizeof(prim_to_gl_prim)/sizeof(GLenum));
assert(varr->index_attachment != NULL);
GLuint gl_prim = prim_to_gl_prim[prim];
gl33_stats_post_draw();
gl33_stats_pre_draw();
r_flush_sprites();
GLuint prev_vao = gl33_vao_current();
gl33_bind_vao(varr->gl_handle);
gl33_sync_state();
gl33_vertex_array_flush_buffers(varr);
uintptr_t iofs = firstidx * sizeof(gl33_ibo_index_t);
if(instances) {
if(base_instance) {
glDrawElementsInstancedBaseInstance(gl_prim, count, GL33_IBO_GL_DATATYPE, (void*)iofs, instances, base_instance);
} else {
glDrawElementsInstanced(gl_prim, count, GL33_IBO_GL_DATATYPE, (void*)iofs, instances);
}
} else {
glDrawElements(gl_prim, count, GL33_IBO_GL_DATATYPE, (void*)iofs);
}
if(R.framebuffer.active) {
gl33_framebuffer_taint(R.framebuffer.active);
}
gl33_bind_vao(prev_vao);
gl33_stats_post_draw();
}
static void gl33_framebuffer(Framebuffer *fb) {
@ -1004,6 +1011,7 @@ RendererBackend _r_backend_gl33 = {
.capabilities = gl33_capabilities,
.capabilities_current = gl33_capabilities_current,
.draw = gl33_draw,
.draw_indexed = gl33_draw_indexed,
.color4 = gl33_color4,
.color_current = gl33_color_current,
.blend = gl33_blend,
@ -1056,15 +1064,23 @@ RendererBackend _r_backend_gl33 = {
.vertex_buffer_destroy = gl33_vertex_buffer_destroy,
.vertex_buffer_invalidate = gl33_vertex_buffer_invalidate,
.vertex_buffer_get_stream = gl33_vertex_buffer_get_stream,
.index_buffer_create = gl33_index_buffer_create,
.index_buffer_get_capacity = gl33_index_buffer_get_capacity,
.index_buffer_get_debug_label = gl33_index_buffer_get_debug_label,
.index_buffer_set_debug_label = gl33_index_buffer_set_debug_label,
.index_buffer_set_offset = gl33_index_buffer_set_offset,
.index_buffer_get_offset = gl33_index_buffer_get_offset,
.index_buffer_add_indices = gl33_index_buffer_add_indices,
.index_buffer_destroy = gl33_index_buffer_destroy,
.vertex_array_destroy = gl33_vertex_array_destroy,
.vertex_array_create = gl33_vertex_array_create,
.vertex_array_set_debug_label = gl33_vertex_array_set_debug_label,
.vertex_array_get_debug_label = gl33_vertex_array_get_debug_label,
.vertex_array_layout = gl33_vertex_array_layout,
.vertex_array_attach_buffer = gl33_vertex_array_attach_buffer,
.vertex_array_get_attachment = gl33_vertex_array_get_attachment,
.vertex_array = gl33_vertex_array,
.vertex_array_current = gl33_vertex_array_current,
.vertex_array_attach_vertex_buffer = gl33_vertex_array_attach_vertex_buffer,
.vertex_array_get_vertex_attachment = gl33_vertex_array_get_vertex_attachment,
.vertex_array_attach_index_buffer = gl33_vertex_array_attach_index_buffer,
.vertex_array_get_index_attachment = gl33_vertex_array_get_index_attachment,
.vsync = gl33_vsync,
.vsync_current = gl33_vsync_current,
.swap = gl33_swap,

View file

@ -13,15 +13,30 @@
#include "opengl.h"
#include "resource/texture.h"
#include "../common/backend.h"
#include "common_buffer.h"
typedef struct TextureUnit TextureUnit;
typedef enum BufferBindingIndex {
GL33_BUFFER_BINDING_ARRAY,
GL33_BUFFER_BINDING_COPY_WRITE,
GL33_BUFFER_BINDING_PIXEL_UNPACK,
GL33_NUM_BUFFER_BINDINGS
} BufferBindingIndex;
// Internal helper functions
uint gl33_bind_texture(Texture *texture, bool for_rendering);
void gl33_bind_pbo(GLuint pbo);
void gl33_bind_vao(GLuint vao);
void gl33_bind_vbo(GLuint vbo);
void gl33_sync_vao(void);
GLuint gl33_vao_current(void);
void gl33_bind_buffer(BufferBindingIndex bindidx, GLuint gl_handle);
void gl33_sync_buffer(BufferBindingIndex bindidx);
GLuint gl33_buffer_current(BufferBindingIndex bindidx);
GLenum gl33_bindidx_to_glenum(BufferBindingIndex bindidx);
void gl33_set_clear_color(const Color *color);
void gl33_set_clear_depth(float depth);
@ -30,17 +45,12 @@ void gl33_sync_shader(void);
void gl33_sync_texunit(TextureUnit *unit, bool prepare_rendering, bool ensure_active) attr_nonnull(1);
void gl33_sync_texunits(bool prepare_rendering);
void gl33_sync_framebuffer(void);
void gl33_sync_vertex_array(void);
void gl33_sync_blend_mode(void);
void gl33_sync_cull_face_mode(void);
void gl33_sync_depth_test_func(void);
void gl33_sync_capabilities(void);
void gl33_sync_vao(void);
void gl33_sync_vbo(void);
GLuint gl33_vao_current(void);
GLuint gl33_vbo_current(void);
void gl33_buffer_deleted(CommonBuffer *cbuf);
void gl33_vertex_buffer_deleted(VertexBuffer *vbuf);
void gl33_vertex_array_deleted(VertexArray *varr);
void gl33_texture_deleted(Texture *tex);

View file

@ -0,0 +1,68 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
*/
#include "taisei.h"
#include "index_buffer.h"
#include "core.h"
#include "../glcommon/debug.h"
IndexBuffer* gl33_index_buffer_create(size_t max_elements) {
IndexBuffer *ibuf = (IndexBuffer*)gl33_buffer_create(
GL33_BUFFER_BINDING_COPY_WRITE,
max_elements * sizeof(gl33_ibo_index_t),
GL_STATIC_DRAW,
NULL
);
snprintf(ibuf->cbuf.debug_label, sizeof(ibuf->cbuf.debug_label), "IBO #%i", ibuf->cbuf.gl_handle);
log_debug("Created IBO %u for %zu elements", ibuf->cbuf.gl_handle, max_elements);
return ibuf;
}
size_t gl33_index_buffer_get_capacity(IndexBuffer *ibuf) {
return ibuf->cbuf.size / sizeof(gl33_ibo_index_t);
}
const char* gl33_index_buffer_get_debug_label(IndexBuffer *ibuf) {
return ibuf->cbuf.debug_label;
}
void gl33_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label) {
glcommon_set_debug_label(ibuf->cbuf.debug_label, "IBO", GL_BUFFER, ibuf->cbuf.gl_handle, label);
}
void gl33_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset) {
ibuf->cbuf.offset = offset * sizeof(gl33_ibo_index_t);
}
size_t gl33_index_buffer_get_offset(IndexBuffer *ibuf) {
return ibuf->cbuf.offset / sizeof(gl33_ibo_index_t);
}
void gl33_index_buffer_add_indices(IndexBuffer *ibuf, uint index_ofs, size_t num_elements, uint indices[num_elements]) {
SDL_RWops *stream = gl33_buffer_get_stream(&ibuf->cbuf);
gl33_ibo_index_t data[num_elements];
for(size_t i = 0; i < num_elements; ++i) {
uintmax_t idx = indices[i] + index_ofs;
assert(idx <= GL33_IBO_MAX_INDEX);
data[i] = idx;
}
SDL_RWwrite(stream, &data, sizeof(gl33_ibo_index_t), num_elements);
}
void gl33_index_buffer_destroy(IndexBuffer *ibuf) {
log_debug("Deleted IBO %u", ibuf->cbuf.gl_handle);
gl33_buffer_destroy(&ibuf->cbuf);
}
void gl33_index_buffer_flush(IndexBuffer *ibuf) {
gl33_buffer_flush(&ibuf->cbuf);
}

View file

@ -0,0 +1,30 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
*/
#pragma once
#include "taisei.h"
#include "common_buffer.h"
typedef struct IndexBuffer {
CommonBuffer cbuf;
} IndexBuffer;
typedef GLushort gl33_ibo_index_t;
#define GL33_IBO_MAX_INDEX UINT16_MAX
#define GL33_IBO_GL_DATATYPE GL_UNSIGNED_SHORT
IndexBuffer* gl33_index_buffer_create(size_t max_elements);
size_t gl33_index_buffer_get_capacity(IndexBuffer *ibuf);
const char* gl33_index_buffer_get_debug_label(IndexBuffer *ibuf);
void gl33_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label);
void gl33_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset);
size_t gl33_index_buffer_get_offset(IndexBuffer *ibuf);
void gl33_index_buffer_add_indices(IndexBuffer *ibuf, uint index_ofs, size_t num_indices, uint indices[num_indices]);
void gl33_index_buffer_destroy(IndexBuffer *ibuf);
void gl33_index_buffer_flush(IndexBuffer *ibuf);

View file

@ -1,7 +1,9 @@
r_gl33_src = files(
'common_buffer.c',
'core.c',
'framebuffer.c',
'index_buffer.c',
'shader_object.c',
'shader_program.c',
'texture.c',

View file

@ -119,11 +119,15 @@ static void gl33_texture_set(Texture *tex, uint mipmap, const Pixmap *image) {
GLTextureFormatTuple *fmt = prepare_pixmap(tex, image, &pix);
void *image_data = pix.data.untyped;
GLuint prev_pbo;
gl33_bind_texture(tex, false);
gl33_sync_texunit(tex->binding_unit, false, true);
gl33_bind_pbo(tex->pbo);
if(tex->pbo) {
prev_pbo = gl33_buffer_current(GL33_BUFFER_BINDING_PIXEL_UNPACK);
gl33_bind_buffer(GL33_BUFFER_BINDING_PIXEL_UNPACK, tex->pbo);
gl33_sync_buffer(GL33_BUFFER_BINDING_PIXEL_UNPACK);
glBufferData(GL_PIXEL_UNPACK_BUFFER, pixmap_data_size(&pix), image_data, GL_STREAM_DRAW);
image_data = NULL;
}
@ -145,7 +149,10 @@ static void gl33_texture_set(Texture *tex, uint mipmap, const Pixmap *image) {
free(pix.data.untyped);
gl33_bind_pbo(0);
if(tex->pbo) {
gl33_bind_buffer(GL33_BUFFER_BINDING_PIXEL_UNPACK, prev_pbo);
}
tex->mipmaps_outdated = true;
}

View file

@ -10,6 +10,7 @@
#include "vertex_array.h"
#include "vertex_buffer.h"
#include "index_buffer.h"
#include "core.h"
#include "../glcommon/debug.h"
@ -44,29 +45,40 @@ void gl33_vertex_array_destroy(VertexArray *varr) {
free(varr);
}
static void gl33_vertex_array_update_layout(VertexArray *varr, uint attachment, uint old_num_attribs) {
static void gl33_vertex_array_update_layout(VertexArray *varr) {
GLuint vao_saved = gl33_vao_current();
GLuint vbo_saved = gl33_vbo_current();
GLuint vbo_saved = gl33_buffer_current(GL33_BUFFER_BINDING_ARRAY);
gl33_bind_vao(varr->gl_handle);
gl33_sync_vao();
if(varr->layout_dirty_bits & VAO_INDEX_BIT) {
gl33_sync_vao();
if(varr->index_attachment) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, varr->index_attachment->cbuf.gl_handle);
} else {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
for(uint i = 0; i < varr->num_attributes; ++i) {
VertexAttribFormat *a = varr->attribute_layout + i;
assert((uint)a->spec.type < sizeof(va_type_to_gl_type)/sizeof(GLenum));
assert(a->attachment < VAO_MAX_BUFFERS);
if(attachment != UINT_MAX && attachment != a->attachment) {
if(!(varr->layout_dirty_bits & (1u << i))) {
continue;
}
VertexBuffer *vbuf = r_vertex_array_get_attachment(varr, a->attachment);
VertexBuffer *vbuf = varr->attachments[a->attachment];
if(vbuf == NULL) {
continue;
}
gl33_bind_vbo(vbuf->gl_handle);
gl33_sync_vbo();
gl33_sync_vao();
gl33_bind_buffer(GL33_BUFFER_BINDING_ARRAY, vbuf->cbuf.gl_handle);
gl33_sync_buffer(GL33_BUFFER_BINDING_ARRAY);
glEnableVertexAttribArray(i);
@ -105,15 +117,21 @@ static void gl33_vertex_array_update_layout(VertexArray *varr, uint attachment,
}
}
for(uint i = varr->num_attributes; i < old_num_attribs; ++i) {
for(uint i = varr->num_attributes; i < varr->prev_num_attributes; ++i) {
gl33_sync_vao();
glDisableVertexAttribArray(i);
}
gl33_bind_vbo(vbo_saved);
gl33_bind_buffer(GL33_BUFFER_BINDING_ARRAY, vbo_saved);
gl33_bind_vao(vao_saved);
varr->prev_num_attributes = varr->num_attributes;
varr->layout_dirty_bits = 0;
}
void gl33_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) {
void gl33_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) {
assert(attachment < VAO_MAX_BUFFERS);
// TODO: more efficient way of handling this?
if(attachment >= varr->num_attachments) {
varr->attachments = realloc(varr->attachments, (attachment + 1) * sizeof(VertexBuffer*));
@ -121,10 +139,15 @@ void gl33_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint
}
varr->attachments[attachment] = vbuf;
gl33_vertex_array_update_layout(varr, attachment, varr->num_attributes);
varr->layout_dirty_bits |= (1u << attachment);
}
VertexBuffer* gl33_vertex_array_get_attachment(VertexArray *varr, uint attachment) {
void gl33_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf) {
varr->index_attachment = ibuf;
varr->layout_dirty_bits |= VAO_INDEX_BIT;
}
VertexBuffer* gl33_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment) {
if(varr->num_attachments <= attachment) {
return NULL;
}
@ -132,16 +155,18 @@ VertexBuffer* gl33_vertex_array_get_attachment(VertexArray *varr, uint attachmen
return varr->attachments[attachment];
}
void gl33_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) {
uint old_nattribs = varr->num_attributes;
IndexBuffer* gl33_vertex_array_get_index_attachment(VertexArray *varr) {
return varr->index_attachment;
}
void gl33_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) {
if(varr->num_attributes != nattribs) {
varr->attribute_layout = realloc(varr->attribute_layout, sizeof(VertexAttribFormat) * nattribs);
varr->num_attributes = nattribs;
}
memcpy(varr->attribute_layout, attribs, sizeof(VertexAttribFormat) * nattribs);
gl33_vertex_array_update_layout(varr, UINT32_MAX, old_nattribs);
varr->layout_dirty_bits |= (1u << nattribs) - 1;
}
const char* gl33_vertex_array_get_debug_label(VertexArray *varr) {
@ -153,9 +178,17 @@ void gl33_vertex_array_set_debug_label(VertexArray *varr, const char *label) {
}
void gl33_vertex_array_flush_buffers(VertexArray *varr) {
if(varr->layout_dirty_bits) {
gl33_vertex_array_update_layout(varr);
}
for(uint i = 0; i < varr->num_attachments; ++i) {
if(varr->attachments[i] != NULL) {
gl33_vertex_buffer_flush(varr->attachments[i]);
}
}
if(varr->index_attachment != NULL) {
gl33_index_buffer_flush(varr->index_attachment);
}
}

View file

@ -12,12 +12,18 @@
#include "../api.h"
#include "opengl.h"
#define VAO_MAX_BUFFERS 31
#define VAO_INDEX_BIT (1u << VAO_MAX_BUFFERS)
struct VertexArray {
VertexBuffer **attachments;
VertexAttribFormat *attribute_layout;
IndexBuffer *index_attachment;
GLuint gl_handle;
uint num_attachments;
uint num_attributes;
uint prev_num_attributes;
uint layout_dirty_bits;
char debug_label[R_DEBUG_LABEL_SIZE];
};
@ -25,7 +31,9 @@ VertexArray* gl33_vertex_array_create(void);
const char* gl33_vertex_array_get_debug_label(VertexArray *varr);
void gl33_vertex_array_set_debug_label(VertexArray *varr, const char *label);
void gl33_vertex_array_destroy(VertexArray *varr);
void gl33_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment);
VertexBuffer* gl33_vertex_array_get_attachment(VertexArray *varr, uint attachment);
void gl33_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment);
void gl33_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf);
VertexBuffer* gl33_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment);
IndexBuffer* gl33_vertex_array_get_index_attachment(VertexArray *varr);
void gl33_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]);
void gl33_vertex_array_flush_buffers(VertexArray *varr);

View file

@ -8,140 +8,44 @@
#include "taisei.h"
#include <string.h>
#include <stdalign.h>
#include "../api.h"
#include "vertex_buffer.h"
#include "core.h"
#include "../glcommon/debug.h"
#define STREAM_VBUF(rw) ((VertexBuffer*)rw)
static int64_t gl33_vertex_buffer_stream_seek(SDL_RWops *rw, int64_t offset, int whence) {
VertexBuffer *vbuf = STREAM_VBUF(rw);
switch(whence) {
case RW_SEEK_CUR: {
vbuf->offset += offset;
break;
}
case RW_SEEK_END: {
vbuf->offset = vbuf->size + offset;
break;
}
case RW_SEEK_SET: {
vbuf->offset = offset;
break;
}
}
assert(vbuf->offset < vbuf->size);
return vbuf->offset;
}
static int64_t gl33_vertex_buffer_stream_size(SDL_RWops *rw) {
VertexBuffer *vbuf = STREAM_VBUF(rw);
return vbuf->size;
}
static size_t gl33_vertex_buffer_stream_write(SDL_RWops *rw, const void *data, size_t size, size_t num) {
VertexBuffer *vbuf = STREAM_VBUF(rw);
size_t total_size = size * num;
assert(vbuf->offset + total_size <= vbuf->size);
if(total_size > 0) {
memcpy(vbuf->cache.buffer + vbuf->offset, data, total_size);
vbuf->cache.update_begin = min(vbuf->offset, vbuf->cache.update_begin);
vbuf->cache.update_end = max(vbuf->offset + total_size, vbuf->cache.update_end);
vbuf->offset += total_size;
}
return num;
}
static size_t gl33_vertex_buffer_stream_read(SDL_RWops *rw, void *data, size_t size, size_t num) {
SDL_SetError("Stream is write-only");
return 0;
}
static int gl33_vertex_buffer_stream_close(SDL_RWops *rw) {
SDL_SetError("Can't close a vertex buffer stream");
return -1;
}
SDL_RWops* gl33_vertex_buffer_get_stream(VertexBuffer *vbuf) {
return &vbuf->stream;
}
VertexBuffer* gl33_vertex_buffer_create(size_t capacity, void *data) {
VertexBuffer *vbuf = calloc(1, sizeof(VertexBuffer));
vbuf->size = capacity = topow2(capacity);
vbuf->cache.buffer = calloc(1, capacity);
vbuf->cache.update_begin = capacity;
VertexBuffer *vbuf = (VertexBuffer*)gl33_buffer_create(
GL33_BUFFER_BINDING_ARRAY,
capacity,
GL_STATIC_DRAW,
data
);
glGenBuffers(1, &vbuf->gl_handle);
GLuint vbo_saved = gl33_vbo_current();
gl33_bind_vbo(vbuf->gl_handle);
gl33_sync_vbo();
assert(glIsBuffer(vbuf->gl_handle));
glBufferData(GL_ARRAY_BUFFER, capacity, data, GL_STATIC_DRAW);
gl33_bind_vbo(vbo_saved);
vbuf->stream.type = SDL_RWOPS_UNKNOWN;
vbuf->stream.close = gl33_vertex_buffer_stream_close;
vbuf->stream.read = gl33_vertex_buffer_stream_read;
vbuf->stream.write = gl33_vertex_buffer_stream_write;
vbuf->stream.seek = gl33_vertex_buffer_stream_seek;
vbuf->stream.size = gl33_vertex_buffer_stream_size;
snprintf(vbuf->debug_label, sizeof(vbuf->debug_label), "VBO #%i", vbuf->gl_handle);
log_debug("Created VBO %u with %zukb of storage", vbuf->gl_handle, vbuf->size / 1024);
snprintf(vbuf->cbuf.debug_label, sizeof(vbuf->cbuf.debug_label), "VBO #%i", vbuf->cbuf.gl_handle);
log_debug("Created VBO %u with %zukb of storage", vbuf->cbuf.gl_handle, vbuf->cbuf.size / 1024);
return vbuf;
}
void gl33_vertex_buffer_destroy(VertexBuffer *vbuf) {
free(vbuf->cache.buffer);
gl33_vertex_buffer_deleted(vbuf);
glDeleteBuffers(1, &vbuf->gl_handle);
log_debug("Deleted VBO %u with %zukb of storage", vbuf->gl_handle, vbuf->size / 1024);
free(vbuf);
log_debug("Deleted VBO %u with %zukb of storage", vbuf->cbuf.gl_handle, vbuf->cbuf.size / 1024);
gl33_buffer_destroy(&vbuf->cbuf);
}
void gl33_vertex_buffer_invalidate(VertexBuffer *vbuf) {
GLuint vbo_saved = gl33_vbo_current();
gl33_bind_vbo(vbuf->gl_handle);
gl33_sync_vbo();
glBufferData(GL_ARRAY_BUFFER, vbuf->size, NULL, GL_DYNAMIC_DRAW);
gl33_bind_vbo(vbo_saved);
vbuf->offset = 0;
gl33_buffer_invalidate(&vbuf->cbuf);
}
const char* gl33_vertex_buffer_get_debug_label(VertexBuffer *vbuf) {
return vbuf->debug_label;
return vbuf->cbuf.debug_label;
}
void gl33_vertex_buffer_set_debug_label(VertexBuffer *vbuf, const char *label) {
glcommon_set_debug_label(vbuf->debug_label, "VBO", GL_BUFFER, vbuf->gl_handle, label);
glcommon_set_debug_label(vbuf->cbuf.debug_label, "VBO", GL_BUFFER, vbuf->cbuf.gl_handle, label);
}
void gl33_vertex_buffer_flush(VertexBuffer *vbuf) {
if(vbuf->cache.update_begin >= vbuf->cache.update_end) {
return;
}
size_t update_size = vbuf->cache.update_end - vbuf->cache.update_begin;
assert(update_size > 0);
GLuint vbo_saved = gl33_vbo_current();
gl33_bind_vbo(vbuf->gl_handle);
gl33_sync_vbo();
glBufferSubData(GL_ARRAY_BUFFER, vbuf->cache.update_begin, update_size, vbuf->cache.buffer + vbuf->cache.update_begin);
gl33_bind_vbo(vbo_saved);
vbuf->cache.update_begin = vbuf->size;
vbuf->cache.update_end = 0;
gl33_buffer_flush(&vbuf->cbuf);
}
SDL_RWops* gl33_vertex_buffer_get_stream(VertexBuffer *vbuf) {
return gl33_buffer_get_stream(&vbuf->cbuf);
}

View file

@ -9,34 +9,12 @@
#pragma once
#include "taisei.h"
#include "opengl.h"
#include <SDL.h>
#include "common_buffer.h"
typedef struct VertexBuffer {
union {
SDL_RWops stream;
struct {
char padding[offsetof(SDL_RWops, hidden)];
struct {
char *buffer;
size_t update_begin;
size_t update_end;
} cache;
size_t offset;
size_t size;
GLuint gl_handle;
char debug_label[R_DEBUG_LABEL_SIZE];
};
};
CommonBuffer cbuf;
} VertexBuffer;
static_assert(
offsetof(VertexBuffer, stream) == 0,
"stream should be the first member in VertexBuffer for simplicity"
);
VertexBuffer* gl33_vertex_buffer_create(size_t capacity, void *data);
const char* gl33_vertex_buffer_get_debug_label(VertexBuffer *vbuf);
void gl33_vertex_buffer_set_debug_label(VertexBuffer *vbuf, const char *label);

View file

@ -65,7 +65,7 @@ void null_uniform(Uniform *uniform, uint offset, uint count, const void *data) {
UniformType null_uniform_type(Uniform *uniform) { return UNIFORM_FLOAT; }
void null_draw(Primitive prim, uint first, uint count, uint32_t *indices, uint instances, uint base_instance) { }
void null_draw(VertexArray *varr, Primitive prim, uint first, uint count, uint instances, uint base_instance) { }
Texture* null_texture_create(const TextureParams *params) {
return (void*)&placeholder;
@ -136,15 +136,24 @@ const char* null_vertex_buffer_get_debug_label(VertexBuffer *vbuf) { return "nul
void null_vertex_buffer_destroy(VertexBuffer *vbuf) { }
void null_vertex_buffer_invalidate(VertexBuffer *vbuf) { }
IndexBuffer* null_index_buffer_create(size_t max_elements) { return (void*)&placeholder; }
size_t null_index_buffer_get_capacity(IndexBuffer *ibuf) { return UINT32_MAX; }
const char* null_index_buffer_get_debug_label(IndexBuffer *ibuf) { return "null index buffer"; }
void null_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label) { }
void null_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset) { }
size_t null_index_buffer_get_offset(IndexBuffer *ibuf) { return 0; }
void null_index_buffer_add_indices(IndexBuffer *ibuf, uint index_ofs, size_t num_elements, uint indices[num_elements]) { }
void null_index_buffer_destroy(IndexBuffer *ibuf) { }
VertexArray* null_vertex_array_create(void) { return (void*)&placeholder; }
void null_vertex_array_set_debug_label(VertexArray *varr, const char *label) { }
const char* null_vertex_array_get_debug_label(VertexArray *varr) { return "null vertex array"; }
void null_vertex_array_destroy(VertexArray *varr) { }
void null_vertex_array_attach_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) { }
VertexBuffer* null_vertex_array_get_attachment(VertexArray *varr, uint attachment) { return (void*)&placeholder; }
void null_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) { }
void null_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *vbuf) { }
VertexBuffer* null_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment) { return (void*)&placeholder; }
IndexBuffer* null_vertex_array_get_index_attachment(VertexArray *varr) { return (void*)&placeholder; }
void null_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) { }
void null_vertex_array(VertexArray *varr) { }
VertexArray* null_vertex_array_current(void) { return (void*)&placeholder; }
void null_clear(ClearBufferFlags flags) { }
void null_clear_color4(float r, float g, float b, float a) { }
@ -168,6 +177,7 @@ RendererBackend _r_backend_null = {
.capabilities = null_capabilities,
.capabilities_current = null_capabilities_current,
.draw = null_draw,
.draw_indexed = null_draw,
.color4 = null_color4,
.color_current = null_color_current,
.blend = null_blend,
@ -220,15 +230,23 @@ RendererBackend _r_backend_null = {
.vertex_buffer_destroy = null_vertex_buffer_destroy,
.vertex_buffer_invalidate = null_vertex_buffer_invalidate,
.vertex_buffer_get_stream = null_vertex_buffer_get_stream,
.index_buffer_create = null_index_buffer_create,
.index_buffer_get_capacity = null_index_buffer_get_capacity,
.index_buffer_get_debug_label = null_index_buffer_get_debug_label,
.index_buffer_set_debug_label = null_index_buffer_set_debug_label,
.index_buffer_set_offset = null_index_buffer_set_offset,
.index_buffer_get_offset = null_index_buffer_get_offset,
.index_buffer_add_indices = null_index_buffer_add_indices,
.index_buffer_destroy = null_index_buffer_destroy,
.vertex_array_create = null_vertex_array_create,
.vertex_array_get_debug_label = null_vertex_array_get_debug_label,
.vertex_array_set_debug_label = null_vertex_array_set_debug_label,
.vertex_array_destroy = null_vertex_array_destroy,
.vertex_array_layout = null_vertex_array_layout,
.vertex_array_attach_buffer = null_vertex_array_attach_buffer,
.vertex_array_get_attachment = null_vertex_array_get_attachment,
.vertex_array = null_vertex_array,
.vertex_array_current = null_vertex_array_current,
.vertex_array_attach_vertex_buffer = null_vertex_array_attach_vertex_buffer,
.vertex_array_get_vertex_attachment = null_vertex_array_get_vertex_attachment,
.vertex_array_attach_index_buffer = null_vertex_array_attach_index_buffer,
.vertex_array_get_index_attachment = null_vertex_array_get_index_attachment,
.vsync = null_vsync,
.vsync_current = null_vsync_current,
.swap = null_swap,

View file

@ -17,6 +17,9 @@
#include "resource.h"
#include "renderer/api.h"
// TODO: Rewrite all of this mess, maybe even consider a different format
// IQM for instance: http://sauerbraten.org/iqm/
ResourceHandler model_res_handler = {
.type = RES_MODEL,
.typename = "model",
@ -43,21 +46,19 @@ bool check_model_path(const char *path) {
}
typedef struct ModelLoadData {
ObjFileData *obj;
GenericModelVertex *verts;
Model *model;
uint *indices;
uint icount;
} ModelLoadData;
void* load_model_begin(const char *path, uint flags) {
Model *m = malloc(sizeof(Model));
ObjFileData *data = malloc(sizeof(ObjFileData));
GenericModelVertex *verts;
parse_obj(path, data);
m->fverts = data->fverts;
m->indices = calloc(data->icount, sizeof(uint));
m->icount = data->icount;
uint *indices = calloc(data->icount, sizeof(uint));
uint icount = data->icount;
verts = calloc(data->icount, sizeof(GenericModelVertex));
@ -94,21 +95,23 @@ void* load_model_begin(const char *path, uint flags) {
memcpy(verts[i].normal, data->normals[ni], sizeof(vec3_noalign));
}
m->indices[i] = i;
indices[i] = i;
}
free_obj(data);
free(data);
#undef BADREF
ModelLoadData *ldata = malloc(sizeof(ModelLoadData));
ldata->obj = data;
ldata->verts = verts;
ldata->model = m;
ldata->indices = indices;
ldata->icount = icount;
return ldata;
fail:
free(m->indices);
free(m);
free(indices);
free(verts);
free_obj(data);
free(data);
@ -116,33 +119,23 @@ fail:
}
void* load_model_end(void *opaque, const char *path, uint flags) {
VertexBuffer *vbuf= r_vertex_buffer_static_models();
ModelLoadData *ldata = opaque;
if(!ldata) {
return NULL;
}
SDL_RWops *stream = r_vertex_buffer_get_stream(vbuf);
size_t ioffset = SDL_RWtell(stream);
for(int i = 0; i < ldata->obj->icount; ++i) {
ldata->model->indices[i] += ioffset / sizeof(GenericModelVertex);
}
SDL_RWwrite(stream, ldata->verts, sizeof(GenericModelVertex), ldata->obj->icount);
Model *model = calloc(1, sizeof(Model));
r_model_add_static(model, PRIM_TRIANGLES, ldata->icount, ldata->verts, ldata->indices);
free(ldata->verts);
free_obj(ldata->obj);
free(ldata->obj);
Model *m = ldata->model;
free(ldata->indices);
free(ldata);
return m;
return model;
}
void unload_model(void *model) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space
free(((Model*)model)->indices);
free(model);
}

View file

@ -12,6 +12,8 @@
#include "util.h"
#include "resource.h"
#include "renderer/api.h"
typedef struct ObjFileData {
vec3_noalign *xs;
int xcount;
@ -28,11 +30,13 @@ typedef struct ObjFileData {
int fverts;
} ObjFileData;
typedef struct Model {
uint *indices;
int icount;
int fverts;
} Model;
struct Model {
VertexArray *vertex_array;
size_t num_vertices;
size_t offset;
Primitive primitive;
bool indexed;
};
char* model_path(const char *name);
bool check_model_path(const char *path);