Skip to content

Commit

Permalink
Try to avoid glGenBuffer in the middle of frames
Browse files Browse the repository at this point in the history
and don’t do offscreen renders
  • Loading branch information
troughton committed May 13, 2019
1 parent c44a471 commit 42f187a
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 147 deletions.
56 changes: 19 additions & 37 deletions src/platform/guimac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ MenuRef AddSubMenu(const std::string &label) override {
}

void Clear() override {
while([nsMenuBar numberOfItems] != 1) {
while([nsMenuBar numberOfItems] > 1) {
[nsMenuBar removeItemAtIndex:1];
}
subMenus.clear();
Expand All @@ -344,7 +344,7 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
// Cocoa NSView and NSWindow extensions
//-----------------------------------------------------------------------------

@interface SSView : NSView
@interface SSView : NSOpenGLView
@property Platform::Window *receiver;

@property BOOL acceptsFirstResponder;
Expand All @@ -362,26 +362,24 @@ - (void)didEdit:(NSString *)text;

@implementation SSView
{
GlOffscreen offscreen;
NSOpenGLContext *glContext;
NSTrackingArea *trackingArea;
NSTextField *editor;
}

@synthesize acceptsFirstResponder;

- (id)initWithFrame:(NSRect)frameRect {
if(self = [super initWithFrame:frameRect]) {

NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFAColorSize, 24,
NSOpenGLPFADepthSize, 24,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];

if(self = [super initWithFrame:frameRect pixelFormat:pixelFormat]) {
self.wantsLayer = YES;

NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFAColorSize, 24,
NSOpenGLPFADepthSize, 24,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:NULL];


editor = [[NSTextField alloc] init];
editor.editable = YES;
[[editor cell] setWraps:NO];
Expand All @@ -394,7 +392,7 @@ - (id)initWithFrame:(NSRect)frameRect {
}

- (void)dealloc {
offscreen.Clear();
// offscreen.Clear();
}

- (BOOL)isFlipped {
Expand All @@ -404,29 +402,13 @@ - (BOOL)isFlipped {
@synthesize receiver;

- (void)drawRect:(NSRect)aRect {
[glContext makeCurrentContext];

NSSize size = [self convertSizeToBacking:self.bounds.size];
int width = (int)size.width,
height = (int)size.height;
offscreen.Render(width, height, [&] {
if(receiver->onRender) {
receiver->onRender();
}
});

CGDataProviderRef provider = CGDataProviderCreateWithData(
NULL, &offscreen.data[0], width * height * 4, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef image = CGImageCreate(width, height, 8, 32,
width * 4, colorspace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
provider, NULL, true, kCGRenderingIntentDefault);

CGContextDrawImage((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort],
[self bounds], image);
[[self openGLContext] makeCurrentContext];

CGImageRelease(image);
CGDataProviderRelease(provider);
if(receiver->onRender) {
receiver->onRender();
}

[[self openGLContext] flushBuffer];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)event {
Expand Down
175 changes: 97 additions & 78 deletions src/render/gl3shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,20 +458,28 @@ void EdgeRenderer::Init(const StippleAtlas *a) {
{ ATTRIB_TAN, "tgt" }
}
);

glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);

}

void EdgeRenderer::Clear() {
shader.Clear();
}

EdgeRenderer::Handle EdgeRenderer::Add(const SEdgeList &edges, bool dynamic) {
Handle handle;
glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);

void EdgeRenderer::SetEdgeCount(uint32_t edgeCount) {
verticesIndex = 0;
indicesIndex = 0;

// 8 vertices per edge, and 18 indices per edge.
glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
glBufferData(GL_ARRAY_BUFFER, edgeCount * 8 * sizeof(EdgeVertex), nullptr, GL_DYNAMIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, edgeCount * 6 * 3 * sizeof(uint32_t), nullptr, GL_DYNAMIC_DRAW);
}

void EdgeRenderer::Add(const SEdgeList &edges) {
EdgeVertex *vertices = new EdgeVertex[edges.l.n * 8];
uint32_t *indices = new uint32_t[edges.l.n * 6 * 3];
double phase = 0.0;
Expand All @@ -484,6 +492,8 @@ EdgeRenderer::Handle EdgeRenderer::Add(const SEdgeList &edges, bool dynamic) {
// 3d positions
Vector3f a = Vector3f::From(curr.a);
Vector3f b = Vector3f::From(curr.b);

printf("Drawing edge between (%.2f, %.2f, %.2f) and (%.2f, %.2f, %.2f)\n", a.x, a.y, a.z, b.x, b.y, b.z);

// tangent
Vector3f tan = Vector3f::From(curr.b.Minus(curr.a));
Expand Down Expand Up @@ -561,24 +571,28 @@ EdgeRenderer::Handle EdgeRenderer::Add(const SEdgeList &edges, bool dynamic) {
phase = 0.0;
}
}
handle.size = curIndex;
GLenum mode = dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
glBufferData(GL_ARRAY_BUFFER, curVertex * sizeof(EdgeVertex), vertices, mode);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, curIndex * sizeof(uint32_t), indices, mode);

glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);

glBufferSubData(GL_ARRAY_BUFFER, verticesIndex * sizeof(EdgeVertex), curVertex * sizeof(EdgeVertex), vertices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indicesIndex * sizeof(uint32_t), curIndex * sizeof(uint32_t), indices);

verticesIndex += curVertex;
indicesIndex += curIndex;

delete []vertices;
delete []indices;

return handle;
}

void EdgeRenderer::Remove(const EdgeRenderer::Handle &handle) {
glDeleteBuffers(1, &handle.vertexBuffer);
glDeleteBuffers(1, &handle.indexBuffer);
}

void EdgeRenderer::Draw(const EdgeRenderer::Handle &handle) {
if(handle.size == 0) return;

void EdgeRenderer::Draw(const SEdgeList &edges) {
if (edges.l.n == 0) return;

uint32_t baseIndex = verticesIndex;
uint32_t baseVertex = indicesIndex;
this->Add(edges);
uint32_t edgeCount = edges.l.n;

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, atlas->GetTexture(pattern));
shader.SetUniformTextureUnit("pattern", 1);
Expand All @@ -596,7 +610,7 @@ void EdgeRenderer::Draw(const EdgeRenderer::Handle &handle) {
glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, sizeof(EdgeVertex), (void *)offsetof(EdgeVertex, pos));
glVertexAttribPointer(ATTRIB_LOC, 3, GL_FLOAT, GL_FALSE, sizeof(EdgeVertex), (void *)offsetof(EdgeVertex, loc));
glVertexAttribPointer(ATTRIB_TAN, 3, GL_FLOAT, GL_FALSE, sizeof(EdgeVertex), (void *)offsetof(EdgeVertex, tan));
glDrawElements(GL_TRIANGLES, handle.size, GL_UNSIGNED_INT, NULL);
glDrawElementsBaseVertex(GL_TRIANGLES, 6 * 3 * edgeCount, GL_UNSIGNED_INT, (GLvoid*)(baseIndex * sizeof(uint32_t)), baseVertex);

glDisableVertexAttribArray(ATTRIB_POS);
glDisableVertexAttribArray(ATTRIB_LOC);
Expand All @@ -608,12 +622,6 @@ void EdgeRenderer::Draw(const EdgeRenderer::Handle &handle) {
shader.Disable();
}

void EdgeRenderer::Draw(const SEdgeList &edges) {
Handle handle = Add(edges, /*dynamic=*/true);
Draw(handle);
Remove(handle);
}

void EdgeRenderer::SetModelview(double *matrix) {
shader.SetUniformMatrix("modelview", matrix);
}
Expand Down Expand Up @@ -647,19 +655,29 @@ void OutlineRenderer::Init(const StippleAtlas *a) {
{ ATTRIB_NOR, "nor" }
}
);

glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
}

void OutlineRenderer::Clear() {
shader.Clear();
}

OutlineRenderer::Handle OutlineRenderer::Add(const SOutlineList &outlines, bool dynamic) {
Handle handle;
glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);

void OutlineRenderer::SetOutlineCount(uint32_t outlineCount) {
verticesIndex = 0;
indicesIndex = 0;

// 8 vertices per edge, and 18 indices per edge.
glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
glBufferData(GL_ARRAY_BUFFER, outlineCount * 8 * sizeof(OutlineVertex), nullptr, GL_DYNAMIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, outlineCount * 6 * 3 * sizeof(uint32_t), nullptr, GL_DYNAMIC_DRAW);
}

void OutlineRenderer::Add(const SOutlineList &outlines) {
OutlineVertex *vertices = new OutlineVertex[outlines.l.n * 8];
uint32_t *indices = new uint32_t[outlines.l.n * 6 * 3];
double phase = 0.0;
Expand Down Expand Up @@ -762,23 +780,26 @@ OutlineRenderer::Handle OutlineRenderer::Add(const SOutlineList &outlines, bool
phase = 0.0;
}
}
handle.size = curIndex;
GLenum mode = dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
glBufferData(GL_ARRAY_BUFFER, curVertex * sizeof(OutlineVertex), vertices, mode);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, curIndex * sizeof(uint32_t), indices, mode);

glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);

glBufferSubData(GL_ARRAY_BUFFER, verticesIndex * sizeof(OutlineVertex), curVertex * sizeof(OutlineVertex), vertices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indicesIndex * sizeof(uint32_t), curIndex * sizeof(uint32_t), indices);

verticesIndex += curVertex;
indicesIndex += curIndex;

delete []vertices;
delete []indices;
return handle;
}

void OutlineRenderer::Remove(const OutlineRenderer::Handle &handle) {
glDeleteBuffers(1, &handle.vertexBuffer);
glDeleteBuffers(1, &handle.indexBuffer);
}

void OutlineRenderer::Draw(const OutlineRenderer::Handle &handle, Canvas::DrawOutlinesAs mode) {
if(handle.size == 0) return;
void OutlineRenderer::Draw(const SOutlineList &outlines, Canvas::DrawOutlinesAs mode) {
if (outlines.l.n == 0) return;

uint32_t baseIndex = indicesIndex;
uint32_t baseVertex = verticesIndex;
this->Add(outlines);
uint32_t outlineCount = outlines.l.n;

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, atlas->GetTexture(pattern));
Expand Down Expand Up @@ -807,7 +828,7 @@ void OutlineRenderer::Draw(const OutlineRenderer::Handle &handle, Canvas::DrawOu
(void *)offsetof(OutlineVertex, nol));
glVertexAttribPointer(ATTRIB_NOR, 3, GL_FLOAT, GL_FALSE, sizeof(OutlineVertex),
(void *)offsetof(OutlineVertex, nor));
glDrawElements(GL_TRIANGLES, handle.size, GL_UNSIGNED_INT, NULL);
glDrawElementsBaseVertex(GL_TRIANGLES, 6 * 3 * outlineCount, GL_UNSIGNED_INT, (GLvoid*)(baseIndex * sizeof(uint32_t)), baseVertex);

glDisableVertexAttribArray(ATTRIB_POS);
glDisableVertexAttribArray(ATTRIB_LOC);
Expand All @@ -820,12 +841,6 @@ void OutlineRenderer::Draw(const OutlineRenderer::Handle &handle, Canvas::DrawOu
shader.Disable();
}

void OutlineRenderer::Draw(const SOutlineList &outlines, Canvas::DrawOutlinesAs drawAs) {
Handle handle = Add(outlines, /*dynamic=*/true);
Draw(handle, drawAs);
Remove(handle);
}

void OutlineRenderer::SetModelview(double *matrix) {
shader.SetUniformMatrix("modelview", matrix);
}
Expand Down Expand Up @@ -960,6 +975,9 @@ void IndexedMeshRenderer::Init() {
texShader.SetUniformTextureUnit("texture", 0);
texaShader.SetUniformTextureUnit("texture", 0);
selectedShader = &colShader;

glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);
}

