Rework automipmapping;

The sync was totally wrong here.  It's a bit better now.  However there
are some general sync issues that need to be fixed.  Basically a Pass
that does reads and writes or multiple writes doesn't work properly, for
various reasons.  I think sync needs to be split into 2 phases -- first
process all the reads and merge barrier bits into the barrier of the
last writer, then process all the writes and set 'final' resource state
for stuff in the pass.  Due to branch prediction it may be better to
have 2 separate lists -- one for reads and one for writes.  And I'm not
100% sure on how to reconcile a Pass that is doing reads and writes to
the same resource yet, still thinking about it.
This commit is contained in:
bjorn 2022-08-08 21:26:07 -07:00
parent 6d6e79e704
commit 0436a5deae
1 changed files with 25 additions and 27 deletions

View File

@ -844,22 +844,28 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
Canvas* canvas = &pass->info.canvas;
if (canvas->mipmap) {
for (uint32_t j = 0; j < COUNTOF(canvas->textures) && canvas->textures[j]; j++) {
if (canvas->textures[j]->info.mipmaps > 1) {
barriers[i].prev |= GPU_PHASE_COLOR;
barriers[i].next |= GPU_PHASE_TRANSFER;
barriers[i].flush |= GPU_CACHE_COLOR_WRITE;
barriers[i].clear |= GPU_CACHE_TRANSFER_READ;
mipmapTexture(pass->stream, canvas->textures[j], 0, ~0u);
bool depth = pass->depth && pass->depth->info.mipmaps > 1;
gpu_barrier barrier = {
.prev = GPU_PHASE_COLOR | (depth ? GPU_PHASE_DEPTH_LATE : 0),
.next = GPU_PHASE_TRANSFER,
.flush = GPU_CACHE_COLOR_WRITE | (depth ? GPU_CACHE_DEPTH_WRITE : 0),
.clear = GPU_CACHE_TRANSFER_READ
};
// Wait for rendering to finish before mipmapping
gpu_sync(pass->stream, &barrier, 1);
for (uint32_t t = 0; t < canvas->count; t++) {
if (pass->color[t]->info.mipmaps > 1) {
mipmapTexture(pass->stream, pass->color[t], 0, ~0u);
trackTexture(pass, pass->color[t], GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_WRITE);
}
}
if (canvas->depth.texture && canvas->depth.texture->info.mipmaps > 1) {
barriers[i].prev |= GPU_PHASE_DEPTH_LATE;
barriers[i].next |= GPU_PHASE_TRANSFER;
barriers[i].flush |= GPU_CACHE_DEPTH_WRITE;
barriers[i].clear |= GPU_CACHE_TRANSFER_READ;
mipmapTexture(pass->stream, canvas->depth.texture, 0, ~0u);
if (depth) {
mipmapTexture(pass->stream, pass->depth, 0, ~0u);
trackTexture(pass, pass->depth, GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_WRITE);
}
}
break;
@ -902,7 +908,7 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
// finish. In between, the 'flush' cache is flushed and the 'clear' cache is cleared.
gpu_barrier* barrier = &barriers[sync->lastWriteIndex];
// Only the first write in a pass is considered for a barrier (and there's no intra-pass sync)
// Only the first write in a pass is used for inter-stream barriers
if (sync->lastWriteIndex == i + 1) {
continue;
}
@ -3469,22 +3475,14 @@ void lovrPassReset(Pass* pass) {
memcpy(pass->target.color[0].clear, state.background, 4 * sizeof(float));
}
if (canvas->mipmap) {
trackTexture(pass, pass->color[i], GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_WRITE);
} else {
gpu_cache cache = GPU_CACHE_COLOR_WRITE | (canvas->loads[i] == LOAD_KEEP ? GPU_CACHE_COLOR_READ : 0);
trackTexture(pass, pass->color[i], GPU_PHASE_COLOR, cache);
}
gpu_cache cache = GPU_CACHE_COLOR_WRITE | (canvas->loads[i] == LOAD_KEEP ? GPU_CACHE_COLOR_READ : 0);
trackTexture(pass, pass->color[i], GPU_PHASE_COLOR, cache);
}
if (pass->depth) {
if (canvas->mipmap && pass->depth->info.mipmaps > 1) {
trackTexture(pass, pass->depth, GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_WRITE);
} else {
gpu_phase phase = canvas->depth.load == LOAD_KEEP ? GPU_PHASE_DEPTH_EARLY : GPU_PHASE_DEPTH_LATE;
gpu_cache cache = GPU_CACHE_DEPTH_WRITE | (canvas->depth.load == LOAD_KEEP ? GPU_CACHE_DEPTH_READ : 0);
trackTexture(pass, pass->depth, phase, cache);
}
gpu_phase phase = canvas->depth.load == LOAD_KEEP ? GPU_PHASE_DEPTH_EARLY : GPU_PHASE_DEPTH_LATE;
gpu_cache cache = GPU_CACHE_DEPTH_WRITE | (canvas->depth.load == LOAD_KEEP ? GPU_CACHE_DEPTH_READ : 0);
trackTexture(pass, pass->depth, phase, cache);
}
gpu_render_begin(pass->stream, &pass->target);