Fix automipmap synchronization;

This commit is contained in:
bjorn 2022-08-23 18:49:11 -07:00
parent e4024d82c4
commit 1c48578e95
3 changed files with 29 additions and 14 deletions

View File

@ -547,7 +547,8 @@ typedef enum {
GPU_PHASE_DEPTH_EARLY = (1 << 6),
GPU_PHASE_DEPTH_LATE = (1 << 7),
GPU_PHASE_COLOR = (1 << 8),
GPU_PHASE_TRANSFER = (1 << 9)
GPU_PHASE_TRANSFER = (1 << 9),
GPU_PHASE_ALL = (1 << 10)
} gpu_phase;
typedef enum {
@ -564,8 +565,8 @@ typedef enum {
GPU_CACHE_COLOR_WRITE = (1 << 10),
GPU_CACHE_TRANSFER_READ = (1 << 11),
GPU_CACHE_TRANSFER_WRITE = (1 << 12),
GPU_CACHE_WRITE = GPU_CACHE_STORAGE_WRITE | GPU_CACHE_DEPTH_WRITE | GPU_CACHE_COLOR_WRITE | GPU_CACHE_TRANSFER_WRITE,
GPU_CACHE_READ = ~GPU_CACHE_WRITE
GPU_CACHE_WRITE_MASK = GPU_CACHE_STORAGE_WRITE | GPU_CACHE_DEPTH_WRITE | GPU_CACHE_COLOR_WRITE | GPU_CACHE_TRANSFER_WRITE,
GPU_CACHE_READ_MASK = ~GPU_CACHE_WRITE_MASK
} gpu_cache;
typedef struct {

View File

@ -194,7 +194,7 @@ static void expunge(void);
static VkFramebuffer getCachedFramebuffer(VkRenderPass pass, VkImageView images[9], uint32_t imageCount, uint32_t size[2]);
static VkImageLayout getNaturalLayout(uint32_t usage, VkImageAspectFlags aspect);
static VkFormat convertFormat(gpu_texture_format format, int colorspace);
static VkPipelineStageFlags convertPhase(gpu_phase phase);
static VkPipelineStageFlags convertPhase(gpu_phase phase, bool dst);
static VkAccessFlags convertCache(gpu_cache cache);
static VkBool32 relay(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, const VkDebugUtilsMessengerCallbackDataEXT* data, void* userdata);
static void nickname(void* object, VkObjectType type, const char* name);
@ -1796,8 +1796,8 @@ void gpu_sync(gpu_stream* stream, gpu_barrier* barriers, uint32_t count) {
for (uint32_t i = 0; i < count; i++) {
gpu_barrier* barrier = &barriers[i];
src |= convertPhase(barrier->prev);
dst |= convertPhase(barrier->next);
src |= convertPhase(barrier->prev, false);
dst |= convertPhase(barrier->next, true);
memoryBarrier.srcAccessMask |= convertCache(barrier->flush);
memoryBarrier.dstAccessMask |= convertCache(barrier->clear);
}
@ -2704,7 +2704,7 @@ static VkFormat convertFormat(gpu_texture_format format, int colorspace) {
return formats[format][colorspace];
}
static VkPipelineStageFlags convertPhase(gpu_phase phase) {
static VkPipelineStageFlags convertPhase(gpu_phase phase, bool dst) {
VkPipelineStageFlags flags = 0;
if (phase & GPU_PHASE_INDIRECT) flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
if (phase & GPU_PHASE_INPUT_INDEX) flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
@ -2716,6 +2716,7 @@ static VkPipelineStageFlags convertPhase(gpu_phase phase) {
if (phase & GPU_PHASE_DEPTH_LATE) flags |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
if (phase & GPU_PHASE_COLOR) flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
if (phase & GPU_PHASE_TRANSFER) flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
if (phase & GPU_PHASE_ALL) flags |= dst ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
return flags;
}

View File

@ -877,26 +877,24 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
if (canvas->mipmap) {
bool depth = pass->depth && pass->depth->info.mipmaps > 1;
// Waits for the external subpass dependency layout transition to finish before mipmapping
gpu_barrier barrier = {
.prev = GPU_PHASE_COLOR | (depth ? GPU_PHASE_DEPTH_LATE : 0),
.prev = GPU_PHASE_ALL,
.next = GPU_PHASE_TRANSFER,
.flush = GPU_CACHE_COLOR_WRITE | (depth ? GPU_CACHE_DEPTH_WRITE : 0),
.flush = 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 (depth) {
mipmapTexture(pass->stream, pass->depth, 0, ~0u);
trackTexture(pass, pass->depth, GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_WRITE);
}
}
break;
@ -963,8 +961,8 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
// - does clear the write cache
// - resets the 'last write' and clears pendingReads
uint32_t read = access->cache & GPU_CACHE_READ;
uint32_t write = access->cache & GPU_CACHE_WRITE;
uint32_t read = access->cache & GPU_CACHE_READ_MASK;
uint32_t write = access->cache & GPU_CACHE_WRITE_MASK;
uint32_t newReads = read & ~sync->pendingReads;
bool hasNewReads = newReads || (access->phase & ~sync->readPhase);
bool readAfterWrite = read && sync->pendingWrite && hasNewReads;
@ -1000,6 +998,21 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
sync->lastWriteIndex = i + 1;
}
}
// For automipmapping, the final write to the target is a transfer, not an attachment write
if (pass->info.type == PASS_RENDER && pass->info.canvas.mipmap) {
for (uint32_t t = 0; t < pass->info.canvas.count; t++) {
if (pass->color[t]->info.mipmaps > 1) {
pass->color[t]->sync.writePhase = GPU_PHASE_TRANSFER;
pass->color[t]->sync.pendingWrite = GPU_CACHE_TRANSFER_WRITE;
}
}
if (pass->depth && pass->depth->info.mipmaps > 1) {
pass->depth->sync.writePhase = GPU_PHASE_TRANSFER;
pass->depth->sync.pendingWrite = GPU_CACHE_TRANSFER_WRITE;
}
}
}
for (uint32_t i = 0; i < count; i++) {