Permalink
Browse files

Performance deutlich verbessert durch recycling von einmal erstellen …

…FBOs.
  • Loading branch information...
1 parent baf9d1f commit d9e0d0bc391e96a4f23fa300c3a97e77f5070428 @dividuum committed Feb 15, 2012
Showing with 1,867 additions and 44 deletions.
  1. +5 −2 Makefile
  2. +86 −0 framebuffer.c
  3. +7 −0 framebuffer.h
  4. +16 −8 image.c
  5. +10 −33 main.c
  6. +20 −0 misc.c
  7. +7 −0 misc.h
  8. +961 −0 tlsf.c
  9. +52 −0 tlsf.h
  10. +180 −0 tlsfbits.h
  11. +522 −0 utlist.h
  12. +1 −1 video.c
View
@@ -8,7 +8,7 @@ all: gpn-info
main.o: main.c kernel.h
-gpn-info: main.o image.o font.o video.o tlsf.o
+gpn-info: main.o image.o font.o video.o tlsf.o framebuffer.o misc.o
$(CC) -o $@ $^ $(LDFLAGS)
bin2c: bin2c.c
@@ -18,7 +18,10 @@ kernel.h: kernel.lua bin2c $(LUAC)
luac -p $<
./bin2c $* < $< > $@
-.PHONY: clean
+performance: performance.csv
+ gnuplot -e "plot './performance.csv' using 1:8 with lines;pause mouse key"
+
+.PHONY: clean performance
clean:
rm -f *.o gpn-info kernel.h
View
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <GL/glew.h>
+#include <GL/gl.h>
+
+#include "utlist.h"
+#include "misc.h"
+
+#define MAX_CACHED 20
+
+typedef struct framebuffer {
+ int fbo;
+ int tex;
+ int width;
+ int height;
+ struct framebuffer *prev;
+ struct framebuffer *next;
+} framebuffer_t;
+
+static framebuffer_t *framebuffers = NULL;
+static int num_framebuffers = 0;
+
+void free_framebuffer(framebuffer_t *framebuffer) {
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->fbo);
+ glBindTexture(GL_TEXTURE_2D, framebuffer->tex);
+ DL_DELETE(framebuffers, framebuffer);
+ free(framebuffer);
+ num_framebuffers--;
+}
+
+void make_framebuffer(int width, int height, int *tex, int *fbo) {
+ framebuffer_t *framebuffer, *tmp;
+
+ fprintf(stderr, "requesting framebuffer: %dx%d\n", width, height);
+ fprintf(stderr, "got %d %p framebuffers\n", num_framebuffers, framebuffers);
+
+ DL_FOREACH_SAFE(framebuffers, framebuffer, tmp) {
+ fprintf(stderr, "checking %dx%d %d %d\n", framebuffer->width, framebuffer->height,
+ framebuffer->tex, framebuffer->fbo);
+
+ // Same size?
+ if (framebuffer->height == height && framebuffer->width == width) {
+ fprintf(stderr, "found reusable framebuffer\n");
+ *tex = framebuffer->tex;
+ *fbo = framebuffer->fbo;
+ free_framebuffer(framebuffer);
+ return;
+ }
+ }
+ fprintf(stderr, "nope\n");
+
+ glGenFramebuffers(1, fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
+
+ glGenTextures(1, tex);
+ glBindTexture(GL_TEXTURE_2D, *tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, NULL);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0);
+ assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+int recycle_framebuffer(int width, int height, int tex, int fbo) {
+ framebuffer_t *framebuffer = xmalloc(sizeof(framebuffer_t));
+ framebuffer->width = width;
+ framebuffer->height = height;
+ framebuffer->tex = tex;
+ framebuffer->fbo = fbo;
+
+ fprintf(stderr, "added recyleable framebuffer %dx%d %d %d\n", framebuffer->width, framebuffer->height,
+ framebuffer->tex, framebuffer->fbo);
+
+ DL_PREPEND(framebuffers, framebuffer);
+ num_framebuffers++;
+
+ if (num_framebuffers > MAX_CACHED) {
+ fprintf(stderr, "too full\n");
+ free_framebuffer(framebuffers);
+ }
+}
View
@@ -0,0 +1,7 @@
+#ifndef TEXTURE_H
+#define TEXTURE_H
+
+int make_framebuffer(int width, int height, int *tex, int *fbo);
+int recycle_framebuffer(int width, int height, int tex, int fbo);
+
+#endif
View
@@ -9,6 +9,8 @@
#include <png.h>
#include <jpeglib.h>
+#include "framebuffer.h"
+
#define IMAGE "image"
typedef struct {
@@ -115,15 +117,14 @@ static int load_jpeg(const char *filename, int *width, int *height) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
#if 0
- glTexImage2D (GL_TEXTURE_2D, 0, jpeg_tex->internalFormat,
- jpeg_tex->width, jpeg_tex->height, 0, jpeg_tex->format,
- GL_UNSIGNED_BYTE, jpeg_tex->texels);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat,
+ *width, *height, 0, format,
+ GL_UNSIGNED_BYTE, pixels);
#else
gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat,
*width, *height, format, GL_UNSIGNED_BYTE, pixels);
#endif
-
/* OpenGL has its own copy of texture data */
free(pixels);
@@ -307,10 +308,17 @@ static const luaL_reg image_methods[] = {
static int image_gc(lua_State *L) {
image_t *image = to_image(L, 1);
- // fprintf(stderr, "discarding tex: %d\n", image->tex, image->fbo);
- glDeleteTextures(1, &image->tex);
- if (image->fbo)
- glDeleteFramebuffers(1, &image->fbo);
+ if (image->fbo) {
+ // If images has attached Framebuffer, put the
+ // texture and framebuffer into the recycler.
+ // Allocations for new framebuffers can then
+ // reuse these => Better performance.
+ recycle_framebuffer(image->width, image->height,
+ image->tex, image->fbo);
+ } else {
+ // No Framebuffer? Just remove the texture.
+ glDeleteTextures(1, &image->tex);
+ }
return 0;
}
View
@@ -29,14 +29,16 @@
#include "uthash.h"
#include "tlsf.h"
+#include "misc.h"
#include "kernel.h"
#include "image.h"
#include "video.h"
#include "font.h"
+#include "framebuffer.h"
#define MAX_CODE_SIZE 16384 // byte
#define MAX_MEM 200000 // KB
-#define MIN_DELTA 25 // ms
+#define MIN_DELTA 0 // ms
#define MAX_DELTA 2000 // ms
#define MAX_RUNAWAY_TIME 5 // sec
@@ -101,22 +103,6 @@ static node_t root;
static int inotify_fd;
static double now;
-static void die(const char *fmt, ...) {
- // va_list ap;
- // va_start(ap, fmt);
- // printf("CRITICAL ERROR: ");
- // vprintf(fmt, ap);
- // printf("\n");
- // va_end(ap);
- exit(1);
-}
-
-static void *xmalloc(size_t size) {
- void *ptr = calloc(1, size);
- if (!ptr) die("cannot malloc");
- return ptr;
-}
-
/*======= Lua Sandboxing =======*/
static void *lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
@@ -261,7 +247,7 @@ static void node_render_self(node_t *node, int width, int height) {
lua_node_enter(node, 3);
}
-static int node_render_in_state(lua_State *L, node_t *node) {
+static int node_render_to_image(lua_State *L, node_t *node) {
/* Neuen Framebuffer und zugehoerige Texture anlegen.
* Dort wird dann das Child reingerendert. Das Ergebnis
* ist ein Image.
@@ -280,24 +266,15 @@ static int node_render_in_state(lua_State *L, node_t *node) {
return 0;
}
+
print_render_state();
int prev_fbo, fbo, tex;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-
- glGenTextures(1, &tex);
- glBindTexture(GL_TEXTURE_2D, tex);
- // fprintf(stderr, "%d %d\n", fbo, tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, node->width, node->height, 0, GL_RGBA, GL_INT, NULL);
+ make_framebuffer(node->width, node->height, &tex, &fbo);
+ fprintf(stderr, "TEXTURE ALLOC: %d %d\n", tex, fbo);
+ print_render_state();
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
- assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindTexture(GL_TEXTURE_2D, 0);
/* Render into new Texture */
@@ -335,7 +312,7 @@ static int node_render_in_state(lua_State *L, node_t *node) {
static int luaRenderSelf(lua_State *L) {
node_t *node = lua_touserdata(L, lua_upvalueindex(1));
- return node_render_in_state(L, node);
+ return node_render_to_image(L, node);
}
static int luaRenderChild(lua_State *L) {
@@ -346,7 +323,7 @@ static int luaRenderChild(lua_State *L) {
HASH_FIND(by_name, node->childs, name, strlen(name), child);
if (!child)
luaL_error(L, "child not found");
- return node_render_in_state(L, child);
+ return node_render_to_image(L, child);
}
static int luaSendChild(lua_State *L) {
View
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+void die(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ printf("CRITICAL ERROR: ");
+ vprintf(fmt, ap);
+ printf("\n");
+ va_end(ap);
+ exit(1);
+}
+
+void *xmalloc(size_t size) {
+ void *ptr = calloc(1, size);
+ if (!ptr) die("cannot malloc");
+ return ptr;
+}
+
View
@@ -0,0 +1,7 @@
+#ifndef MISC_H
+#define MISC_H
+
+void die(const char *fmt, ...);
+void *xmalloc(size_t size);
+
+#endif
Oops, something went wrong.

0 comments on commit d9e0d0b

Please sign in to comment.