Browse Source

UBO fixes

- correct fix for ubo memroy allocation (use returned alignment instead
of struct size)
- separated convex fill to own command type
- moved uboPos to call struct
shared-context
Mikko Mononen 11 years ago
parent
commit
85fb384a3d
1 changed files with 83 additions and 70 deletions
  1. +83
    -70
      src/nanovg_gl3buf.h

+ 83
- 70
src/nanovg_gl3buf.h View File

@@ -93,6 +93,7 @@ struct GLNVGtexture {

enum GLNVGcallType {
GLNVG_FILL,
GLNVG_CONVEXFILL,
GLNVG_STROKE,
GLNVG_TRIANGLES,
};
@@ -106,6 +107,7 @@ struct GLNVGcall {
float strokeWidth;
int triangleOffset;
int triangleCount;
int uboOffset;
};

struct GLNVGpath {
@@ -113,7 +115,6 @@ struct GLNVGpath {
int fillCount;
int strokeOffset;
int strokeCount;
int convex;
};

struct GLNVGuboFrag {
@@ -656,10 +657,9 @@ static int glnvg__setupPaintUBO(struct GLNVGcontext* gl, struct NVGpaint* paint,
return 1;
}

static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, int* uboPos)
static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, int uboOffset)
{
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag));
*uboPos += gl->uboPosAlignment;
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, uboOffset, sizeof(struct GLNVGuboFrag));
if (paint->image != 0) {
struct GLNVGtexture* tex = glnvg__findTexture(gl, paint->image);
if (tex == NULL) return 0;
@@ -676,81 +676,87 @@ static void glnvg__renderViewport(void* uptr, int width, int height)
gl->view[1] = (float)height;
}

static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos )
static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call)
{
struct GLNVGpath* paths = &gl->paths[call->pathOffset];
int npaths = call->pathCount, i;

if (npaths == 1 && paths[0].convex) {
glnvg__setupPaint(gl, &call->paint, uboPos);
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
if (gl->edgeAntiAlias) {
// Draw fringes
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
}
} else {
// Draw shapes
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xff);
glStencilFunc(GL_ALWAYS, 0, ~0L);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

// set bindpoint for solid loc
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, call->uboOffset, sizeof(struct GLNVGuboFrag));
glnvg__checkError("fill solid loc");

glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glDisable(GL_CULL_FACE);
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
glEnable(GL_CULL_FACE);

// Draw aliased off-pixels
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);

// Draw shapes
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xff);
glStencilFunc(GL_ALWAYS, 0, ~0L);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

// set bindpoint for solid loc
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag));
*uboPos += gl->uboPosAlignment;
glnvg__checkError("fill solid loc");

glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glDisable(GL_CULL_FACE);
glnvg__setupPaint(gl, &call->paint, call->uboOffset + gl->uboPosAlignment);

if (gl->edgeAntiAlias) {
glStencilFunc(GL_EQUAL, 0x00, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw fringes
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
glEnable(GL_CULL_FACE);
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
}

// Draw aliased off-pixels
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);
// Draw fill
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);

glnvg__setupPaint(gl, &call->paint, uboPos);
glDisable(GL_STENCIL_TEST);
}

if (gl->edgeAntiAlias) {
glStencilFunc(GL_EQUAL, 0x00, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw fringes
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
}
static void glnvg__convexFill(struct GLNVGcontext* gl, struct GLNVGcall* call)
{
struct GLNVGpath* paths = &gl->paths[call->pathOffset];
int npaths = call->pathCount, i;

// Draw fill
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);
glnvg__setupPaint(gl, &call->paint, call->uboOffset);

glDisable(GL_STENCIL_TEST);
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
if (gl->edgeAntiAlias) {
// Draw fringes
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
}
}

static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos)
static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call)
{
struct GLNVGpath* paths = &gl->paths[call->pathOffset];
int npaths = call->pathCount, i;
glnvg__setupPaint(gl, &call->paint, uboPos);

glnvg__setupPaint(gl, &call->paint, call->uboOffset);

// Draw Strokes
for (i = 0; i < npaths; i++)
glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
}

static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos)
static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call)
{
struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image);
if (tex != NULL)
glBindTexture(GL_TEXTURE_2D, tex->tex);
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag));
*uboPos += gl->uboPosAlignment;

glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, call->uboOffset, sizeof(struct GLNVGuboFrag));

