From 4f118dcd975bab1b19cde31264e2917a958293db Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 28 Apr 2020 12:44:28 +0200 Subject: [PATCH] some work on gl3 --- src/d3d/d3d.cpp | 2 +- src/geoplg.cpp | 2 + src/gl/gl3pipe.cpp | 218 +++++++++++++++++++++++++++---------------- src/gl/gl3raster.cpp | 28 ++++-- src/gl/gl3shader.cpp | 86 ++--------------- src/gl/gl3skin.cpp | 211 ++++++++++++++++++++++------------------- src/gl/rwgl3.h | 6 +- 7 files changed, 289 insertions(+), 264 deletions(-) diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index a4c1e49..a052266 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -371,7 +371,7 @@ lockTexture(void *texture, int32 level, int32 lockMode) #ifdef RW_D3D9 IDirect3DTexture9 *tex = (IDirect3DTexture9*)texture; D3DLOCKED_RECT lr; - tex->LockRect(level, &lr, 0, 0); + tex->LockRect(level, &lr, 0, D3DLOCK_NOSYSLOCK); return (uint8*)lr.pBits; #else RasterLevels *levels = (RasterLevels*)texture; diff --git a/src/geoplg.cpp b/src/geoplg.cpp index db0c72c..1a976c3 100644 --- a/src/geoplg.cpp +++ b/src/geoplg.cpp @@ -249,6 +249,8 @@ destroyNativeData(void *object, int32 offset, int32 size) return d3d8::destroyNativeData(object, offset, size); if(geometry->instData->platform == PLATFORM_D3D9) return d3d9::destroyNativeData(object, offset, size); + if(geometry->instData->platform == PLATFORM_GL3) + return gl3::destroyNativeData(object, offset, size); return object; } diff --git a/src/gl/gl3pipe.cpp b/src/gl/gl3pipe.cpp index 793d794..226eb91 100644 --- a/src/gl/gl3pipe.cpp +++ b/src/gl/gl3pipe.cpp @@ -22,14 +22,32 @@ namespace gl3 { #ifdef RW_OPENGL -static void -instance(rw::ObjPipeline *rwpipe, Atomic *atomic) +void +freeInstanceData(Geometry *geometry) { - ObjPipeline *pipe = (ObjPipeline*)rwpipe; - Geometry *geo = atomic->geometry; - // TODO: allow for REINSTANCE - if(geo->instData) + if(geometry->instData == nil || + geometry->instData->platform != PLATFORM_GL3) return; + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + geometry->instData = nil; + glDeleteBuffers(1, &header->ibo); + glDeleteBuffers(1, &header->vbo); + rwFree(header->indexBuffer); + rwFree(header->vertexBuffer); + rwFree(header->attribDesc); + rwFree(header); +} + +void* +destroyNativeData(void *object, int32, int32) +{ + freeInstanceData((Geometry*)object); + return object; +} + +static InstanceDataHeader* +instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo) +{ InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); MeshHeader *meshh = geo->meshHeader; geo->instData = header; @@ -74,7 +92,36 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) header->indexBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - pipe->instanceCB(geo, header); + return header; +} + +static void +instance(rw::ObjPipeline *rwpipe, Atomic *atomic) +{ + ObjPipeline *pipe = (ObjPipeline*)rwpipe; + Geometry *geo = atomic->geometry; + // don't try to (re)instance native data + if(geo->flags & Geometry::NATIVE) + return; + + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + if(geo->instData){ + // Already have instanced data, so check if we have to reinstance + assert(header->platform == PLATFORM_GL3); + if(header->serialNumber != geo->meshHeader->serialNum){ + // Mesh changed, so reinstance everything + freeInstanceData(geo); + } + } + + // no instance or complete reinstance + if(geo->instData == nil){ + geo->instData = instanceMesh(rwpipe, geo); + pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0); + }else if(geo->lockedSinceInst) + pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1); + + geo->lockedSinceInst = 0; } static void @@ -88,9 +135,7 @@ render(rw::ObjPipeline *rwpipe, Atomic *atomic) { ObjPipeline *pipe = (ObjPipeline*)rwpipe; Geometry *geo = atomic->geometry; - // TODO: allow for REINSTANCE - if(geo->instData == nil) - pipe->instance(atomic); + pipe->instance(atomic); assert(geo->instData != nil); assert(geo->instData->platform == PLATFORM_GL3); if(pipe->renderCB) @@ -109,84 +154,100 @@ ObjPipeline::ObjPipeline(uint32 platform) } void -defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) +defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) { - AttribDesc attribs[12], *a; - uint32 stride; + AttribDesc *attribs, *a; - // - // Create attribute descriptions - // - a = attribs; - stride = 0; - - // Positions - a->index = ATTRIB_POS; - a->size = 3; - a->type = GL_FLOAT; - a->normalized = GL_FALSE; - a->offset = stride; - stride += 12; - a++; - - // Normals - // TODO: compress + bool isPrelit = !!(geo->flags & Geometry::PRELIT); bool hasNormals = !!(geo->flags & Geometry::NORMALS); - if(hasNormals){ - a->index = ATTRIB_NORMAL; + + if(!reinstance){ + AttribDesc tmpAttribs[12]; + uint32 stride; + + // + // Create attribute descriptions + // + a = tmpAttribs; + stride = 0; + + // Positions + a->index = ATTRIB_POS; a->size = 3; a->type = GL_FLOAT; a->normalized = GL_FALSE; a->offset = stride; stride += 12; a++; + + // Normals + // TODO: compress + if(hasNormals){ + a->index = ATTRIB_NORMAL; + a->size = 3; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 12; + a++; + } + + // Prelighting + if(isPrelit){ + a->index = ATTRIB_COLOR; + a->size = 4; + a->type = GL_UNSIGNED_BYTE; + a->normalized = GL_TRUE; + a->offset = stride; + stride += 4; + a++; + } + + // Texture coordinates + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + a->index = ATTRIB_TEXCOORDS0+n; + a->size = 2; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 8; + a++; + } + + header->numAttribs = a - tmpAttribs; + for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++) + a->stride = stride; + header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); + memcpy(header->attribDesc, tmpAttribs, + header->numAttribs*sizeof(AttribDesc)); + + // + // Allocate vertex buffer + // + header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); + assert(header->vbo == 0); + glGenBuffers(1, &header->vbo); } - // Prelighting - bool isPrelit = !!(geo->flags & Geometry::PRELIT); - if(isPrelit){ - a->index = ATTRIB_COLOR; - a->size = 4; - a->type = GL_UNSIGNED_BYTE; - a->normalized = GL_TRUE; - a->offset = stride; - stride += 4; - a++; - } - - // Texture coordinates - for(int32 n = 0; n < geo->numTexCoordSets; n++){ - a->index = ATTRIB_TEXCOORDS0+n; - a->size = 2; - a->type = GL_FLOAT; - a->normalized = GL_FALSE; - a->offset = stride; - stride += 8; - a++; - } - - header->numAttribs = a - attribs; - for(a = attribs; a != &attribs[header->numAttribs]; a++) - a->stride = stride; - header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); - memcpy(header->attribDesc, attribs, - header->numAttribs*sizeof(AttribDesc)); + attribs = header->attribDesc; // - // Allocate and fill vertex buffer + // Fill vertex buffer // - uint8 *verts = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); - header->vertexBuffer = verts; + + uint8 *verts = header->vertexBuffer; // Positions - for(a = attribs; a->index != ATTRIB_POS; a++) - ; - instV3d(VERT_FLOAT3, verts + a->offset, - geo->morphTargets[0].vertices, - header->totalNumVertex, a->stride); + if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){ + for(a = attribs; a->index != ATTRIB_POS; a++) + ; + instV3d(VERT_FLOAT3, verts + a->offset, + geo->morphTargets[0].vertices, + header->totalNumVertex, a->stride); + } // Normals - if(hasNormals){ + if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){ for(a = attribs; a->index != ATTRIB_NORMAL; a++) ; instV3d(VERT_FLOAT3, verts + a->offset, @@ -195,7 +256,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) } // Prelighting - if(isPrelit){ + if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){ for(a = attribs; a->index != ATTRIB_COLOR; a++) ; int n = header->numMeshes; @@ -212,16 +273,17 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) // Texture coordinates for(int32 n = 0; n < geo->numTexCoordSets; n++){ - for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++) - ; - instTexCoords(VERT_FLOAT2, verts + a->offset, - geo->texCoords[n], - header->totalNumVertex, a->stride); + if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<index != ATTRIB_TEXCOORDS0+n; a++) + ; + instTexCoords(VERT_FLOAT2, verts + a->offset, + geo->texCoords[n], + header->totalNumVertex, a->stride); + } } - glGenBuffers(1, &header->vbo); glBindBuffer(GL_ARRAY_BUFFER, header->vbo); - glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*stride, + glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride, header->vertexBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 911b48f..54d2e12 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -213,18 +213,28 @@ rasterLock(Raster *raster, int32 level, int32 lockMode) assert(raster->privateFlags == 0); - px = (uint8*)rwMalloc(raster->stride*raster->height, 0); // TODO: hint - assert(raster->pixels == nil); - raster->pixels = px; + switch(raster->type & 0xF00){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + px = (uint8*)rwMalloc(raster->stride*raster->height, MEMDUR_EVENT | ID_DRIVER); + assert(raster->pixels == nil); + raster->pixels = px; - if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){ - uint32 prev = bindTexture(natras->texid); - glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px); - bindTexture(prev); + if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){ + uint32 prev = bindTexture(natras->texid); + glGetTexImage(GL_TEXTURE_2D, level, natras->format, natras->type, px); + bindTexture(prev); + } + + raster->privateFlags = lockMode; + break; + + default: + assert(0 && "cannot lock this type of raster yet"); + return nil; } - raster->privateFlags = lockMode; - return px; #else return nil; diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index a3bd08f..84d5e89 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -68,28 +68,6 @@ findBlock(const char *name) Shader *currentShader; -// TODO: maybe make this public somewhere? -static char* -loadfile(const char *path) -{ - FILE *f; - char *buf; - long len; - - if(f = fopen(path, "rb"), f == nil){ - fprintf(stderr, "Couldn't open file %s\n", path); - exit(1); - } - fseek(f, 0, SEEK_END); - len = ftell(f); - buf = (char*)rwMalloc(len+1, MEMDUR_EVENT); - rewind(f); - fread(buf, 1, len, f); - buf[len] = '\0'; - fclose(f); - return buf; -} - static int compileshader(GLenum type, const char **src, GLuint *shader) { @@ -156,12 +134,17 @@ Shader::create(const char **vsrc, const char **fsrc) return nil; fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs); - if(fail) + if(fail){ + glDeleteShader(vs); return nil; + } fail = linkprogram(vs, fs, &program); - if(fail) + if(fail){ + glDeleteShader(fs); + glDeleteShader(vs); return nil; + } glDeleteProgram(vs); glDeleteProgram(fs); @@ -195,61 +178,6 @@ Shader::create(const char **vsrc, const char **fsrc) return sh; } -#if 0 -Shader* -Shader::fromStrings(const char *vsrc, const char *fsrc) -{ - GLuint vs, fs, program; - int i; - int fail; - - fail = compileshader(GL_VERTEX_SHADER, vsrc, &vs); - if(fail) - return nil; - - fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs); - if(fail) - return nil; - - fail = linkprogram(vs, fs, &program); - if(fail) - return nil; - glDeleteProgram(vs); - glDeleteProgram(fs); - - Shader *sh = rwNewT(Shader, 1, MEMDUR_EVENT | ID_DRIVER); // or global? - - // set uniform block binding - for(i = 0; i < uniformRegistry.numBlocks; i++){ - int idx = glGetUniformBlockIndex(program, - uniformRegistry.blockNames[i]); - if(idx >= 0) - glUniformBlockBinding(program, idx, i); - } - - // query uniform locations - sh->program = program; - sh->uniformLocations = rwNewT(GLint, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER); - for(i = 0; i < uniformRegistry.numUniforms; i++) - sh->uniformLocations[i] = glGetUniformLocation(program, - uniformRegistry.uniformNames[i]); - - return sh; -} - -Shader* -Shader::fromFiles(const char *vspath, const char *fspath) -{ - char *vsrc, *fsrc; - vsrc = loadfile(vspath); - fsrc = loadfile(fspath); - Shader *s = fromStrings(vsrc, fsrc); - rwFree(vsrc); - rwFree(fsrc); - return s; -} -#endif - void Shader::use(void) { diff --git a/src/gl/gl3skin.cpp b/src/gl/gl3skin.cpp index 2169781..182bfb3 100644 --- a/src/gl/gl3skin.cpp +++ b/src/gl/gl3skin.cpp @@ -67,103 +67,119 @@ enum }; void -skinInstanceCB(Geometry *geo, InstanceDataHeader *header) +skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) { - AttribDesc attribs[14], *a; - uint32 stride; + AttribDesc *attribs, *a; - // - // Create attribute descriptions - // - a = attribs; - stride = 0; - - // Positions - a->index = ATTRIB_POS; - a->size = 3; - a->type = GL_FLOAT; - a->normalized = GL_FALSE; - a->offset = stride; - stride += 12; - a++; - - // Normals - // TODO: compress + bool isPrelit = !!(geo->flags & Geometry::PRELIT); bool hasNormals = !!(geo->flags & Geometry::NORMALS); - if(hasNormals){ - a->index = ATTRIB_NORMAL; + + if(!reinstance){ + AttribDesc tmpAttribs[14]; + uint32 stride; + + // + // Create attribute descriptions + // + a = tmpAttribs; + stride = 0; + + // Positions + a->index = ATTRIB_POS; a->size = 3; a->type = GL_FLOAT; a->normalized = GL_FALSE; a->offset = stride; stride += 12; a++; - } - // Prelighting - bool isPrelit = !!(geo->flags & Geometry::PRELIT); - if(isPrelit){ - a->index = ATTRIB_COLOR; + // Normals + // TODO: compress + if(hasNormals){ + a->index = ATTRIB_NORMAL; + a->size = 3; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 12; + a++; + } + + // Prelighting + if(isPrelit){ + a->index = ATTRIB_COLOR; + a->size = 4; + a->type = GL_UNSIGNED_BYTE; + a->normalized = GL_TRUE; + a->offset = stride; + stride += 4; + a++; + } + + // Texture coordinates + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + a->index = ATTRIB_TEXCOORDS0+n; + a->size = 2; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 8; + a++; + } + + // Weights + a->index = ATTRIB_WEIGHTS; a->size = 4; - a->type = GL_UNSIGNED_BYTE; - a->normalized = GL_TRUE; - a->offset = stride; - stride += 4; - a++; - } - - // Texture coordinates - for(int32 n = 0; n < geo->numTexCoordSets; n++){ - a->index = ATTRIB_TEXCOORDS0+n; - a->size = 2; a->type = GL_FLOAT; a->normalized = GL_FALSE; a->offset = stride; - stride += 8; + stride += 16; a++; + + // Indices + a->index = ATTRIB_INDICES; + a->size = 4; + a->type = GL_UNSIGNED_BYTE; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 4; + a++; + + header->numAttribs = a - tmpAttribs; + for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++) + a->stride = stride; + header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); + memcpy(header->attribDesc, tmpAttribs, + header->numAttribs*sizeof(AttribDesc)); + + // + // Allocate vertex buffer + // + header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); + assert(header->vbo == 0); + glGenBuffers(1, &header->vbo); } - // Weights - a->index = ATTRIB_WEIGHTS; - a->size = 4; - a->type = GL_FLOAT; - a->normalized = GL_FALSE; - a->offset = stride; - stride += 16; - a++; - - // Indices - a->index = ATTRIB_INDICES; - a->size = 4; - a->type = GL_UNSIGNED_BYTE; - a->normalized = GL_FALSE; - a->offset = stride; - stride += 4; - a++; - - header->numAttribs = a - attribs; - for(a = attribs; a != &attribs[header->numAttribs]; a++) - a->stride = stride; - header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); - memcpy(header->attribDesc, attribs, - header->numAttribs*sizeof(AttribDesc)); - - // - // Allocate and fill vertex buffer - // Skin *skin = Skin::get(geo); - uint8 *verts = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); - header->vertexBuffer = verts; + attribs = header->attribDesc; + + // + // Fill vertex buffer + // + + uint8 *verts = header->vertexBuffer; // Positions - for(a = attribs; a->index != ATTRIB_POS; a++) - ; - instV3d(VERT_FLOAT3, verts + a->offset, - geo->morphTargets[0].vertices, - header->totalNumVertex, a->stride); + if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){ + for(a = attribs; a->index != ATTRIB_POS; a++) + ; + instV3d(VERT_FLOAT3, verts + a->offset, + geo->morphTargets[0].vertices, + header->totalNumVertex, a->stride); + } // Normals - if(hasNormals){ + if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){ for(a = attribs; a->index != ATTRIB_NORMAL; a++) ; instV3d(VERT_FLOAT3, verts + a->offset, @@ -172,7 +188,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) } // Prelighting - if(isPrelit){ + if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){ for(a = attribs; a->index != ATTRIB_COLOR; a++) ; instColor(VERT_RGBA, verts + a->offset, @@ -182,32 +198,37 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) // Texture coordinates for(int32 n = 0; n < geo->numTexCoordSets; n++){ - for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++) - ; - instTexCoords(VERT_FLOAT2, verts + a->offset, - geo->texCoords[n], - header->totalNumVertex, a->stride); + if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<index != ATTRIB_TEXCOORDS0+n; a++) + ; + instTexCoords(VERT_FLOAT2, verts + a->offset, + geo->texCoords[n], + header->totalNumVertex, a->stride); + } } // Weights - for(a = attribs; a->index != ATTRIB_WEIGHTS; a++) - ; - float *w = skin->weights; - instV4d(VERT_FLOAT4, verts + a->offset, - (V4d*)w, - header->totalNumVertex, a->stride); + if(!reinstance){ + for(a = attribs; a->index != ATTRIB_WEIGHTS; a++) + ; + float *w = skin->weights; + instV4d(VERT_FLOAT4, verts + a->offset, + (V4d*)w, + header->totalNumVertex, a->stride); + } // Indices - for(a = attribs; a->index != ATTRIB_INDICES; a++) - ; - // not really colors of course but what the heck - instColor(VERT_RGBA, verts + a->offset, - (RGBA*)skin->indices, - header->totalNumVertex, a->stride); + if(!reinstance){ + for(a = attribs; a->index != ATTRIB_INDICES; a++) + ; + // not really colors of course but what the heck + instColor(VERT_RGBA, verts + a->offset, + (RGBA*)skin->indices, + header->totalNumVertex, a->stride); + } - glGenBuffers(1, &header->vbo); glBindBuffer(GL_ARRAY_BUFFER, header->vbo); - glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*stride, + glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride, header->vertexBuffer, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 2384ee7..665b2d2 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -182,18 +182,20 @@ void flushCache(void); class ObjPipeline : public rw::ObjPipeline { public: - void (*instanceCB)(Geometry *geo, InstanceDataHeader *header); + void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance); void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header); void (*renderCB)(Atomic *atomic, InstanceDataHeader *header); ObjPipeline(uint32 platform); }; -void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance); void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); int32 lightingCB(Atomic *atomic); +void *destroyNativeData(void *object, int32, int32); + ObjPipeline *makeDefaultPipeline(void); // Native Texture and Raster