void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects) { Vk_Buffer *rbo = &frame->rbo; draw->rbo = rbo; draw->n_rects = 0; draw->max_rects = max_rects; draw->rects = rbo->data; } void D_End(D_Context *draw, Vk_Frame *frame) { VkCommandBuffer cmd = frame->cmd; Vk_Pipeline *basic = &draw->pipelines[0]; // We can probably stop doing this at some point VkDescriptorSet set; VkDescriptorSetAllocateInfo alloc_info = { 0 }; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = frame->descriptors; alloc_info.descriptorSetCount = 1; alloc_info.pSetLayouts = &basic->layout.set; vk.AllocateDescriptorSets(vk.device, &alloc_info, &set); // 'update' the descriptor sets for binding M_TempScope(0, 0) { VkWriteDescriptorSet writes[2] = { 0 }; VkDescriptorBufferInfo rbo_info = { 0 }; rbo_info.buffer = draw->rbo->handle; rbo_info.offset = 0; rbo_info.range = VK_WHOLE_SIZE; VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = draw->n_images); for (U32 it = 0; it < draw->n_images; ++it) { image_info[it].imageView = draw->images[it].image.view; image_info[it].sampler = vk.sampler; image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[0].dstSet = set; writes[0].dstBinding = 0; writes[0].descriptorCount = 1; writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; writes[0].pBufferInfo = &rbo_info; writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes[1].dstSet = set; writes[1].dstBinding = 1; writes[1].descriptorCount = draw->n_images; writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; writes[1].pImageInfo = image_info; vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0); } vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle); vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0); vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &draw->camera->proj.fwd); VkViewport viewport = { 0, 0, (F32) draw->window_width, (F32) draw->window_height, 0.0f, 1.0f }; VkRect2D scissor = { 0, 0, draw->window_width, draw->window_height }; vk.CmdSetViewport(cmd, 0, 1, &viewport); vk.CmdSetScissor(cmd, 0, 1, &scissor); vk.CmdDraw(cmd, 6, draw->n_rects, 0, 0); } internal U32 V4f_UnormColour(V4f c) { // @Todo: SRGB handling U32 result = ((U8) (255.0f * c.a)) << 24 | ((U8) (255.0f * c.r)) << 16 | ((U8) (255.0f * c.g)) << 8 | ((U8) (255.0f * c.b)) << 0; return result; } void _D_Rect(D_Context *draw, D_RectOpts *opts) { if (draw->n_rects < draw->max_rects) { D_Rect *rect = &draw->rects[draw->n_rects]; rect->texture = opts->texture; rect->x = opts->p.x; rect->y = opts->p.y; rect->uv[0] = opts->uv.min.x; rect->uv[1] = opts->uv.min.y; rect->uv[2] = opts->uv.max.x; rect->uv[3] = opts->uv.max.y; rect->angle = opts->angle; if (opts->flags & D_RECT_PER_VERTEX_COLOUR) { rect->c[0] = V4f_UnormColour(opts->vtxc[0]); rect->c[1] = V4f_UnormColour(opts->vtxc[1]); rect->c[2] = V4f_UnormColour(opts->vtxc[2]); rect->c[3] = V4f_UnormColour(opts->vtxc[3]); } else { U32 unorm = V4f_UnormColour(opts->c); rect->c[0] = unorm; rect->c[1] = unorm; rect->c[2] = unorm; rect->c[3] = unorm; } if (opts->flags & D_RECT_IGNORE_ASPECT) { rect->w = opts->w; rect->h = opts->h; } else { Vk_Image *image = &draw->images[opts->texture].image; if (image->width > image->height) { rect->w = opts->scale * ((F32) image->width / (F32) image->height); rect->h = opts->scale; } else { rect->w = opts->scale; rect->h = opts->scale * ((F32) image->height / (F32) image->width); } } draw->n_rects += 1; } }