|
|
|
@ -1,5 +1,6 @@
|
|
|
|
#include "draw.h"
|
|
|
|
#include "draw.h"
|
|
|
|
#include "hex.h"
|
|
|
|
#include "hex.h"
|
|
|
|
|
|
|
|
#include "camera.h"
|
|
|
|
#include "vulkan/vulkan_core.h"
|
|
|
|
#include "vulkan/vulkan_core.h"
|
|
|
|
|
|
|
|
|
|
|
|
void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, VkDeviceAddress camera_address, double time, uint32_t frame) {
|
|
|
|
void record_hex_draw(VkCommandBuffer command_buffer, HexContext* hex, VkDeviceAddress camera_address, double time, uint32_t frame) {
|
|
|
|
@ -32,22 +33,17 @@ static void bind_ui_pipeline(VkCommandBuffer command_buffer, UIContext* ui) {
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui->pipeline.layout, 3, 1, &ui->textures, 0, NULL);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui->pipeline.layout, 3, 1, &ui->textures, 0, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Single pass over container_order (back to front, same z-order UI has
|
|
|
|
// UI-only pass over container_order (back to front). Camera scenes are
|
|
|
|
// always used): a container with a camera attached renders that camera's
|
|
|
|
// rendered to offscreen textures in draw_frame before this is called; each
|
|
|
|
// hex scene scissored to its own region first, then every container
|
|
|
|
// camera-attached container samples its texture via a background IMAGE
|
|
|
|
// (camera-attached or not) draws its normal 2D drawables via the UI
|
|
|
|
// drawable created by camera_display (camera.c).
|
|
|
|
// pipeline on top - see draw_frame's single unified rendering scope, which
|
|
|
|
static void record_container_draw(
|
|
|
|
// is what makes interleaving these two pipelines per-container possible
|
|
|
|
|
|
|
|
// without a barrier between them.
|
|
|
|
|
|
|
|
void record_container_draw(
|
|
|
|
|
|
|
|
VkCommandBuffer command_buffer,
|
|
|
|
VkCommandBuffer command_buffer,
|
|
|
|
RenderContext* gpu,
|
|
|
|
RenderContext* gpu,
|
|
|
|
UIContext* ui,
|
|
|
|
UIContext* ui,
|
|
|
|
HexContext* hex,
|
|
|
|
|
|
|
|
VkViewport full_viewport,
|
|
|
|
|
|
|
|
VkRect2D full_scissor,
|
|
|
|
|
|
|
|
double time,
|
|
|
|
double time,
|
|
|
|
uint32_t frame) {
|
|
|
|
uint32_t frame) {
|
|
|
|
|
|
|
|
(void)gpu;
|
|
|
|
UIPushConstant push = {
|
|
|
|
UIPushConstant push = {
|
|
|
|
.time = (float)time,
|
|
|
|
.time = (float)time,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
@ -56,31 +52,6 @@ void record_container_draw(
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t o = 0; o < ui->container_order_count; o++) {
|
|
|
|
for(uint32_t o = 0; o < ui->container_order_count; o++) {
|
|
|
|
Container* c = &ui->containers[ui->container_order[o]];
|
|
|
|
Container* c = &ui->containers[ui->container_order[o]];
|
|
|
|
|
|
|
|
|
|
|
|
if(c->camera != NULL) {
|
|
|
|
|
|
|
|
VkRect2D rect;
|
|
|
|
|
|
|
|
container_screen_rect(gpu, c, &rect);
|
|
|
|
|
|
|
|
VkViewport camera_viewport = {
|
|
|
|
|
|
|
|
.x = (float)rect.offset.x,
|
|
|
|
|
|
|
|
.y = (float)rect.offset.y,
|
|
|
|
|
|
|
|
.width = (float)rect.extent.width,
|
|
|
|
|
|
|
|
.height = (float)rect.extent.height,
|
|
|
|
|
|
|
|
.minDepth = 0.0f,
|
|
|
|
|
|
|
|
.maxDepth = 1.0f,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
vkCmdSetViewport(command_buffer, 0, 1, &camera_viewport);
|
|
|
|
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &rect);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
record_hex_draw(command_buffer, hex, c->camera->gpu_address[frame], time, frame);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// record_hex_draw left a hex pipeline bound (a different bind point
|
|
|
|
|
|
|
|
// state) and the viewport/scissor scoped to this container - restore
|
|
|
|
|
|
|
|
// both before this (or the next) container's UI drawables.
|
|
|
|
|
|
|
|
vkCmdSetViewport(command_buffer, 0, 1, &full_viewport);
|
|
|
|
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &full_scissor);
|
|
|
|
|
|
|
|
bind_ui_pipeline(command_buffer, ui);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
push.container = c->address[frame];
|
|
|
|
push.container = c->address[frame];
|
|
|
|
vkCmdPushConstants(command_buffer, ui->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, &push);
|
|
|
|
vkCmdPushConstants(command_buffer, ui->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, &push);
|
|
|
|
vkCmdDrawIndirect(command_buffer, c->container[frame], offsetof(GPUContainer, draw), 1, 0);
|
|
|
|
vkCmdDrawIndirect(command_buffer, c->container[frame], offsetof(GPUContainer, draw), 1, 0);
|
|
|
|
@ -107,7 +78,6 @@ VkResult draw_frame(
|
|
|
|
RenderContext* context,
|
|
|
|
RenderContext* context,
|
|
|
|
UIContext* ui,
|
|
|
|
UIContext* ui,
|
|
|
|
HexContext* hex,
|
|
|
|
HexContext* hex,
|
|
|
|
Camera* offscreen_camera,
|
|
|
|
|
|
|
|
double time) {
|
|
|
|
double time) {
|
|
|
|
VkResult result;
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
|
|
|
|
@ -223,29 +193,39 @@ VkResult draw_frame(
|
|
|
|
.layerCount = 1,
|
|
|
|
.layerCount = 1,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Targets a different image entirely (not the swapchain), so this can run
|
|
|
|
// Render each camera's hex scene to its offscreen texture before the
|
|
|
|
// any time after the command buffer begins - independent of the acquire
|
|
|
|
// main scene pass. Iterate container_order to discover cameras; skip
|
|
|
|
// below. The read barrier at the end is the producer-before-consumer sync
|
|
|
|
// duplicates (same camera referenced by multiple containers).
|
|
|
|
// that makes the texture safe for the unified scene pass (or anything
|
|
|
|
// Cameras are independent so this order carries no semantic dependency.
|
|
|
|
// else) to sample later this same frame.
|
|
|
|
for(uint32_t o = 0; o < ui->container_order_count; o++) {
|
|
|
|
if(offscreen_camera != NULL) {
|
|
|
|
Container* c = &ui->containers[ui->container_order[o]];
|
|
|
|
|
|
|
|
Camera* cam = c->camera;
|
|
|
|
|
|
|
|
if(cam == NULL || !cam->has_texture_target) continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool already_rendered = false;
|
|
|
|
|
|
|
|
for(uint32_t p = 0; p < o; p++) {
|
|
|
|
|
|
|
|
if(ui->containers[ui->container_order[p]].camera == cam) {
|
|
|
|
|
|
|
|
already_rendered = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(already_rendered) continue;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t f = context->current_frame;
|
|
|
|
uint32_t f = context->current_frame;
|
|
|
|
Texture* target = &ui->texture_slots[offscreen_camera->texture.texture_slot[f]];
|
|
|
|
Texture* target = &ui->texture_slots[cam->texture.texture_slot[f]];
|
|
|
|
|
|
|
|
|
|
|
|
VkViewport offscreen_viewport = {
|
|
|
|
VkExtent2D cam_extent = {cam->texture.width, cam->texture.height};
|
|
|
|
.width = (float)offscreen_camera->texture.width,
|
|
|
|
VkViewport cam_viewport = {
|
|
|
|
.height = (float)offscreen_camera->texture.height,
|
|
|
|
.width = (float)cam_extent.width,
|
|
|
|
|
|
|
|
.height = (float)cam_extent.height,
|
|
|
|
.maxDepth = 1.0f,
|
|
|
|
.maxDepth = 1.0f,
|
|
|
|
.minDepth = 0.0f,
|
|
|
|
.minDepth = 0.0f,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
vkCmdSetViewport(command_buffer, 0, 1, &offscreen_viewport);
|
|
|
|
vkCmdSetViewport(command_buffer, 0, 1, &cam_viewport);
|
|
|
|
|
|
|
|
VkRect2D cam_scissor = {.extent = cam_extent};
|
|
|
|
VkRect2D offscreen_scissor = {
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &cam_scissor);
|
|
|
|
.extent = {offscreen_camera->texture.width, offscreen_camera->texture.height},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &offscreen_scissor);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageMemoryBarrier offscreen_acquire_barrier = {
|
|
|
|
VkImageMemoryBarrier cam_acquire_barrier = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
@ -259,9 +239,9 @@ VkResult draw_frame(
|
|
|
|
vkCmdPipelineBarrier(command_buffer,
|
|
|
|
vkCmdPipelineBarrier(command_buffer,
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
0, 0, NULL, 0, NULL, 1, &offscreen_acquire_barrier);
|
|
|
|
0, 0, NULL, 0, NULL, 1, &cam_acquire_barrier);
|
|
|
|
|
|
|
|
|
|
|
|
VkRenderingAttachmentInfo offscreen_color_attachment = {
|
|
|
|
VkRenderingAttachmentInfo cam_color = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.imageView = target->view,
|
|
|
|
.imageView = target->view,
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
@ -269,27 +249,27 @@ VkResult draw_frame(
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
.clearValue = {.color = {{0.0f, 0.0f, 0.0f, 0.0f}}},
|
|
|
|
.clearValue = {.color = {{0.0f, 0.0f, 0.0f, 0.0f}}},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
VkRenderingAttachmentInfo offscreen_depth_attachment = {
|
|
|
|
VkRenderingAttachmentInfo cam_depth = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
.imageView = offscreen_camera->texture.depth_image_view[f],
|
|
|
|
.imageView = cam->texture.depth_image_view[f],
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
|
|
.clearValue = {.depthStencil = {1.0f, 0}},
|
|
|
|
.clearValue = {.depthStencil = {1.0f, 0}},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
VkRenderingInfo offscreen_rendering = {
|
|
|
|
VkRenderingInfo cam_rendering = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
.renderArea = {{0, 0}, offscreen_scissor.extent},
|
|
|
|
.renderArea = {{0, 0}, cam_extent},
|
|
|
|
.layerCount = 1,
|
|
|
|
.layerCount = 1,
|
|
|
|
.colorAttachmentCount = 1,
|
|
|
|
.colorAttachmentCount = 1,
|
|
|
|
.pColorAttachments = &offscreen_color_attachment,
|
|
|
|
.pColorAttachments = &cam_color,
|
|
|
|
.pDepthAttachment = &offscreen_depth_attachment,
|
|
|
|
.pDepthAttachment = &cam_depth,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
vkCmdBeginRendering(command_buffer, &offscreen_rendering);
|
|
|
|
vkCmdBeginRendering(command_buffer, &cam_rendering);
|
|
|
|
record_hex_draw(command_buffer, hex, offscreen_camera->gpu_address[f], time, f);
|
|
|
|
record_hex_draw(command_buffer, hex, cam->gpu_address[f], time, f);
|
|
|
|
vkCmdEndRendering(command_buffer);
|
|
|
|
vkCmdEndRendering(command_buffer);
|
|
|
|
|
|
|
|
|
|
|
|
VkImageMemoryBarrier offscreen_read_barrier = {
|
|
|
|
VkImageMemoryBarrier cam_read_barrier = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
|
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
@ -303,7 +283,7 @@ VkResult draw_frame(
|
|
|
|
vkCmdPipelineBarrier(command_buffer,
|
|
|
|
vkCmdPipelineBarrier(command_buffer,
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
0, 0, NULL, 0, NULL, 1, &offscreen_read_barrier);
|
|
|
|
0, 0, NULL, 0, NULL, 1, &cam_read_barrier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkViewport viewport = {
|
|
|
|
VkViewport viewport = {
|
|
|
|
@ -360,7 +340,7 @@ VkResult draw_frame(
|
|
|
|
.pDepthAttachment = &depth_attachment,
|
|
|
|
.pDepthAttachment = &depth_attachment,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
vkCmdBeginRendering(command_buffer, &scene_rendering);
|
|
|
|
vkCmdBeginRendering(command_buffer, &scene_rendering);
|
|
|
|
record_container_draw(command_buffer, context, ui, hex, viewport, scissor, time, context->current_frame);
|
|
|
|
record_container_draw(command_buffer, context, ui, time, context->current_frame);
|
|
|
|
vkCmdEndRendering(command_buffer);
|
|
|
|
vkCmdEndRendering(command_buffer);
|
|
|
|
|
|
|
|
|
|
|
|
VkImageMemoryBarrier present_barrier = {
|
|
|
|
VkImageMemoryBarrier present_barrier = {
|
|
|
|
|