This commit is contained in:
bjorn 2022-06-24 19:00:59 -07:00
parent 9e7bd34ab1
commit c327eb103f
4 changed files with 173 additions and 0 deletions

View File

@ -10,6 +10,7 @@ typedef struct gpu_shader gpu_shader;
typedef struct gpu_bundle_pool gpu_bundle_pool;
typedef struct gpu_bundle gpu_bundle;
typedef struct gpu_pipeline gpu_pipeline;
typedef struct gpu_tally gpu_tally;
typedef struct gpu_stream gpu_stream;
size_t gpu_sizeof_buffer(void);
@ -20,6 +21,7 @@ size_t gpu_sizeof_shader(void);
size_t gpu_sizeof_bundle_pool(void);
size_t gpu_sizeof_bundle(void);
size_t gpu_sizeof_pipeline(void);
size_t gpu_sizeof_tally(void);
// Buffer
@ -447,6 +449,22 @@ bool gpu_pipeline_init_graphics(gpu_pipeline* pipeline, gpu_pipeline_info* info)
bool gpu_pipeline_init_compute(gpu_pipeline* pipeline, gpu_compute_pipeline_info* info);
void gpu_pipeline_destroy(gpu_pipeline* pipeline);
// Tally
typedef enum {
GPU_TALLY_TIMER,
GPU_TALLY_PIXEL,
GPU_TALLY_PIPELINE
} gpu_tally_type;
typedef struct {
gpu_tally_type type;
uint32_t count;
} gpu_tally_info;
bool gpu_tally_init(gpu_tally* tally, gpu_tally_info* info);
void gpu_tally_destroy(gpu_tally* tally);
// Stream
typedef enum {
@ -547,10 +565,15 @@ void gpu_copy_buffers(gpu_stream* stream, gpu_buffer* src, gpu_buffer* dst, uint
void gpu_copy_textures(gpu_stream* stream, gpu_texture* src, gpu_texture* dst, uint32_t srcOffset[4], uint32_t dstOffset[4], uint32_t size[3]);
void gpu_copy_buffer_texture(gpu_stream* stream, gpu_buffer* src, gpu_texture* dst, uint32_t srcOffset, uint32_t dstOffset[4], uint32_t extent[3]);
void gpu_copy_texture_buffer(gpu_stream* stream, gpu_texture* src, gpu_buffer* dst, uint32_t srcOffset[4], uint32_t dstOffset, uint32_t extent[3]);
void gpu_copy_tally_buffer(gpu_stream* stream, gpu_tally* src, gpu_buffer* dst, uint32_t srcIndex, uint32_t dstOffset, uint32_t count, uint32_t stride);
void gpu_clear_buffer(gpu_stream* stream, gpu_buffer* buffer, uint32_t offset, uint32_t size);
void gpu_clear_texture(gpu_stream* stream, gpu_texture* texture, float value[4], uint32_t layer, uint32_t layerCount, uint32_t level, uint32_t levelCount);
void gpu_clear_tally(gpu_stream* stream, gpu_tally* tally, uint32_t index, uint32_t count);
void gpu_blit(gpu_stream* stream, gpu_texture* src, gpu_texture* dst, uint32_t srcOffset[4], uint32_t dstOffset[4], uint32_t srcExtent[3], uint32_t dstExtent[3], gpu_filter filter);
void gpu_sync(gpu_stream* stream, gpu_barrier* barriers, uint32_t count);
void gpu_tally_begin(gpu_stream* stream, gpu_tally* tally, uint32_t index);
void gpu_tally_end(gpu_stream* stream, gpu_tally* tally, uint32_t index);
void gpu_tally_mark(gpu_stream* stream, gpu_tally* tally, uint32_t index);
// Entry

View File

@ -55,6 +55,10 @@ struct gpu_pipeline {
VkPipeline handle;
};
struct gpu_tally {
VkQueryPool handle;
};
struct gpu_stream {
VkCommandBuffer commands;
};
@ -67,6 +71,7 @@ size_t gpu_sizeof_shader() { return sizeof(gpu_shader); }
size_t gpu_sizeof_bundle_pool() { return sizeof(gpu_bundle_pool); }
size_t gpu_sizeof_bundle() { return sizeof(gpu_bundle); }
size_t gpu_sizeof_pipeline() { return sizeof(gpu_pipeline); }
size_t gpu_sizeof_tally() { return sizeof(gpu_tally); }
// Internals
@ -262,6 +267,8 @@ static bool check(bool condition, const char* message);
X(vkCreateQueryPool)\
X(vkDestroyQueryPool)\
X(vkCmdResetQueryPool)\
X(vkCmdBeginQuery)\
X(vkCmdEndQuery)\
X(vkCmdWriteTimestamp)\
X(vkCmdCopyQueryPoolResults)\
X(vkCreateBuffer)\
@ -1350,6 +1357,40 @@ void gpu_pipeline_destroy(gpu_pipeline* pipeline) {
condemn(pipeline->handle, VK_OBJECT_TYPE_PIPELINE);
}
// Tally
bool gpu_tally_init(gpu_tally* tally, gpu_tally_info* info) {
VkQueryType queryTypes[] = {
[GPU_TALLY_TIMER] = VK_QUERY_TYPE_TIMESTAMP,
[GPU_TALLY_PIXEL] = VK_QUERY_TYPE_OCCLUSION,
[GPU_TALLY_PIPELINE] = VK_QUERY_TYPE_PIPELINE_STATISTICS
};
VkQueryPoolCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
.queryType = queryTypes[info->type],
.queryCount = info->count,
.pipelineStatistics = info->type == GPU_TALLY_PIPELINE ? (
VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT |
VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT |
VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT
) : 0
};
VK(vkCreateQueryPool(state.device, &createInfo, NULL, &tally->handle), "Could not create query pool") {
return false;
}
return true;
}
void gpu_tally_destroy(gpu_tally* tally) {
condemn(tally->handle, VK_OBJECT_TYPE_QUERY_POOL);
}
// Stream
gpu_stream* gpu_stream_begin(const char* label) {
@ -1558,6 +1599,10 @@ void gpu_copy_texture_buffer(gpu_stream* stream, gpu_texture* src, gpu_buffer* d
vkCmdCopyImageToBuffer(stream->commands, src->handle, VK_IMAGE_LAYOUT_GENERAL, dst->handle, 1, &region);
}
void gpu_copy_tally_buffer(gpu_stream* stream, gpu_tally* src, gpu_buffer* dst, uint32_t srcIndex, uint32_t dstOffset, uint32_t count, uint32_t stride) {
vkCmdCopyQueryPoolResults(stream->commands, src->handle, srcIndex, count, dst->handle, dstOffset, stride, 0);
}
void gpu_clear_buffer(gpu_stream* stream, gpu_buffer* buffer, uint32_t offset, uint32_t size) {
vkCmdFillBuffer(stream->commands, buffer->handle, buffer->offset + offset, size, 0);
}
@ -1583,6 +1628,10 @@ void gpu_clear_texture(gpu_stream* stream, gpu_texture* texture, float value[4],
}
}
void gpu_clear_tally(gpu_stream* stream, gpu_tally* tally, uint32_t index, uint32_t count) {
vkCmdResetQueryPool(stream->commands, tally->handle, index, count);
}
void gpu_blit(gpu_stream* stream, gpu_texture* src, gpu_texture* dst, uint32_t srcOffset[4], uint32_t dstOffset[4], uint32_t srcExtent[3], uint32_t dstExtent[3], gpu_filter filter) {
VkImageBlit region = {
.srcSubresource = {
@ -1629,6 +1678,18 @@ void gpu_sync(gpu_stream* stream, gpu_barrier* barriers, uint32_t count) {
}
}
void gpu_tally_begin(gpu_stream* stream, gpu_tally* tally, uint32_t index) {
vkCmdBeginQuery(stream->commands, tally->handle, index, 0);
}
void gpu_tally_end(gpu_stream* stream, gpu_tally* tally, uint32_t index) {
vkCmdEndQuery(stream->commands, tally->handle, index);
}
void gpu_tally_mark(gpu_stream* stream, gpu_tally* tally, uint32_t index) {
vkCmdWriteTimestamp(stream->commands, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, tally->handle, index);
}
// Entry
bool gpu_init(gpu_config* config) {
@ -2352,6 +2413,7 @@ static void expunge() {
case VK_OBJECT_TYPE_DESCRIPTOR_POOL: vkDestroyDescriptorPool(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_PIPELINE_LAYOUT: vkDestroyPipelineLayout(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_PIPELINE: vkDestroyPipeline(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_QUERY_POOL: vkDestroyQueryPool(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_RENDER_PASS: vkDestroyRenderPass(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_FRAMEBUFFER: vkDestroyFramebuffer(state.device, victim->handle, NULL); break;
case VK_OBJECT_TYPE_DEVICE_MEMORY: vkFreeMemory(state.device, victim->handle, NULL); break;

View File

@ -150,6 +150,14 @@ struct Font {
uint32_t atlasY;
};
struct Tally {
uint32_t ref;
uint32_t tick;
TallyInfo info;
gpu_tally* gpu;
uint64_t* masks;
};
typedef struct {
float view[16];
float projection[16];
@ -2111,6 +2119,37 @@ void lovrFontGetLines(Font* font, ColoredString* strings, uint32_t count, float
tempPop(stack);
}
// Tally
Tally* lovrTallyCreate(TallyInfo* info) {
lovrCheck(info->count > 0, "Tally count must be greater than zero");
lovrCheck(info->views <= state.limits.renderSize[2], "Tally view count can not exceed the maximum view count");
Tally* tally = calloc(1, sizeof(Tally) + gpu_sizeof_tally());
lovrAssert(tally, "Out of memory");
tally->ref = 1;
tally->tick = state.tick;
tally->info = *info;
tally->gpu = (gpu_tally*) (tally + 1);
tally->masks = calloc((info->count + 63) / 64, sizeof(uint64_t));
lovrAssert(tally->masks, "Out of memory");
uint32_t total = info->count * (info->type == TALLY_TIMER ? 2 * info->views : 1);
gpu_tally_init(tally->gpu, &(gpu_tally_info) {
.type = (gpu_tally_type) info->type,
.count = total
});
return tally;
}
void lovrTallyDestroy(void* ref) {
Tally* tally = ref;
gpu_tally_destroy(tally->gpu);
free(tally->masks);
free(tally);
}
// Pass
Pass* lovrGraphicsGetPass(PassInfo* info) {
@ -3875,6 +3914,34 @@ void lovrPassMipmap(Pass* pass, Texture* texture, uint32_t base, uint32_t count)
trackTexture(pass, texture, GPU_PHASE_TRANSFER, GPU_CACHE_TRANSFER_READ | GPU_CACHE_TRANSFER_WRITE);
}
void lovrPassTick(Pass* pass, Tally* tally, uint32_t index) {
lovrCheck(index < tally->info.count, "Trying to use tally slot #%d, but the tally only has %d slots", index + 1, tally->info.count);
lovrCheck(~tally->masks[index / 64] & (1 << (index % 64)), "Tally slot #%d has already been used", index + 1);
if (tally->tick != state.tick) {
gpu_clear_tally(state.stream, tally->gpu, 0, tally->info.count * 2 * tally->info.views);
memset(tally->masks, 0, (tally->info.count + 63) / 64 * sizeof(uint64_t));
tally->tick = state.tick;
}
if (tally->info.type == TALLY_TIMER) {
gpu_tally_mark(pass->stream, tally->gpu, index * 2 * tally->info.views);
} else {
gpu_tally_begin(pass->stream, tally->gpu, index);
}
}
void lovrPassTock(Pass* pass, Tally* tally, uint32_t index) {
lovrCheck(index < tally->info.count, "Trying to use tally slot #%d, but the tally only has %d slots", index + 1, tally->info.count);
lovrCheck(tally->masks[index / 64] & (1 << (index % 64)), "Tally slot #%d has not been started yet", index + 1);
if (tally->info.type == TALLY_TIMER) {
gpu_tally_mark(pass->stream, tally->gpu, index * 2 * tally->info.views + tally->info.views);
} else {
gpu_tally_end(pass->stream, tally->gpu, index);
}
}
// Helpers
static void* tempAlloc(size_t size) {

View File

@ -14,6 +14,7 @@ typedef struct Sampler Sampler;
typedef struct Shader Shader;
typedef struct Material Material;
typedef struct Font Font;
typedef struct Tally Tally;
typedef struct Pass Pass;
typedef struct {
@ -357,6 +358,24 @@ float lovrFontGetKerning(Font* font, uint32_t left, uint32_t right);
float lovrFontGetWidth(Font* font, ColoredString* strings, uint32_t count);
void lovrFontGetLines(Font* font, ColoredString* strings, uint32_t count, float wrap, void (*callback)(void* context, const char* string, size_t length), void* context);
// Tally
typedef enum {
TALLY_TIMER,
TALLY_PIXEL,
TALLY_PIPELINE
} TallyType;
typedef struct {
TallyType type;
uint32_t count;
uint32_t views;
} TallyInfo;
Tally* lovrTallyCreate(TallyInfo* info);
void lovrTallyDestroy(void* ref);
const TallyInfo* lovrTallyGetInfo(Tally* tally);
// Pass
typedef enum {
@ -506,3 +525,5 @@ void lovrPassCopyImageToTexture(Pass* pass, struct Image* src, Texture* dst, uin
void lovrPassCopyTextureToTexture(Pass* pass, Texture* src, Texture* dst, uint32_t srcOffset[4], uint32_t dstOffset[4], uint32_t extent[3]);
void lovrPassBlit(Pass* pass, Texture* src, Texture* dst, uint32_t srcOffset[4], uint32_t dstOffset[4], uint32_t srcExtent[3], uint32_t dstExtent[3], FilterMode filter);
void lovrPassMipmap(Pass* pass, Texture* texture, uint32_t base, uint32_t count);
void lovrPassTick(Pass* pass, Tally* tally, uint32_t index);
void lovrPassTock(Pass* pass, Tally* tally, uint32_t index);