Add flag to make Canvas depth texture readable;

- DepthFormat is now just TextureFormat.
- Canvas:getDepthTexture instead of Canvas:getDepthFormat.
This commit is contained in:
bjorn 2018-09-27 18:34:43 -07:00
parent 56fa853b09
commit cfac548e7b
8 changed files with 77 additions and 46 deletions

View File

@ -80,7 +80,6 @@ extern const char* CompareModes[];
extern const char* ControllerAxes[];
extern const char* ControllerButtons[];
extern const char* ControllerHands[];
extern const char* DepthFormats[];
extern const char* DrawModes[];
extern const char* EventTypes[];
extern const char* FilterModes[];

View File

@ -63,13 +63,6 @@ const char* CompareModes[] = {
NULL
};
const char* DepthFormats[] = {
[DEPTH_D16] = "d16",
[DEPTH_D32F] = "d32f",
[DEPTH_D24S8] = "d24s8",
NULL
};
const char* DrawModes[] = {
[DRAW_MODE_FILL] = "fill",
[DRAW_MODE_LINE] = "line",
@ -154,6 +147,9 @@ const char* TextureFormats[] = {
[FORMAT_RGB5A1] = "rgb5a1",
[FORMAT_RGB10A2] = "rgb5a2",
[FORMAT_RG11B10F] = "rg11b10f",
[FORMAT_D16] = "d16",
[FORMAT_D32F] = "d32f",
[FORMAT_D24S8] = "d24s8",
[FORMAT_DXT1] = "dxt1",
[FORMAT_DXT3] = "dxt3",
[FORMAT_DXT5] = "dxt5",
@ -950,7 +946,13 @@ int l_lovrGraphicsNewCanvas(lua_State* L) {
index = 3;
}
CanvasFlags flags = { .depth = DEPTH_D16, .stereo = true, .msaa = 0, .mipmaps = true };
CanvasFlags flags = {
.depth = { .enabled = true, .readable = false, .format = FORMAT_D16 },
.stereo = true,
.msaa = 0,
.mipmaps = true
};
TextureFormat format = FORMAT_RGBA;
bool anonymous = attachmentCount == 0;
@ -958,8 +960,18 @@ int l_lovrGraphicsNewCanvas(lua_State* L) {
lua_getfield(L, index, "depth");
switch (lua_type(L, -1)) {
case LUA_TNIL: break;
case LUA_TBOOLEAN: flags.depth = lua_toboolean(L, -1) ? DEPTH_D16 : DEPTH_NONE; break;
default: flags.depth = luaL_checkoption(L, -1, NULL, DepthFormats);
case LUA_TBOOLEAN: flags.depth.enabled = lua_toboolean(L, -1); break;
case LUA_TSTRING: flags.depth.format = luaL_checkoption(L, -1, NULL, TextureFormats); break;
case LUA_TTABLE:
lua_getfield(L, -1, "readable");
flags.depth.readable = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "format");
flags.depth.format = luaL_checkoption(L, -1, NULL, TextureFormats);
lua_pop(L, 1);
break;
default: lovrThrow("Expected boolean, string, or table for Canvas depth flag");
}
lua_pop(L, 1);

View File

@ -121,10 +121,10 @@ int l_lovrCanvasGetDimensions(lua_State* L) {
return 2;
}
int l_lovrCanvasGetDepthFormat(lua_State* L) {
int l_lovrCanvasGetDepthTexture(lua_State* L) {
Canvas* canvas = luax_checktype(L, 1, Canvas);
DepthFormat format = lovrCanvasGetDepthFormat(canvas);
lua_pushstring(L, DepthFormats[format]);
Texture* texture = lovrCanvasGetDepthTexture(canvas);
luax_pushobject(L, texture);
return 1;
}
@ -150,7 +150,7 @@ const luaL_Reg lovrCanvas[] = {
{ "getWidth", l_lovrCanvasGetWidth },
{ "getHeight", l_lovrCanvasGetHeight },
{ "getDimensions", l_lovrCanvasGetDimensions },
{ "getDepthFormat", l_lovrCanvasGetDepthFormat },
{ "getDepthTexture", l_lovrCanvasGetDepthTexture },
{ "getMSAA", l_lovrCanvasGetMSAA },
{ "isStereo", l_lovrCanvasIsStereo },
{ NULL, NULL }

View File

@ -132,6 +132,9 @@ TextureData* lovrTextureDataCreate(int width, int height, uint8_t value, Texture
case FORMAT_RGB5A1: pixelSize = 2; break;
case FORMAT_RGB10A2: pixelSize = 4; break;
case FORMAT_RG11B10F: pixelSize = 4; break;
case FORMAT_D16: pixelSize = 2; break;
case FORMAT_D32F: pixelSize = 4; break;
case FORMAT_D24S8: pixelSize = 4; break;
case FORMAT_DXT1:
case FORMAT_DXT3:

View File

@ -19,6 +19,9 @@ typedef enum {
FORMAT_RGB5A1,
FORMAT_RGB10A2,
FORMAT_RG11B10F,
FORMAT_D16,
FORMAT_D32F,
FORMAT_D24S8,
FORMAT_DXT1,
FORMAT_DXT3,
FORMAT_DXT5

View File

@ -4,13 +4,6 @@
#define MAX_CANVAS_ATTACHMENTS 4
typedef enum {
DEPTH_D16,
DEPTH_D32F,
DEPTH_D24S8,
DEPTH_NONE
} DepthFormat;
typedef struct {
Texture* texture;
int slice;
@ -18,7 +11,11 @@ typedef struct {
} Attachment;
typedef struct {
DepthFormat depth;
struct {
bool enabled;
bool readable;
TextureFormat format;
} depth;
bool stereo;
int msaa;
bool mipmaps;
@ -36,5 +33,5 @@ bool lovrCanvasIsStereo(Canvas* canvas);
int lovrCanvasGetWidth(Canvas* canvas);
int lovrCanvasGetHeight(Canvas* canvas);
int lovrCanvasGetMSAA(Canvas* canvas);
DepthFormat lovrCanvasGetDepthFormat(Canvas* canvas);
Texture* lovrCanvasGetDepthTexture(Canvas* canvas);
TextureData* lovrCanvasNewTextureData(Canvas* canvas, int index);

View File

@ -128,9 +128,10 @@ struct Canvas {
int height;
CanvasFlags flags;
uint32_t framebuffer;
uint32_t depthBuffer;
uint32_t resolveBuffer;
uint32_t depthBuffer;
Attachment attachments[MAX_CANVAS_ATTACHMENTS];
Attachment depth;
int count;
bool needsAttach;
bool needsResolve;
@ -224,6 +225,9 @@ static GLenum convertTextureFormat(TextureFormat format) {
case FORMAT_RGB5A1: return GL_RGBA;
case FORMAT_RGB10A2: return GL_RGBA;
case FORMAT_RG11B10F: return GL_RGB;
case FORMAT_D16: return GL_DEPTH_COMPONENT;
case FORMAT_D32F: return GL_DEPTH_COMPONENT;
case FORMAT_D24S8: return GL_DEPTH_STENCIL;
case FORMAT_DXT1: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
case FORMAT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
case FORMAT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
@ -244,6 +248,9 @@ static GLenum convertTextureFormatInternal(TextureFormat format, bool srgb) {
case FORMAT_RGB5A1: return GL_RGB5_A1;
case FORMAT_RGB10A2: return GL_RGB10_A2;
case FORMAT_RG11B10F: return GL_R11F_G11F_B10F;
case FORMAT_D16: return GL_DEPTH_COMPONENT16;
case FORMAT_D32F: return GL_DEPTH_COMPONENT32F;
case FORMAT_D24S8: return GL_DEPTH24_STENCIL8;
case FORMAT_DXT1: return srgb ? GL_COMPRESSED_SRGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
case FORMAT_DXT3: return srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
case FORMAT_DXT5: return srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
@ -264,6 +271,9 @@ static GLenum convertTextureFormatType(TextureFormat format) {
case FORMAT_RGB5A1: return GL_UNSIGNED_SHORT_5_5_5_1;
case FORMAT_RGB10A2: return GL_UNSIGNED_INT_2_10_10_10_REV;
case FORMAT_RG11B10F: return GL_UNSIGNED_INT_10F_11F_11F_REV;
case FORMAT_D16: return GL_UNSIGNED_SHORT;
case FORMAT_D32F: return GL_UNSIGNED_INT;
case FORMAT_D24S8: return GL_UNSIGNED_INT_24_8;
case FORMAT_DXT1:
case FORMAT_DXT3:
case FORMAT_DXT5:
@ -272,15 +282,6 @@ static GLenum convertTextureFormatType(TextureFormat format) {
}
}
static GLenum convertDepthFormat(DepthFormat format) {
switch (format) {
case DEPTH_D16: return GL_DEPTH_COMPONENT16; break;
case DEPTH_D32F: return GL_DEPTH_COMPONENT32F; break;
case DEPTH_D24S8: return GL_DEPTH24_STENCIL8; break;
default: lovrThrow("Unreachable"); return GL_DEPTH_COMPONENT16;
}
}
static bool isTextureFormatCompressed(TextureFormat format) {
switch (format) {
case FORMAT_DXT1: case FORMAT_DXT3: case FORMAT_DXT5: return true;
@ -288,6 +289,13 @@ static bool isTextureFormatCompressed(TextureFormat format) {
}
}
static bool isTextureFormatDepth(TextureFormat format) {
switch (format) {
case FORMAT_D16: case FORMAT_D32F: case FORMAT_D24S8: return true;
default: return false;
}
}
static GLenum convertBufferUsage(BufferUsage usage) {
switch (usage) {
case USAGE_STATIC: return GL_STATIC_DRAW;
@ -1201,13 +1209,20 @@ Canvas* lovrCanvasCreate(int width, int height, CanvasFlags flags) {
glGenFramebuffers(1, &canvas->framebuffer);
lovrGpuBindFramebuffer(canvas->framebuffer);
if (flags.depth != DEPTH_NONE) {
GLenum attachment = flags.depth == DEPTH_D24S8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
GLenum format = convertDepthFormat(flags.depth);
glGenRenderbuffers(1, &canvas->depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, canvas->depthBuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, canvas->flags.msaa, format, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, canvas->depthBuffer);
if (flags.depth.enabled) {
lovrAssert(isTextureFormatDepth(flags.depth.format), "Canvas depth buffer can't use a color TextureFormat");
GLenum attachment = flags.depth.format == FORMAT_D24S8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
if (flags.depth.readable) {
canvas->depth.texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, false, flags.mipmaps, flags.msaa);
lovrTextureAllocate(canvas->depth.texture, width, height, 1, flags.depth.format);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, canvas->depth.texture->id, 0);
} else {
GLenum format = convertTextureFormatInternal(flags.depth.format, false);
glGenRenderbuffers(1, &canvas->depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, canvas->depthBuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, canvas->flags.msaa, format, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, canvas->depthBuffer);
}
}
if (flags.msaa) {
@ -1225,6 +1240,7 @@ void lovrCanvasDestroy(void* ref) {
for (int i = 0; i < canvas->count; i++) {
lovrRelease(canvas->attachments[i].texture);
}
lovrRelease(canvas->depth.texture);
free(ref);
}
@ -1245,8 +1261,9 @@ void lovrCanvasSetAttachments(Canvas* canvas, Attachment* attachments, int count
Texture* texture = attachments[i].texture;
int width = lovrTextureGetWidth(texture, attachments[i].level);
int height = lovrTextureGetHeight(texture, attachments[i].level);
lovrAssert(!canvas->depthBuffer || width == canvas->width, "Texture width of %d does not match Canvas width (%d)", width, canvas->width);
lovrAssert(!canvas->depthBuffer || height == canvas->height, "Texture height of %d does not match Canvas height (%d)", height, canvas->height);
bool hasDepth = canvas->flags.depth.enabled;
lovrAssert(!hasDepth || width == canvas->width, "Texture width of %d does not match Canvas width (%d)", width, canvas->width);
lovrAssert(!hasDepth || height == canvas->height, "Texture height of %d does not match Canvas height (%d)", height, canvas->height);
lovrAssert(texture->msaa == canvas->flags.msaa, "Texture MSAA does not match Canvas MSAA");
lovrRetain(texture);
}
@ -1377,8 +1394,8 @@ int lovrCanvasGetMSAA(Canvas* canvas) {
return canvas->flags.msaa;
}
DepthFormat lovrCanvasGetDepthFormat(Canvas* canvas) {
return canvas->flags.depth;
Texture* lovrCanvasGetDepthTexture(Canvas* canvas) {
return canvas->depth.texture;
}
TextureData* lovrCanvasNewTextureData(Canvas* canvas, int index) {

View File

@ -227,7 +227,7 @@ static void ensureCanvas() {
uint32_t width, height;
state.system->GetRecommendedRenderTargetSize(&width, &height);
CanvasFlags flags = { .depth = DEPTH_D24S8, .stereo = true, .msaa = state.msaa };
CanvasFlags flags = { .depth = { true, false, FORMAT_D24S8 }, .stereo = true, .msaa = state.msaa };
state.canvas = lovrCanvasCreate(width * 2, height, flags);
Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, false, state.msaa);
lovrTextureAllocate(texture, width * 2, height, 1, FORMAT_RGBA);