glnvg__checkError("tris solid img loc");
glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);
}
@@ -758,7 +764,8 @@ static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call, in
static void glnvg__renderFlush(void* uptr)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
int i, uboPos;
int i, offset;
char* buff;

if (gl->ncalls > 0) {

@@ -767,28 +774,31 @@ static void glnvg__renderFlush(void* uptr)

// upload ubo for frag shaders - maximum ubos is 2x num calls
glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf);
glBufferData(GL_UNIFORM_BUFFER, 3 * gl->ncalls * sizeof(struct GLNVGuboFrag), 0, GL_STREAM_DRAW);
char* buff = (char*)glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
glBufferData(GL_UNIFORM_BUFFER, 2 * gl->ncalls * gl->uboPosAlignment, 0, GL_STREAM_DRAW);
buff = (char*)glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
offset = 0;
for (i = 0; i < gl->ncalls; i++) {
struct GLNVGcall* call = &gl->calls[i];
struct GLNVGuboFrag* ubo = (struct GLNVGuboFrag*)buff;
struct GLNVGuboFrag* ubo = (struct GLNVGuboFrag*)&buff[offset];
call->uboOffset = offset;
if (call->type == GLNVG_FILL) {
if (!(call->pathCount == 1 && gl->paths[call->pathOffset].convex)) {
ubo->type = NSVG_SHADER_SIMPLE;
buff += gl->uboPosAlignment;
ubo = (struct GLNVGuboFrag*)buff;
}
ubo->type = NSVG_SHADER_SIMPLE;
offset += gl->uboPosAlignment;
ubo = (struct GLNVGuboFrag*)&buff[offset];
glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, 1.0001f, ubo);
offset += gl->uboPosAlignment;
} else if (call->type == GLNVG_CONVEXFILL) {
glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, 1.0001f, ubo);
buff += gl->uboPosAlignment;
offset += gl->uboPosAlignment;
} else if (call->type == GLNVG_STROKE) {
glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, call->strokeWidth, ubo);
buff += gl->uboPosAlignment;
offset += gl->uboPosAlignment;
} else if (call->type == GLNVG_TRIANGLES) {
struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image);
glnvg__toFloatColor(ubo->innerCol, call->paint.innerColor);
ubo->texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1;
ubo->type = NSVG_SHADER_IMG;
buff += gl->uboPosAlignment;
offset += gl->uboPosAlignment;
}
}
glUnmapBuffer(GL_UNIFORM_BUFFER);
@@ -809,16 +819,17 @@ static void glnvg__renderFlush(void* uptr)
glBindBufferBase(GL_UNIFORM_BUFFER, GLNVG_UBO_VIEW_BINDING, gl->uboViewBuf);

glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf);
uboPos = 0;

for (i = 0; i < gl->ncalls; i++) {
struct GLNVGcall* call = &gl->calls[i];
if (call->type == GLNVG_FILL)
glnvg__fill(gl, call, &uboPos);
glnvg__fill(gl, call);
else if (call->type == GLNVG_CONVEXFILL)
glnvg__convexFill(gl, call);
else if (call->type == GLNVG_STROKE)
glnvg__stroke(gl, call, &uboPos);
glnvg__stroke(gl, call);
else if (call->type == GLNVG_TRIANGLES)
glnvg__triangles(gl, call, &uboPos);
glnvg__triangles(gl, call);
}

glDisableVertexAttribArray(0);
@@ -902,6 +913,9 @@ static void glnvg__renderFill(void* uptr, struct NVGpaint* paint, struct NVGscis
call->paint = *paint;
call->scissor = *scissor;

if (npaths == 1 && paths[0].convex)
call->type = GLNVG_CONVEXFILL;

// Allocate vertices for all the paths.
maxverts = glnvg__maxVertCount(paths, npaths);
vertsoff = glnvg__allocVerts(gl, maxverts + 6);
@@ -910,7 +924,6 @@ static void glnvg__renderFill(void* uptr, struct NVGpaint* paint, struct NVGscis
struct GLNVGpath* copy = &gl->paths[call->pathOffset + i];
const struct NVGpath* path = &paths[i];
memset(copy, 0, sizeof(struct GLNVGpath));
copy->convex = path->convex;
if (path->nfill) {
copy->fillOffset = vertsoff;
copy->fillCount = path->nfill;


Loading…
Cancel
Save