void IndexedMeshRenderer::Clear() {
Expand All @@ -968,32 +986,39 @@ void IndexedMeshRenderer::Clear() {
colShader.Clear();
pointShader.Clear();
}

IndexedMeshRenderer::Handle IndexedMeshRenderer::Add(const SIndexedMesh &m, bool dynamic) {
Handle handle;
glGenBuffers(1, &handle.vertexBuffer);
glGenBuffers(1, &handle.indexBuffer);

GLenum mode = dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;

void IndexedMeshRenderer::SetCounts(uint32_t vertices, uint32_t indices) {
verticesIndex = 0;
indicesIndex = 0;

glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, m.vertices.size() * sizeof(SIndexedMesh::Vertex),
m.vertices.data(), mode);

glBufferData(GL_ARRAY_BUFFER, vertices * sizeof(SIndexedMesh::Vertex),
nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m.indices.size() * sizeof(uint32_t),
m.indices.data(), mode);
handle.size = m.indices.size();
return handle;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * sizeof(uint32_t),
nullptr, GL_DYNAMIC_DRAW);
}

void IndexedMeshRenderer::Remove(const IndexedMeshRenderer::Handle &handle) {
glDeleteBuffers(1, &handle.vertexBuffer);
glDeleteBuffers(1, &handle.indexBuffer);
void IndexedMeshRenderer::Add(const SIndexedMesh &m) {
glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
glBufferSubData(GL_ARRAY_BUFFER, verticesIndex, m.vertices.size() * sizeof(SIndexedMesh::Vertex),
m.vertices.data());
verticesIndex += m.vertices.size();

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indicesIndex, m.indices.size() * sizeof(uint32_t),
m.indices.data());
indicesIndex += m.indices.size();
}

