mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-13 00:28:15 +00:00
gl2shim: more refactoring
This commit is contained in:
parent
8124035763
commit
4114d2f24d
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
gl2wrap_shim.c - vitaGL custom immediate mode shim
|
gl2_shim.c - GL CORE/ES2+ FFP emulation
|
||||||
Copyright (C) 2023 fgsfds
|
Copyright (C) 2023 mittorn, fgsfds
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -14,9 +14,21 @@ GNU General Public License for more details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this is a "replacement" for vitaGL's immediate mode tailored specifically for xash
|
based on vglshim, as it has almost all needed for using glbegins on gles
|
||||||
this will only provide performance gains if vitaGL is built with DRAW_SPEEDHACK=1
|
BufStorage mode should work similar to vglshim with vitagl's DRAW_SPEEDHACK
|
||||||
since that makes it assume that all vertex data pointers are GPU-mapped
|
as it uses gpu-mapped in similar way
|
||||||
|
|
||||||
|
gl2shim will not give much performance gain. It does not batch small drawcalls, just do little copy optimization
|
||||||
|
It just allows to draw similar way as in native legacy context, but in es/core contexts
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
1. Matrix support is very limited, only combined MVP
|
||||||
|
2. No TexEnv support, multitexture always works in MODULATE mode
|
||||||
|
3. DrawElements with client pointers will not work on CORE/WEBGL contexts, DrawRangeElements will
|
||||||
|
4. No quads in arrays drawing (simple DrawArrays(GL_QUADS) may be implemented, but DrawElements not)
|
||||||
|
5. Textures are enabled with texcoord attribs, not glEnable (can be changed, but who cares?)
|
||||||
|
6. Begin/End limited to 8192 vertices. It is possible to support more, but need change glVertex logic to split drawcals, which may make it slower
|
||||||
|
7. Textures internalformat ignored except of removing alpha from RGB textures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gl_local.h"
|
#include "gl_local.h"
|
||||||
@ -27,6 +39,7 @@ GNU General Public License for more details.
|
|||||||
#define MAX_SHADERLEN 4096
|
#define MAX_SHADERLEN 4096
|
||||||
// increase this when adding more attributes
|
// increase this when adding more attributes
|
||||||
#define MAX_PROGS 32
|
#define MAX_PROGS 32
|
||||||
|
// must be LESS GL2_MAX_VERTS
|
||||||
#define MAX_BEGINEND_VERTS 8192
|
#define MAX_BEGINEND_VERTS 8192
|
||||||
void* (APIENTRY* _pglMapBufferRange)(GLenum target, GLsizei offset, GLsizei length, GLbitfield access);
|
void* (APIENTRY* _pglMapBufferRange)(GLenum target, GLsizei offset, GLsizei length, GLbitfield access);
|
||||||
void* (APIENTRY* _pglFlushMappedBufferRange)(GLenum target, GLsizei offset, GLsizei length);
|
void* (APIENTRY* _pglFlushMappedBufferRange)(GLenum target, GLsizei offset, GLsizei length);
|
||||||
@ -35,15 +48,15 @@ void (APIENTRY*_pglBufferStorage)( GLenum target,
|
|||||||
GLsizei size,
|
GLsizei size,
|
||||||
const GLvoid * data,
|
const GLvoid * data,
|
||||||
GLbitfield flags);
|
GLbitfield flags);
|
||||||
void (*_pglWaitSync)( void * sync,
|
void (APIENTRY*_pglWaitSync)( void * sync,
|
||||||
GLbitfield flags,
|
GLbitfield flags,
|
||||||
uint64_t timeout);
|
uint64_t timeout);
|
||||||
GLuint (*_pglClientWaitSync)( void * sync,
|
GLuint (APIENTRY*_pglClientWaitSync)( void * sync,
|
||||||
GLbitfield flags,
|
GLbitfield flags,
|
||||||
uint64_t timeout);
|
uint64_t timeout);
|
||||||
void *(*_pglFenceSync)( GLenum condition,
|
void *(APIENTRY*_pglFenceSync)( GLenum condition,
|
||||||
GLbitfield flags);
|
GLbitfield flags);
|
||||||
void (*_pglDeleteSync)( void * sync );
|
void (APIENTRY*_pglDeleteSync)( void * sync );
|
||||||
|
|
||||||
extern ref_api_t gEngfuncs;
|
extern ref_api_t gEngfuncs;
|
||||||
|
|
||||||
@ -120,7 +133,7 @@ static struct
|
|||||||
qboolean async; // enable MAP_UNSYNCHRONIZED_BIT on temporary mappings
|
qboolean async; // enable MAP_UNSYNCHRONIZED_BIT on temporary mappings
|
||||||
qboolean force_flush; // enable MAP_FLUSH_EXPLICIT_BIT and FlushMappedBufferRange calls
|
qboolean force_flush; // enable MAP_FLUSH_EXPLICIT_BIT and FlushMappedBufferRange calls
|
||||||
uint32_t cycle_buffers; // cycle N buffers during draw to reduce locking in non-incremental mode
|
uint32_t cycle_buffers; // cycle N buffers during draw to reduce locking in non-incremental mode
|
||||||
uint32_t version;
|
uint32_t version; // glsl version to use
|
||||||
} gl2wrap_config;
|
} gl2wrap_config;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
@ -435,9 +448,9 @@ static void GL2_InitTriQuads( void )
|
|||||||
for( i = 0; i < (!!_pglDrawRangeElementsBaseVertex?1:4); i++ )
|
for( i = 0; i < (!!_pglDrawRangeElementsBaseVertex?1:4); i++ )
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
GLushort triquads_array[TRIQUADS_SIZE * 6];
|
GLushort triquads_array[TRIQUADS_SIZE];
|
||||||
|
|
||||||
for( j = 0; j < TRIQUADS_SIZE; j++ )
|
for( j = 0; j < TRIQUADS_SIZE / 6; j++ )
|
||||||
{
|
{
|
||||||
triquads_array[j * 6] = j * 4 + i;
|
triquads_array[j * 6] = j * 4 + i;
|
||||||
triquads_array[j * 6 + 1] = j * 4 + 1 + i;
|
triquads_array[j * 6 + 1] = j * 4 + 1 + i;
|
||||||
@ -644,8 +657,6 @@ static void GL2_ResetPersistentBuffer( void )
|
|||||||
int size = GL2_MAX_VERTS * gl2wrap_attr_size[i] * sizeof( GLfloat );
|
int size = GL2_MAX_VERTS * gl2wrap_attr_size[i] * sizeof( GLfloat );
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap.attrbufobj[i][gl2wrap.attrbufcycle] );
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap.attrbufobj[i][gl2wrap.attrbufcycle] );
|
||||||
if(gl2wrap_config.buf_storage)
|
if(gl2wrap_config.buf_storage)
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||||
@ -718,8 +729,17 @@ static void APIENTRY GL2_Begin( GLenum prim )
|
|||||||
// pos always enabled
|
// pos always enabled
|
||||||
gl2wrap.cur_flags |= 1 << GL2_ATTR_POS;
|
gl2wrap.cur_flags |= 1 << GL2_ATTR_POS;
|
||||||
}
|
}
|
||||||
void (*_pglMemoryBarrier)(GLbitfield barriers);
|
void (APIENTRY*_pglMemoryBarrier)(GLbitfield barriers);
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============================
|
||||||
|
UpdateIncrementalBuffer
|
||||||
|
|
||||||
|
glBufferStorage allows to write directly without mapping buffer every time before draw
|
||||||
|
This allows keep VAO unchanged and fastly build needed pipeline in driver for every program variant
|
||||||
|
When buffer storage not supported, we still may use cached VAO, but map/unmap it every time writing new data
|
||||||
|
==============================
|
||||||
|
*/
|
||||||
static void GL2_UpdateIncrementalBuffer( gl2wrap_prog_t *prog, int count )
|
static void GL2_UpdateIncrementalBuffer( gl2wrap_prog_t *prog, int count )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -750,6 +770,7 @@ static void GL2_UpdateIncrementalBuffer( gl2wrap_prog_t *prog, int count )
|
|||||||
}
|
}
|
||||||
else if(!gl2wrap_config.coherent)
|
else if(!gl2wrap_config.coherent)
|
||||||
{
|
{
|
||||||
|
// non-coherent buffers anyway require unmapping or flushing after write
|
||||||
for( i = 0; i < GL2_ATTR_MAX; i++)
|
for( i = 0; i < GL2_ATTR_MAX; i++)
|
||||||
{
|
{
|
||||||
if ( prog->attridx[i] >= 0 )
|
if ( prog->attridx[i] >= 0 )
|
||||||
@ -852,10 +873,18 @@ void GL2_FlushPrims( void )
|
|||||||
|
|
||||||
if(gl2wrap.prim == GL_QUADS)
|
if(gl2wrap.prim == GL_QUADS)
|
||||||
{
|
{
|
||||||
|
// simple case, one quad may draw like polygon(4)
|
||||||
if(count == 4)
|
if(count == 4)
|
||||||
rpglDrawArrays( GL_TRIANGLE_FAN, startindex, count );
|
rpglDrawArrays( GL_TRIANGLE_FAN, startindex, count );
|
||||||
else if(_pglDrawRangeElementsBaseVertex)
|
else if(_pglDrawRangeElementsBaseVertex)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Opengl deprecated QUADS, but made some workarounds availiable
|
||||||
|
* idea: bound static index array that will repeat 0 1 2 0 2 3 4 5 6 4 6 7...
|
||||||
|
* sequence and draw source arrays. But our array may have different offset
|
||||||
|
* When DrawRangeElementsBaseVertex unavailiable, we need build 4 different index arrays (as sequence have period 4)
|
||||||
|
* or just put 0-4 offset when it's availiable
|
||||||
|
* */
|
||||||
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, gl2wrap.triquads_ibo[0] );
|
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, gl2wrap.triquads_ibo[0] );
|
||||||
_pglDrawRangeElementsBaseVertex( GL_TRIANGLES, startindex, startindex + count, Q_min(count / 4 * 6,TRIQUADS_SIZE * 6 - startindex), GL_UNSIGNED_SHORT, (void*)(size_t)(startindex / 4 * 6 * 2), startindex % 4 );
|
_pglDrawRangeElementsBaseVertex( GL_TRIANGLES, startindex, startindex + count, Q_min(count / 4 * 6,TRIQUADS_SIZE * 6 - startindex), GL_UNSIGNED_SHORT, (void*)(size_t)(startindex / 4 * 6 * 2), startindex % 4 );
|
||||||
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||||
@ -873,15 +902,17 @@ void GL2_FlushPrims( void )
|
|||||||
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
|
pglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( gl2wrap.prim == GL_POLYGON )
|
else if( gl2wrap.prim == GL_POLYGON ) // does it have any difference with TRIFAN?
|
||||||
rpglDrawArrays( GL_TRIANGLE_FAN, startindex, count );
|
rpglDrawArrays( GL_TRIANGLE_FAN, startindex, count );
|
||||||
else
|
else // TRIANGLES, LINES, TRISTRIP, TRIFAN supported anyway
|
||||||
rpglDrawArrays( gl2wrap.prim, startindex, count );
|
rpglDrawArrays( gl2wrap.prim, startindex, count );
|
||||||
|
|
||||||
_leave:
|
_leave:
|
||||||
if(gl2wrap_config.vao_mandatory)
|
if(gl2wrap_config.vao_mandatory)
|
||||||
|
{
|
||||||
pglBindVertexArray(0);
|
pglBindVertexArray(0);
|
||||||
pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
gl2wrap.prim = GL_NONE;
|
gl2wrap.prim = GL_NONE;
|
||||||
gl2wrap.begin = gl2wrap.end;
|
gl2wrap.begin = gl2wrap.end;
|
||||||
@ -1027,12 +1058,7 @@ static void APIENTRY GL2_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
|
|||||||
if ( gl2wrap.prim )
|
if ( gl2wrap.prim )
|
||||||
{
|
{
|
||||||
// HACK: enable color attribute if we're using color inside a Begin-End pair
|
// HACK: enable color attribute if we're using color inside a Begin-End pair
|
||||||
GLfloat *p = gl2wrap.attrbuf[GL2_ATTR_COLOR] + gl2wrap.end * 4;
|
|
||||||
gl2wrap.cur_flags |= 1 << GL2_ATTR_COLOR;
|
gl2wrap.cur_flags |= 1 << GL2_ATTR_COLOR;
|
||||||
*p++ = r;
|
|
||||||
*p++ = g;
|
|
||||||
*p++ = b;
|
|
||||||
*p++ = a;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,6 +1163,15 @@ static void APIENTRY GL2_Disable( GLenum e )
|
|||||||
rpglDisable(e);
|
rpglDisable(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Limited matrix emulation
|
||||||
|
|
||||||
|
===========================
|
||||||
|
*/
|
||||||
|
|
||||||
static void APIENTRY GL2_MatrixMode( GLenum m )
|
static void APIENTRY GL2_MatrixMode( GLenum m )
|
||||||
{
|
{
|
||||||
// if(gl2wrap_matrix.mode == m)
|
// if(gl2wrap_matrix.mode == m)
|
||||||
@ -1221,6 +1256,7 @@ static void GL2_Mul4x4(const GLfloat *in0, const GLfloat *in1, GLfloat *out)
|
|||||||
|
|
||||||
static void GL2_UpdateMVP( gl2wrap_prog_t *prog )
|
static void GL2_UpdateMVP( gl2wrap_prog_t *prog )
|
||||||
{
|
{
|
||||||
|
// use bitset to determine if need update matrix for this prog
|
||||||
if( gl2wrap_matrix.update & ( 1U << prog->flags ) )
|
if( gl2wrap_matrix.update & ( 1U << prog->flags ) )
|
||||||
{
|
{
|
||||||
gl2wrap_matrix.update &= ~( 1U << prog->flags );
|
gl2wrap_matrix.update &= ~( 1U << prog->flags );
|
||||||
@ -1242,6 +1278,13 @@ static void APIENTRY GL2_DepthRange(GLdouble far, GLdouble near)
|
|||||||
_pglDepthRangef(far, near);
|
_pglDepthRangef(far, near);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
======================
|
||||||
|
|
||||||
|
Array drawing
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
typedef struct gl2wrap_arraypointer_s
|
typedef struct gl2wrap_arraypointer_s
|
||||||
{
|
{
|
||||||
const void *userptr;
|
const void *userptr;
|
||||||
@ -1318,6 +1361,148 @@ static void APIENTRY GL2_DisableClientState( GLenum array )
|
|||||||
gl2wrap_arrays.flags &= ~(1 << idx);
|
gl2wrap_arrays.flags &= ~(1 << idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========================
|
||||||
|
UploadBufferData
|
||||||
|
|
||||||
|
Dumb buffer upload
|
||||||
|
Used when uploading very large buffers or when persistent/incremental buffers disabled (MapBuffer unavailiable?)
|
||||||
|
===========================
|
||||||
|
*/
|
||||||
|
static void GL2_UploadBufferData( gl2wrap_prog_t *prog, int size, GLuint start, GLuint end, int stride, int attr )
|
||||||
|
{
|
||||||
|
if( !gl2wrap_arrays.ptr[attr].vbo_fb )
|
||||||
|
{
|
||||||
|
gl2wrap_arrays.ptr[attr].vbo_fb = malloc(4 * gl2wrap_config.cycle_buffers);
|
||||||
|
pglGenBuffersARB( gl2wrap_config.cycle_buffers, gl2wrap_arrays.ptr[attr].vbo_fb );
|
||||||
|
}
|
||||||
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.ptr[attr].vbo_fb[gl2wrap_arrays.ptr[attr].vbo_cycle] );
|
||||||
|
gl2wrap_arrays.ptr[attr].vbo_cycle = (gl2wrap_arrays.ptr[attr].vbo_cycle + 1) % gl2wrap_config.cycle_buffers;
|
||||||
|
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, end * stride, gl2wrap_arrays.ptr[attr].userptr, GL_STREAM_DRAW_ARB );
|
||||||
|
pglVertexAttribPointerARB( prog->attridx[attr], gl2wrap_arrays.ptr[attr].size, gl2wrap_arrays.ptr[attr].type, attr == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[attr].stride, 0 );
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
===========================
|
||||||
|
UpdatePersistentArrayBuffer
|
||||||
|
|
||||||
|
Persistent array always mapped to stream_pointer with BufferStorage
|
||||||
|
just memcopy it into and flush when overflowed
|
||||||
|
===========================
|
||||||
|
*/
|
||||||
|
static void GL2_UpdatePersistentArrayBuffer( gl2wrap_prog_t *prog, int size, int offset, GLuint start, GLuint end, int stride, int attr )
|
||||||
|
{
|
||||||
|
|
||||||
|
if(gl2wrap_arrays.stream_counter + size > GL2_MAX_VERTS * 64)
|
||||||
|
{
|
||||||
|
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||||
|
gl2wrap_arrays.stream_counter = 0;
|
||||||
|
gl2wrap_arrays.stream_pointer = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
||||||
|
0,
|
||||||
|
GL2_MAX_VERTS * 64,
|
||||||
|
0x0002 //GL_MAP_WRITE_BIT
|
||||||
|
// | 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
||||||
|
// | 0x0008 // GL_MAP_INVALIDATE_BUFFER_BIT
|
||||||
|
// |0x0020 //GL_MAP_UNSYNCHRONIZED_BIT
|
||||||
|
|(!gl2wrap_config.coherent?0x0010:0) // GL_MAP_FLUSH_EXPLICIT_BIT
|
||||||
|
| 0X40
|
||||||
|
| (gl2wrap_config.coherent?0x00000080:0) // GL_MAP_COHERENT_BIT
|
||||||
|
);
|
||||||
|
//i = -1;
|
||||||
|
//continue;
|
||||||
|
size = end * stride, offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(((char*)gl2wrap_arrays.stream_pointer) + gl2wrap_arrays.stream_counter, ((char*)gl2wrap_arrays.ptr[attr].userptr) + offset, size);
|
||||||
|
if( !gl2wrap_config.coherent )
|
||||||
|
_pglFlushMappedBufferRange( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_counter, size );
|
||||||
|
pglVertexAttribPointerARB( prog->attridx[attr], gl2wrap_arrays.ptr[attr].size, gl2wrap_arrays.ptr[attr].type, attr == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[attr].stride, (void*)(gl2wrap_arrays.stream_counter - offset) );
|
||||||
|
gl2wrap_arrays.stream_counter += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========================
|
||||||
|
UpdateIncrementalArrayBuffer
|
||||||
|
|
||||||
|
Like persistent buffer, but map every time when copying data when BufferStorage unavailiable
|
||||||
|
===========================
|
||||||
|
*/
|
||||||
|
static void GL2_UpdateIncrementalArrayBuffer( gl2wrap_prog_t *prog, int size, int offset, GLuint start, GLuint end, int stride, int attr )
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
qboolean inv = false;
|
||||||
|
if(gl2wrap_arrays.stream_counter + size > GL2_MAX_VERTS * 64)
|
||||||
|
size = end * stride, offset = 0, gl2wrap_arrays.stream_counter = 0, inv = true;
|
||||||
|
mem = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
||||||
|
gl2wrap_arrays.stream_counter,
|
||||||
|
size,
|
||||||
|
0x0002 //GL_MAP_WRITE_BIT
|
||||||
|
| 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
||||||
|
| (inv?0x0008:0) // GL_MAP_INVALIDATE_BUFFER_BIT
|
||||||
|
|(gl2wrap_config.async ? 0x0020:0) //GL_MAP_UNSYNCHRONIZED_BIT
|
||||||
|
|(gl2wrap_config.force_flush ? 0x0010:0) // GL_MAP_FLUSH_EXPLICIT_BIT
|
||||||
|
// GL_MAP_COHERENT_BIT
|
||||||
|
);
|
||||||
|
memcpy(mem, ((char*)gl2wrap_arrays.ptr[attr].userptr) + offset, size);
|
||||||
|
if(gl2wrap_config.force_flush)
|
||||||
|
_pglFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, 0, size);
|
||||||
|
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
||||||
|
pglVertexAttribPointerARB( prog->attridx[attr], gl2wrap_arrays.ptr[attr].size, gl2wrap_arrays.ptr[attr].type, attr == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[attr].stride, (void*)(gl2wrap_arrays.stream_counter - offset) );
|
||||||
|
gl2wrap_arrays.stream_counter += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========================
|
||||||
|
AllocArrayPersistenStorage
|
||||||
|
|
||||||
|
Prepare BufferStorage
|
||||||
|
===========================
|
||||||
|
*/
|
||||||
|
static void GL2_AllocArrayPersistenStorage( void )
|
||||||
|
{
|
||||||
|
pglGenBuffersARB( 1, &gl2wrap_arrays.stream_buffer );
|
||||||
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
||||||
|
_pglBufferStorage( GL_ARRAY_BUFFER_ARB, GL2_MAX_VERTS * 64, NULL,
|
||||||
|
0x0002 //GL_MAP_WRITE_BIT
|
||||||
|
| (gl2wrap_config.coherent?0x00000080:0)
|
||||||
|
| 0x40
|
||||||
|
);
|
||||||
|
gl2wrap_arrays.stream_pointer = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
||||||
|
0,
|
||||||
|
GL2_MAX_VERTS * 64,
|
||||||
|
0x0002 //GL_MAP_WRITE_BIT
|
||||||
|
// | 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
||||||
|
// | 0x0008 // GL_MAP_INVALIDATE_BUFFER_BIT
|
||||||
|
// |0x0020 //GL_MAP_UNSYNCHRONIZED_BIT
|
||||||
|
// |0x0010 // GL_MAP_FLUSH_EXPLICIT_BIT
|
||||||
|
| (!gl2wrap_config.coherent?0x0010:0)
|
||||||
|
| 0X40
|
||||||
|
| (gl2wrap_config.coherent?0x00000080:0) // GL_MAP_COHERENT_BIT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GL2_AllocArrays( void )
|
||||||
|
{
|
||||||
|
if( gl2wrap_config.buf_storage && !gl2wrap_arrays.stream_pointer )
|
||||||
|
GL2_AllocArrayPersistenStorage();
|
||||||
|
else if(!gl2wrap_config.buf_storage && gl2wrap_config.incremental && !gl2wrap_arrays.stream_buffer)
|
||||||
|
{
|
||||||
|
// prepare incremental buffer
|
||||||
|
pglGenBuffersARB( 1, &gl2wrap_arrays.stream_buffer );
|
||||||
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
||||||
|
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, GL2_MAX_VERTS * 64, NULL, GL_STREAM_DRAW_ARB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
======================
|
||||||
|
SetupArrays
|
||||||
|
|
||||||
|
If vao usage mandatory, use persistent/incremental buffers when possible
|
||||||
|
else just set client pointers to default VAO
|
||||||
|
Usage of client pointers is forbidden with non-default VAO and unavailiable in Core
|
||||||
|
======================
|
||||||
|
*/
|
||||||
static void GL2_SetupArrays( GLuint start, GLuint end )
|
static void GL2_SetupArrays( GLuint start, GLuint end )
|
||||||
{
|
{
|
||||||
gl2wrap_prog_t *prog;
|
gl2wrap_prog_t *prog;
|
||||||
@ -1347,9 +1532,11 @@ static void GL2_SetupArrays( GLuint start, GLuint end )
|
|||||||
{
|
{
|
||||||
if(prog->attridx[i] < 0)
|
if(prog->attridx[i] < 0)
|
||||||
continue;
|
continue;
|
||||||
if( flags & (1 << i) )
|
if( flags & (1 << i) ) // attribute is enabled
|
||||||
{
|
{
|
||||||
pglEnableVertexAttribArrayARB( prog->attridx[i] );
|
pglEnableVertexAttribArrayARB( prog->attridx[i] );
|
||||||
|
// sometimes usage of client pointers may be faster, sometimes not
|
||||||
|
// anyway gl core disallows that, so try use streaming
|
||||||
if( gl2wrap_config.vao_mandatory && !gl2wrap_arrays.ptr[i].vbo )
|
if( gl2wrap_config.vao_mandatory && !gl2wrap_arrays.ptr[i].vbo )
|
||||||
{
|
{
|
||||||
// detect stride by type
|
// detect stride by type
|
||||||
@ -1364,41 +1551,12 @@ static void GL2_SetupArrays( GLuint start, GLuint end )
|
|||||||
stride = gl2wrap_arrays.ptr[i].size * 4;
|
stride = gl2wrap_arrays.ptr[i].size * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( gl2wrap_config.buf_storage && !gl2wrap_arrays.stream_pointer )
|
|
||||||
{
|
|
||||||
pglGenBuffersARB( 1, &gl2wrap_arrays.stream_buffer );
|
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
||||||
_pglBufferStorage( GL_ARRAY_BUFFER_ARB, GL2_MAX_VERTS * 64, NULL,
|
|
||||||
0x0002 //GL_MAP_WRITE_BIT
|
|
||||||
| (gl2wrap_config.coherent?0x00000080:0)
|
|
||||||
| 0x40
|
|
||||||
);
|
|
||||||
gl2wrap_arrays.stream_pointer = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
|
||||||
0,
|
|
||||||
GL2_MAX_VERTS * 64,
|
|
||||||
0x0002 //GL_MAP_WRITE_BIT
|
|
||||||
// | 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
|
||||||
// | 0x0008 // GL_MAP_INVALIDATE_BUFFER_BIT
|
|
||||||
// |0x0020 //GL_MAP_UNSYNCHRONIZED_BIT
|
|
||||||
// |0x0010 // GL_MAP_FLUSH_EXPLICIT_BIT
|
|
||||||
| (!gl2wrap_config.coherent?0x0010:0)
|
|
||||||
| 0X40
|
|
||||||
| (gl2wrap_config.coherent?0x00000080:0) // GL_MAP_COHERENT_BIT
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if(!gl2wrap_config.buf_storage && gl2wrap_config.incremental && !gl2wrap_arrays.stream_buffer)
|
|
||||||
{
|
|
||||||
pglGenBuffersARB( 1, &gl2wrap_arrays.stream_buffer );
|
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
|
||||||
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, GL2_MAX_VERTS * 64, NULL, GL_STREAM_DRAW_ARB );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_buffer );
|
|
||||||
}
|
|
||||||
if(!end)
|
if(!end)
|
||||||
{
|
{
|
||||||
|
// we cannot handle this case in VAO without known buffer length
|
||||||
|
// only workaround is scanning index array to determine buffer limits, but it is slow,
|
||||||
|
// so just do not use DrawElements when DrawRangeElements availiable
|
||||||
pglDisableVertexAttribArrayARB( prog->attridx[i] );
|
pglDisableVertexAttribArrayARB( prog->attridx[i] );
|
||||||
gEngfuncs.Con_Printf(S_ERROR "NON-vbo array for DrawElements call, SKIPPING!\n");
|
gEngfuncs.Con_Printf(S_ERROR "NON-vbo array for DrawElements call, SKIPPING!\n");
|
||||||
continue;
|
continue;
|
||||||
@ -1406,71 +1564,22 @@ static void GL2_SetupArrays( GLuint start, GLuint end )
|
|||||||
size = (end - start) * stride;
|
size = (end - start) * stride;
|
||||||
offset = start * stride;
|
offset = start * stride;
|
||||||
|
|
||||||
|
// Logical buffer start can lie before real buffer start
|
||||||
|
// but attrib pointer cannot have negative buffer offset
|
||||||
if( gl2wrap_arrays.stream_counter < offset )
|
if( gl2wrap_arrays.stream_counter < offset )
|
||||||
size = end * stride, offset = 0;
|
size = end * stride, offset = 0;
|
||||||
|
|
||||||
if( (!gl2wrap_config.buf_storage && !gl2wrap_config.incremental) || size > GL2_MAX_VERTS * 32) /// TODO: support incremental for !buf_storage
|
if( (!gl2wrap_config.buf_storage && !gl2wrap_config.incremental) || size > GL2_MAX_VERTS * 32)
|
||||||
{
|
{
|
||||||
if( !gl2wrap_arrays.ptr[i].vbo_fb )
|
GL2_UploadBufferData( prog, size , start, end, stride, i );
|
||||||
{
|
|
||||||
gl2wrap_arrays.ptr[i].vbo_fb = malloc(4 * gl2wrap_config.cycle_buffers);
|
|
||||||
pglGenBuffersARB( gl2wrap_config.cycle_buffers, gl2wrap_arrays.ptr[i].vbo_fb );
|
|
||||||
}
|
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.ptr[i].vbo_fb[gl2wrap_arrays.ptr[i].vbo_cycle] );
|
|
||||||
gl2wrap_arrays.ptr[i].vbo_cycle = (gl2wrap_arrays.ptr[i].vbo_cycle + 1) % gl2wrap_config.cycle_buffers;
|
|
||||||
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, end * stride, gl2wrap_arrays.ptr[i].userptr, GL_STREAM_DRAW_ARB );
|
|
||||||
pglVertexAttribPointerARB( prog->attridx[i], gl2wrap_arrays.ptr[i].size, gl2wrap_arrays.ptr[i].type, i == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[i].stride, 0 );
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(!gl2wrap_config.buf_storage && gl2wrap_config.incremental)
|
if(!gl2wrap_config.buf_storage && gl2wrap_config.incremental)
|
||||||
{
|
{
|
||||||
void *mem;
|
GL2_UpdateIncrementalArrayBuffer( prog, size, offset, start, end, stride, i);
|
||||||
qboolean inv = false;
|
|
||||||
if(gl2wrap_arrays.stream_counter + size > GL2_MAX_VERTS * 64)
|
|
||||||
size = end * stride, offset = 0, gl2wrap_arrays.stream_counter = 0, inv = true;
|
|
||||||
mem = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
|
||||||
gl2wrap_arrays.stream_counter,
|
|
||||||
size,
|
|
||||||
0x0002 //GL_MAP_WRITE_BIT
|
|
||||||
| 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
|
||||||
| (inv?0x0008:0) // GL_MAP_INVALIDATE_BUFFER_BIT
|
|
||||||
|(gl2wrap_config.async ? 0x0020:0) //GL_MAP_UNSYNCHRONIZED_BIT
|
|
||||||
|(gl2wrap_config.force_flush ? 0x0010:0) // GL_MAP_FLUSH_EXPLICIT_BIT
|
|
||||||
// GL_MAP_COHERENT_BIT
|
|
||||||
);
|
|
||||||
memcpy(mem, ((char*)gl2wrap_arrays.ptr[i].userptr) + offset, size);
|
|
||||||
if(gl2wrap_config.force_flush)
|
|
||||||
_pglFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, 0, size);
|
|
||||||
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
|
||||||
pglVertexAttribPointerARB( prog->attridx[i], gl2wrap_arrays.ptr[i].size, gl2wrap_arrays.ptr[i].type, i == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[i].stride, (void*)(gl2wrap_arrays.stream_counter - offset) );
|
|
||||||
gl2wrap_arrays.stream_counter += size;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(gl2wrap_arrays.stream_counter + size > GL2_MAX_VERTS * 64)
|
GL2_UpdatePersistentArrayBuffer( prog, size, offset, start, end, stride, i);
|
||||||
{
|
|
||||||
pglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
|
|
||||||
gl2wrap_arrays.stream_counter = 0;
|
|
||||||
gl2wrap_arrays.stream_pointer = _pglMapBufferRange(GL_ARRAY_BUFFER_ARB,
|
|
||||||
0,
|
|
||||||
GL2_MAX_VERTS * 64,
|
|
||||||
0x0002 //GL_MAP_WRITE_BIT
|
|
||||||
// | 0x0004// GL_MAP_INVALIDATE_RANGE_BIT.
|
|
||||||
// | 0x0008 // GL_MAP_INVALIDATE_BUFFER_BIT
|
|
||||||
// |0x0020 //GL_MAP_UNSYNCHRONIZED_BIT
|
|
||||||
|(!gl2wrap_config.coherent?0x0010:0) // GL_MAP_FLUSH_EXPLICIT_BIT
|
|
||||||
| 0X40
|
|
||||||
| (gl2wrap_config.coherent?0x00000080:0) // GL_MAP_COHERENT_BIT
|
|
||||||
);
|
|
||||||
//i = -1;
|
|
||||||
//continue;
|
|
||||||
size = end * stride, offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(((char*)gl2wrap_arrays.stream_pointer) + gl2wrap_arrays.stream_counter, ((char*)gl2wrap_arrays.ptr[i].userptr) + offset, size);
|
|
||||||
if( !gl2wrap_config.coherent )
|
|
||||||
_pglFlushMappedBufferRange( GL_ARRAY_BUFFER_ARB, gl2wrap_arrays.stream_counter, size );
|
|
||||||
pglVertexAttribPointerARB( prog->attridx[i], gl2wrap_arrays.ptr[i].size, gl2wrap_arrays.ptr[i].type, i == GL2_ATTR_COLOR, gl2wrap_arrays.ptr[i].stride, (void*)(gl2wrap_arrays.stream_counter - offset) );
|
|
||||||
gl2wrap_arrays.stream_counter += size;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1489,6 +1598,7 @@ static void GL2_SetupArrays( GLuint start, GLuint end )
|
|||||||
pglDisableVertexAttribArrayARB( prog->attridx[i] );
|
pglDisableVertexAttribArrayARB( prog->attridx[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// restore state
|
||||||
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_state.vbo );
|
rpglBindBufferARB( GL_ARRAY_BUFFER_ARB, gl2wrap_state.vbo );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1621,5 +1731,6 @@ void GL2_ShimInstall( void )
|
|||||||
#ifdef QUAD_BATCH
|
#ifdef QUAD_BATCH
|
||||||
GL2_OVERRIDE_PTR_B( BindTexture )
|
GL2_OVERRIDE_PTR_B( BindTexture )
|
||||||
#endif
|
#endif
|
||||||
|
GL2_AllocArrays();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user