Add defaultCanvas;

Having a normal Canvas object that represents the backbuffer reduces
some indirection where we have to last-minute check if a Canvas is
set.  It also means that all of the draw-related info that was _sometimes_
on the Canvas is now _always_ on the Canvas, which reduces the amount
of redundant information we need to provide for a draw call.

There may be some issues related to changing the width/height/stereo
of the default Canvas.
This commit is contained in:
bjorn 2019-06-27 15:36:51 -07:00
parent 111872904a
commit 7e067da8e7
3 changed files with 23 additions and 16 deletions

View File

@ -94,6 +94,7 @@ static struct {
int width;
int height;
Camera camera;
Canvas* defaultCanvas;
Shader* defaultShaders[MAX_DEFAULT_SHADERS];
Material* defaultMaterial;
Font* defaultFont;
@ -158,6 +159,8 @@ static void onCloseWindow(void) {
static void onResizeWindow(int width, int height) {
state.width = width;
state.height = height;
state.defaultCanvas->width = width;
state.defaultCanvas->height = height;
}
static void* lovrGraphicsMapBuffer(StreamType type, uint32_t count) {
@ -194,6 +197,7 @@ void lovrGraphicsDestroy() {
lovrRelease(Buffer, state.identityBuffer);
lovrRelease(Material, state.defaultMaterial);
lovrRelease(Font, state.defaultFont);
lovrRelease(Canvas, state.defaultCanvas);
lovrGpuDestroy();
memset(&state, 0, sizeof(state));
}
@ -212,6 +216,8 @@ void lovrGraphicsCreateWindow(WindowFlags* flags) {
lovrPlatformGetFramebufferSize(&state.width, &state.height);
lovrGpuInit(lovrGetProcAddress);
state.defaultCanvas = lovrCanvasCreateFromHandle(state.width, state.height, (CanvasFlags) { .stereo = false }, 0, 0, 0, 1, true);
for (int i = 0; i < MAX_STREAMS; i++) {
state.buffers[i] = lovrBufferCreate(bufferCount[i] * bufferStride[i], NULL, bufferType[i], USAGE_STREAM, false);
}
@ -281,8 +287,15 @@ void lovrGraphicsSetCamera(Camera* camera, bool clear) {
mat4_identity(state.camera.viewMatrix[1]);
mat4_perspective(state.camera.projection[0], .01f, 100.f, 67.f * (float) M_PI / 180.f, (float) state.width / state.height);
mat4_perspective(state.camera.projection[1], .01f, 100.f, 67.f * (float) M_PI / 180.f, (float) state.width / state.height);
state.camera.canvas = state.defaultCanvas;
state.camera.canvas->flags.stereo = false;
} else {
state.camera = *camera;
if (!state.camera.canvas) {
state.camera.canvas = state.defaultCanvas;
state.camera.canvas->flags.stereo = camera->stereo;
}
}
if (clear) {
@ -724,10 +737,7 @@ void lovrGraphicsFlush() {
.drawMode = batch->drawMode,
.instances = instances,
.rangeStart = rangeStart,
.rangeCount = rangeCount,
.width = batch->canvas ? lovrCanvasGetWidth(batch->canvas) : state.width,
.height = batch->canvas ? lovrCanvasGetHeight(batch->canvas) : state.height,
.stereo = batch->canvas ? lovrCanvasIsStereo(batch->canvas) : state.camera.stereo
.rangeCount = rangeCount
});
}
}

View File

@ -215,9 +215,6 @@ typedef struct {
uint32_t instances;
uint32_t rangeStart;
uint32_t rangeCount;
uint32_t width : 15;
uint32_t height : 15;
bool stereo : 1;
} DrawCommand;
void lovrGpuInit(getProcAddressProc getProcAddress);

View File

@ -614,14 +614,14 @@ static void lovrGpuBindMesh(Mesh* mesh, Shader* shader, int baseDivisor) {
}
static void lovrGpuBindCanvas(Canvas* canvas, bool willDraw) {
if (canvas) {
lovrGpuBindFramebuffer(canvas->framebuffer);
canvas->needsResolve = willDraw;
} else {
lovrGpuBindFramebuffer(0);
lovrGpuBindFramebuffer(canvas->framebuffer);
if (canvas->framebuffer == 0) {
return;
}
canvas->needsResolve = willDraw;
if (!canvas->needsAttach) {
return;
}
@ -1135,7 +1135,7 @@ void lovrGpuDiscard(Canvas* canvas, bool color, bool depth, bool stencil) {
int count = 0;
if (color) {
int n = canvas ? canvas->attachmentCount : 1;
int n = MAX(canvas->attachmentCount, 1);
for (int i = 0; i < n; i++) {
attachments[count++] = GL_COLOR_ATTACHMENT0 + i;
}
@ -1155,14 +1155,14 @@ void lovrGpuDiscard(Canvas* canvas, bool color, bool depth, bool stencil) {
void lovrGpuDraw(DrawCommand* draw) {
lovrAssert(state.singlepass != MULTIVIEW || draw->shader->multiview == draw->canvas->flags.stereo, "Shader and Canvas multiview settings must match!");
uint32_t viewportCount = (draw->stereo && state.singlepass != MULTIVIEW) ? 2 : 1;
uint32_t viewportCount = (draw->canvas->flags.stereo && state.singlepass != MULTIVIEW) ? 2 : 1;
uint32_t drawCount = state.singlepass == NONE ? viewportCount : 1;
uint32_t instanceMultiplier = state.singlepass == INSTANCED_STEREO ? viewportCount : 1;
uint32_t viewportsPerDraw = instanceMultiplier;
uint32_t instances = MAX(draw->instances, 1) * instanceMultiplier;
float w = state.singlepass == MULTIVIEW ? draw->width : draw->width / (float) viewportCount;
float h = draw->height;
float w = state.singlepass == MULTIVIEW ? draw->canvas->width : draw->canvas->width / (float) viewportCount;
float h = draw->canvas->height;
float viewports[2][4] = { { 0.f, 0.f, w, h }, { w, 0.f, w, h } };
lovrShaderSetInts(draw->shader, "lovrViewportCount", &(int) { viewportCount }, 0, 1);