void IndexedMeshRenderer::Draw(const IndexedMeshRenderer::Handle &handle) {
if(handle.size == 0) return;

void IndexedMeshRenderer::Draw(const SIndexedMesh &mesh) {
if (mesh.indices.size() == 0) return;

uint32_t baseVertex = verticesIndex;
uint32_t baseIndex = indicesIndex;

selectedShader->Enable();

glBindBuffer(GL_ARRAY_BUFFER, handle.vertexBuffer);
Expand All @@ -1007,7 +1032,7 @@ void IndexedMeshRenderer::Draw(const IndexedMeshRenderer::Handle &handle) {
}

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle.indexBuffer);
glDrawElements(GL_TRIANGLES, handle.size, GL_UNSIGNED_INT, NULL);
glDrawElementsBaseVertex(GL_TRIANGLES, mesh.indices.size(), GL_UNSIGNED_INT, (GLvoid*)(baseIndex * sizeof(uint32_t)), baseVertex);

glDisableVertexAttribArray(ATTRIB_POS);
if(NeedsTexture()) glDisableVertexAttribArray(ATTRIB_TEX);
Expand All @@ -1018,12 +1043,6 @@ void IndexedMeshRenderer::Draw(const IndexedMeshRenderer::Handle &handle) {
selectedShader->Disable();
}

void IndexedMeshRenderer::Draw(const SIndexedMesh &mesh) {
Handle handle = Add(mesh, /*dynamic=*/true) ;
Draw(handle);
Remove(handle);
}

bool IndexedMeshRenderer::NeedsTexture() const {
return selectedShader == &texShader ||
selectedShader == &texaShader ||
Expand Down

0 comments on commit 42f187a

Please sign in to comment.