some work on gl3

This commit is contained in:
aap 2020-04-28 12:44:28 +02:00
parent eb71ca25d0
commit 4f118dcd97
7 changed files with 289 additions and 264 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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,8 +135,6 @@ 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);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_GL3);
@ -109,15 +154,21 @@ ObjPipeline::ObjPipeline(uint32 platform)
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
{
AttribDesc attribs[12], *a;
AttribDesc *attribs, *a;
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(!reinstance){
AttribDesc tmpAttribs[12];
uint32 stride;
//
// Create attribute descriptions
//
a = attribs;
a = tmpAttribs;
stride = 0;
// Positions
@ -131,7 +182,6 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
// Normals
// TODO: compress
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
@ -143,7 +193,6 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
}
// Prelighting
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;
@ -165,28 +214,40 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
a++;
}
header->numAttribs = a - attribs;
for(a = attribs; a != &attribs[header->numAttribs]; 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, attribs,
memcpy(header->attribDesc, tmpAttribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate and fill vertex buffer
// Allocate vertex buffer
//
uint8 *verts = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
header->vertexBuffer = verts;
header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
assert(header->vbo == 0);
glGenBuffers(1, &header->vbo);
}
attribs = header->attribDesc;
//
// Fill vertex buffer
//
uint8 *verts = header->vertexBuffer;
// Positions
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++){
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
for(a = attribs; a->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);
}

View File

@ -213,7 +213,11 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
assert(raster->privateFlags == 0);
px = (uint8*)rwMalloc(raster->stride*raster->height, 0); // TODO: hint
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;
@ -224,6 +228,12 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
}
raster->privateFlags = lockMode;
break;
default:
assert(0 && "cannot lock this type of raster yet");
return nil;
}
return px;
#else

View File

@ -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)
{

View File

@ -67,15 +67,21 @@ enum
};
void
skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
{
AttribDesc attribs[14], *a;
AttribDesc *attribs, *a;
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(!reinstance){
AttribDesc tmpAttribs[14];
uint32 stride;
//
// Create attribute descriptions
//
a = attribs;
a = tmpAttribs;
stride = 0;
// Positions
@ -89,7 +95,6 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
// Normals
// TODO: compress
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
@ -101,7 +106,6 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
}
// Prelighting
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;
@ -141,29 +145,41 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
stride += 4;
a++;
header->numAttribs = a - attribs;
for(a = attribs; a != &attribs[header->numAttribs]; 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, attribs,
memcpy(header->attribDesc, tmpAttribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate and fill vertex buffer
// Allocate vertex buffer
//
header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
assert(header->vbo == 0);
glGenBuffers(1, &header->vbo);
}
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
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++){
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
;
instTexCoords(VERT_FLOAT2, verts + a->offset,
geo->texCoords[n],
header->totalNumVertex, a->stride);
}
}
// Weights
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
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);
}

View File

@ -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