2022-03-27 21:22:24 +00:00
|
|
|
// Copyright 2019-2022, Collabora, Ltd.
|
2020-10-05 22:30:31 +00:00
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief The NEW compositor rendering code header.
|
|
|
|
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
2021-11-03 17:45:39 +00:00
|
|
|
* @ingroup comp_render
|
2020-10-05 22:30:31 +00:00
|
|
|
*/
|
|
|
|
|
2022-05-15 17:03:41 +00:00
|
|
|
#include "render/render_interface.h"
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Common helpers
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
#define C(c) \
|
|
|
|
do { \
|
|
|
|
VkResult ret = c; \
|
|
|
|
if (ret != VK_SUCCESS) { \
|
|
|
|
return false; \
|
|
|
|
} \
|
2020-10-05 22:30:31 +00:00
|
|
|
} while (false)
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
#define D(TYPE, thing) \
|
|
|
|
if (thing != VK_NULL_HANDLE) { \
|
|
|
|
vk->vkDestroy##TYPE(vk->device, thing, NULL); \
|
|
|
|
thing = VK_NULL_HANDLE; \
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
#define DD(pool, thing) \
|
|
|
|
if (thing != VK_NULL_HANDLE) { \
|
|
|
|
free_descriptor_set(vk, pool, thing); \
|
|
|
|
thing = VK_NULL_HANDLE; \
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
2021-11-02 13:54:16 +00:00
|
|
|
/*!
|
2022-03-27 21:10:25 +00:00
|
|
|
* Get the @ref vk_bundle from @ref render_gfx_target_resources.
|
2021-11-02 13:54:16 +00:00
|
|
|
*/
|
|
|
|
static inline struct vk_bundle *
|
2022-03-27 21:10:25 +00:00
|
|
|
vk_from_rtr(struct render_gfx_target_resources *rtr)
|
2021-11-02 13:54:16 +00:00
|
|
|
{
|
2021-11-03 13:28:15 +00:00
|
|
|
return rtr->r->vk;
|
2021-11-02 13:54:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2022-03-27 21:10:25 +00:00
|
|
|
* Get the @ref vk_bundle from @ref render_gfx.
|
2021-11-02 13:54:16 +00:00
|
|
|
*/
|
|
|
|
static inline struct vk_bundle *
|
2022-03-27 21:10:25 +00:00
|
|
|
vk_from_rr(struct render_gfx *rr)
|
2021-11-02 13:54:16 +00:00
|
|
|
{
|
2021-11-02 18:37:07 +00:00
|
|
|
return rr->r->vk;
|
2021-11-02 13:54:16 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 22:30:31 +00:00
|
|
|
static VkResult
|
2021-01-14 14:13:48 +00:00
|
|
|
create_external_render_pass(struct vk_bundle *vk, VkFormat format, VkRenderPass *out_render_pass)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
VkAttachmentDescription attachments[1] = {
|
|
|
|
{
|
|
|
|
.format = format,
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
|
|
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkAttachmentReference color_reference = {
|
|
|
|
.attachment = 0,
|
|
|
|
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkSubpassDescription subpasses[1] = {
|
|
|
|
{
|
|
|
|
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
.inputAttachmentCount = 0,
|
|
|
|
.pInputAttachments = NULL,
|
|
|
|
.colorAttachmentCount = 1,
|
|
|
|
.pColorAttachments = &color_reference,
|
|
|
|
.pResolveAttachments = NULL,
|
|
|
|
.pDepthStencilAttachment = NULL,
|
|
|
|
.preserveAttachmentCount = 0,
|
|
|
|
.pPreserveAttachments = NULL,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkSubpassDependency dependencies[1] = {
|
|
|
|
{
|
|
|
|
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
|
|
|
.dstSubpass = 0,
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
.srcAccessMask = 0,
|
2021-01-14 14:13:48 +00:00
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
2020-10-05 22:30:31 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkRenderPassCreateInfo render_pass_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
|
|
.attachmentCount = ARRAY_SIZE(attachments),
|
|
|
|
.pAttachments = attachments,
|
|
|
|
.subpassCount = ARRAY_SIZE(subpasses),
|
|
|
|
.pSubpasses = subpasses,
|
|
|
|
.dependencyCount = ARRAY_SIZE(dependencies),
|
|
|
|
.pDependencies = dependencies,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkRenderPass render_pass = VK_NULL_HANDLE;
|
|
|
|
ret = vk->vkCreateRenderPass(vk->device, //
|
|
|
|
&render_pass_info, //
|
|
|
|
NULL, //
|
|
|
|
&render_pass); //
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_ERROR(vk, "vkCreateRenderPass failed: %s", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_render_pass = render_pass;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
create_framebuffer(struct vk_bundle *vk,
|
|
|
|
VkImageView image_view,
|
|
|
|
VkRenderPass render_pass,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
VkFramebuffer *out_external_framebuffer)
|
|
|
|
{
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
VkImageView attachments[1] = {image_view};
|
|
|
|
|
|
|
|
VkFramebufferCreateInfo frame_buffer_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
|
|
.renderPass = render_pass,
|
|
|
|
.attachmentCount = ARRAY_SIZE(attachments),
|
|
|
|
.pAttachments = attachments,
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
.layers = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
|
|
|
ret = vk->vkCreateFramebuffer(vk->device, //
|
|
|
|
&frame_buffer_info, //
|
|
|
|
NULL, //
|
|
|
|
&framebuffer); //
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_ERROR(vk, "vkCreateFramebuffer failed: %s", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_external_framebuffer = framebuffer;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
begin_render_pass(struct vk_bundle *vk,
|
|
|
|
VkCommandBuffer command_buffer,
|
|
|
|
VkRenderPass render_pass,
|
|
|
|
VkFramebuffer framebuffer,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height)
|
|
|
|
{
|
|
|
|
VkClearValue clear_color[1] = {{
|
|
|
|
.color = {.float32 = {0.0f, 0.0f, 0.0f, 0.0f}},
|
|
|
|
}};
|
|
|
|
|
|
|
|
VkRenderPassBeginInfo render_pass_begin_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
|
|
.renderPass = render_pass,
|
|
|
|
.framebuffer = framebuffer,
|
|
|
|
.renderArea =
|
|
|
|
{
|
|
|
|
.offset =
|
|
|
|
{
|
|
|
|
.x = 0,
|
|
|
|
.y = 0,
|
|
|
|
},
|
|
|
|
.extent =
|
|
|
|
{
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
.clearValueCount = ARRAY_SIZE(clear_color),
|
|
|
|
.pClearValues = clear_color,
|
|
|
|
};
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
vk->vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Mesh
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
create_mesh_pipeline(struct vk_bundle *vk,
|
|
|
|
VkRenderPass render_pass,
|
|
|
|
VkPipelineLayout pipeline_layout,
|
|
|
|
VkPipelineCache pipeline_cache,
|
|
|
|
uint32_t src_binding,
|
2021-11-08 23:03:03 +00:00
|
|
|
uint32_t mesh_index_count_total,
|
2020-10-05 22:30:31 +00:00
|
|
|
uint32_t mesh_stride,
|
|
|
|
VkShaderModule mesh_vert,
|
|
|
|
VkShaderModule mesh_frag,
|
|
|
|
VkPipeline *out_mesh_pipeline)
|
|
|
|
{
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
// Might be changed to line for debugging.
|
|
|
|
VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
|
|
|
|
|
|
|
|
// Do we use triangle strips or triangles with indices.
|
|
|
|
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
2021-11-08 23:03:03 +00:00
|
|
|
if (mesh_index_count_total > 0) {
|
2020-10-05 22:30:31 +00:00
|
|
|
topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_state = {
|
2021-01-14 14:13:48 +00:00
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
2020-10-05 22:30:31 +00:00
|
|
|
.topology = topology,
|
|
|
|
.primitiveRestartEnable = VK_FALSE,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterization_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
|
|
.depthClampEnable = VK_FALSE,
|
|
|
|
.rasterizerDiscardEnable = VK_FALSE,
|
|
|
|
.polygonMode = polygonMode,
|
|
|
|
.cullMode = VK_CULL_MODE_BACK_BIT,
|
|
|
|
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
|
|
|
.lineWidth = 1.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineColorBlendAttachmentState blend_attachment_state = {
|
|
|
|
.blendEnable = VK_FALSE,
|
|
|
|
.colorWriteMask = 0xf,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo color_blend_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
.attachmentCount = 1,
|
|
|
|
.pAttachments = &blend_attachment_state,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
|
|
|
.depthTestEnable = VK_TRUE,
|
|
|
|
.depthWriteEnable = VK_TRUE,
|
|
|
|
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL,
|
|
|
|
.front =
|
|
|
|
{
|
|
|
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
|
|
|
},
|
|
|
|
.back =
|
|
|
|
{
|
|
|
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo viewport_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
|
|
.viewportCount = 1,
|
|
|
|
.scissorCount = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisample_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
|
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkDynamicState dynamic_states[] = {
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineDynamicStateCreateInfo dynamic_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
|
|
.dynamicStateCount = ARRAY_SIZE(dynamic_states),
|
|
|
|
.pDynamicStates = dynamic_states,
|
|
|
|
};
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
VkVertexInputAttributeDescription vertex_input_attribute_descriptions[2] = {
|
|
|
|
{
|
|
|
|
.binding = src_binding,
|
|
|
|
.location = 0,
|
|
|
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
|
|
.offset = 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.binding = src_binding,
|
|
|
|
.location = 1,
|
|
|
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
|
|
.offset = 16,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription vertex_input_binding_description[1] = {
|
|
|
|
{
|
|
|
|
.binding = src_binding,
|
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
.stride = mesh_stride,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_state = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
.vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_input_attribute_descriptions),
|
|
|
|
.pVertexAttributeDescriptions = vertex_input_attribute_descriptions,
|
|
|
|
.vertexBindingDescriptionCount = ARRAY_SIZE(vertex_input_binding_description),
|
|
|
|
.pVertexBindingDescriptions = vertex_input_binding_description,
|
|
|
|
};
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
.module = mesh_vert,
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
.module = mesh_frag,
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
.stageCount = ARRAY_SIZE(shader_stages),
|
|
|
|
.pStages = shader_stages,
|
|
|
|
.pVertexInputState = &vertex_input_state,
|
|
|
|
.pInputAssemblyState = &input_assembly_state,
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
.pRasterizationState = &rasterization_state,
|
|
|
|
.pMultisampleState = &multisample_state,
|
|
|
|
.pDepthStencilState = &depth_stencil_state,
|
|
|
|
.pColorBlendState = &color_blend_state,
|
|
|
|
.pDynamicState = &dynamic_state,
|
|
|
|
.layout = pipeline_layout,
|
|
|
|
.renderPass = render_pass,
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
.basePipelineIndex = -1,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
|
|
|
ret = vk->vkCreateGraphicsPipelines(vk->device, //
|
|
|
|
pipeline_cache, //
|
|
|
|
1, //
|
|
|
|
&pipeline_info, //
|
|
|
|
NULL, //
|
|
|
|
&pipeline); //
|
|
|
|
if (ret != VK_SUCCESS) {
|
2021-01-14 14:13:48 +00:00
|
|
|
VK_DEBUG(vk, "vkCreateGraphicsPipelines failed: %s", vk_result_string(ret));
|
2020-10-05 22:30:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_mesh_pipeline = pipeline;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_mesh_discriptor_set(struct vk_bundle *vk,
|
|
|
|
uint32_t src_binding,
|
|
|
|
VkSampler sampler,
|
|
|
|
VkImageView image_view,
|
|
|
|
uint32_t ubo_binding,
|
|
|
|
VkBuffer buffer,
|
|
|
|
VkDeviceSize size,
|
|
|
|
VkDescriptorSet descriptor_set)
|
|
|
|
{
|
|
|
|
VkDescriptorImageInfo image_info = {
|
|
|
|
.sampler = sampler,
|
|
|
|
.imageView = image_view,
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkDescriptorBufferInfo buffer_info = {
|
|
|
|
.buffer = buffer,
|
|
|
|
.offset = 0,
|
|
|
|
.range = size,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkWriteDescriptorSet write_descriptor_sets[2] = {
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
.dstSet = descriptor_set,
|
|
|
|
.dstBinding = src_binding,
|
|
|
|
.descriptorCount = 1,
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
.pImageInfo = &image_info,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
.dstSet = descriptor_set,
|
|
|
|
.dstBinding = ubo_binding,
|
|
|
|
.descriptorCount = 1,
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
.pBufferInfo = &buffer_info,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-01-14 14:13:48 +00:00
|
|
|
vk->vkUpdateDescriptorSets(vk->device, //
|
|
|
|
ARRAY_SIZE(write_descriptor_sets), // descriptorWriteCount
|
|
|
|
write_descriptor_sets, // pDescriptorWrites
|
|
|
|
0, // descriptorCopyCount
|
|
|
|
NULL); // pDescriptorCopies
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-23 19:11:53 +00:00
|
|
|
/*
|
|
|
|
*
|
2022-09-12 04:32:28 +00:00
|
|
|
* 'Exported' target resources functions.
|
2021-09-23 19:11:53 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_target_resources_init(struct render_gfx_target_resources *rtr,
|
|
|
|
struct render_resources *r,
|
|
|
|
VkImageView target,
|
|
|
|
struct render_gfx_target_data *data)
|
2021-09-23 19:11:53 +00:00
|
|
|
{
|
2021-11-02 18:37:07 +00:00
|
|
|
struct vk_bundle *vk = r->vk;
|
2021-11-03 13:28:15 +00:00
|
|
|
rtr->r = r;
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
assert(data->is_external);
|
|
|
|
|
2021-11-03 13:28:15 +00:00
|
|
|
rtr->data = *data;
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
C(create_external_render_pass( //
|
|
|
|
vk, // vk_bundle
|
|
|
|
data->format, // target_format
|
2021-11-03 13:28:15 +00:00
|
|
|
&rtr->render_pass)); // out_render_pass
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
C(create_mesh_pipeline(vk, // vk_bundle
|
2021-11-03 13:28:15 +00:00
|
|
|
rtr->render_pass, // render_pass
|
2021-09-23 19:11:53 +00:00
|
|
|
r->mesh.pipeline_layout, // pipeline_layout
|
|
|
|
r->pipeline_cache, // pipeline_cache
|
|
|
|
r->mesh.src_binding, // src_binding
|
2021-11-08 23:03:03 +00:00
|
|
|
r->mesh.index_count_total, // mesh_index_count_total
|
2021-09-23 19:11:53 +00:00
|
|
|
r->mesh.stride, // mesh_stride
|
2021-11-02 18:37:07 +00:00
|
|
|
r->shaders->mesh_vert, // mesh_vert
|
|
|
|
r->shaders->mesh_frag, // mesh_frag
|
2021-11-03 13:28:15 +00:00
|
|
|
&rtr->mesh.pipeline)); // out_mesh_pipeline
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
C(create_framebuffer(vk, // vk_bundle,
|
|
|
|
target, // image_view,
|
2021-11-03 13:28:15 +00:00
|
|
|
rtr->render_pass, // render_pass,
|
2021-09-23 19:11:53 +00:00
|
|
|
data->width, // width,
|
|
|
|
data->height, // height,
|
2021-11-03 13:28:15 +00:00
|
|
|
&rtr->framebuffer)); // out_external_framebuffer
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_target_resources_close(struct render_gfx_target_resources *rtr)
|
2021-09-23 19:11:53 +00:00
|
|
|
{
|
2021-11-03 13:28:15 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rtr(rtr);
|
2021-09-23 19:11:53 +00:00
|
|
|
|
2021-11-03 13:28:15 +00:00
|
|
|
D(RenderPass, rtr->render_pass);
|
|
|
|
D(Pipeline, rtr->mesh.pipeline);
|
|
|
|
D(Framebuffer, rtr->framebuffer);
|
2021-09-23 19:11:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-05 22:30:31 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* 'Exported' rendering functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_init(struct render_gfx *rr, struct render_resources *r)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 18:37:07 +00:00
|
|
|
struct vk_bundle *vk = r->vk;
|
2020-10-05 22:30:31 +00:00
|
|
|
rr->r = r;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mesh per view
|
|
|
|
*/
|
|
|
|
|
2021-11-10 13:09:51 +00:00
|
|
|
C(vk_create_descriptor_set( //
|
2021-09-29 16:35:05 +00:00
|
|
|
vk, // vk_bundle
|
|
|
|
r->mesh.descriptor_pool, // descriptor_pool
|
|
|
|
r->mesh.descriptor_set_layout, // descriptor_set_layout
|
|
|
|
&rr->views[0].mesh.descriptor_set)); // descriptor_set
|
2020-10-05 22:30:31 +00:00
|
|
|
|
2021-11-10 13:09:51 +00:00
|
|
|
C(vk_create_descriptor_set( //
|
2021-09-29 16:35:05 +00:00
|
|
|
vk, // vk_bundle
|
|
|
|
r->mesh.descriptor_pool, // descriptor_pool
|
|
|
|
r->mesh.descriptor_set_layout, // descriptor_set_layout
|
|
|
|
&rr->views[1].mesh.descriptor_set)); // descriptor_set
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-08 13:34:57 +00:00
|
|
|
bool
|
|
|
|
render_gfx_begin(struct render_gfx *rr)
|
|
|
|
{
|
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
|
|
|
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
C(vk->vkResetCommandPool(vk->device, rr->r->cmd_pool, 0));
|
2022-06-10 22:05:33 +00:00
|
|
|
|
|
|
|
VkCommandBufferBeginInfo begin_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
C(vk->vkBeginCommandBuffer( //
|
|
|
|
rr->r->cmd, // commandBuffer
|
|
|
|
&begin_info)); // pBeginInfo
|
2022-04-08 13:34:57 +00:00
|
|
|
|
2022-04-23 21:16:20 +00:00
|
|
|
vk->vkCmdResetQueryPool( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
rr->r->cmd, // commandBuffer
|
2022-04-23 21:16:20 +00:00
|
|
|
rr->r->query_pool, // queryPool
|
|
|
|
0, // firstQuery
|
|
|
|
2); // queryCount
|
|
|
|
|
|
|
|
vk->vkCmdWriteTimestamp( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
rr->r->cmd, // commandBuffer
|
2022-04-23 21:16:20 +00:00
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // pipelineStage
|
|
|
|
rr->r->query_pool, // queryPool
|
|
|
|
0); // query
|
|
|
|
|
2022-04-08 13:34:57 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
render_gfx_end(struct render_gfx *rr)
|
2021-09-23 19:11:53 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2021-09-23 19:11:53 +00:00
|
|
|
|
2022-04-23 21:16:20 +00:00
|
|
|
vk->vkCmdWriteTimestamp( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
rr->r->cmd, // commandBuffer
|
2022-04-23 21:16:20 +00:00
|
|
|
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, // pipelineStage
|
|
|
|
rr->r->query_pool, // queryPool
|
|
|
|
1); // query
|
|
|
|
|
2022-06-10 22:05:33 +00:00
|
|
|
C(vk->vkEndCommandBuffer(rr->r->cmd));
|
2022-04-08 13:34:57 +00:00
|
|
|
|
|
|
|
return true;
|
2021-09-23 19:11:53 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 22:30:31 +00:00
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_close(struct render_gfx *rr)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2022-03-27 21:10:25 +00:00
|
|
|
struct render_resources *r = rr->r;
|
2020-10-05 22:30:31 +00:00
|
|
|
|
2021-09-29 16:35:05 +00:00
|
|
|
// Reclaimed by vkResetDescriptorPool.
|
|
|
|
rr->views[0].mesh.descriptor_set = VK_NULL_HANDLE;
|
|
|
|
rr->views[1].mesh.descriptor_set = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
vk->vkResetDescriptorPool( //
|
|
|
|
vk->device, //
|
|
|
|
r->mesh.descriptor_pool, //
|
|
|
|
0); //
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
U_ZERO(rr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* 'Exported' draw functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_begin_target(struct render_gfx *rr, struct render_gfx_target_resources *rtr)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2021-01-14 14:13:48 +00:00
|
|
|
|
2021-11-03 13:28:15 +00:00
|
|
|
assert(rr->rtr == NULL);
|
|
|
|
rr->rtr = rtr;
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
// This is shared across both views.
|
2021-09-23 19:11:53 +00:00
|
|
|
begin_render_pass(vk, //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
rr->r->cmd, //
|
2021-11-03 13:28:15 +00:00
|
|
|
rr->rtr->render_pass, //
|
|
|
|
rr->rtr->framebuffer, //
|
|
|
|
rr->rtr->data.width, //
|
|
|
|
rr->rtr->data.height); //
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_end_target(struct render_gfx *rr)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2020-10-05 22:30:31 +00:00
|
|
|
|
2021-11-03 13:28:15 +00:00
|
|
|
assert(rr->rtr != NULL);
|
|
|
|
rr->rtr = NULL;
|
2020-10-05 22:30:31 +00:00
|
|
|
|
2021-09-23 19:11:53 +00:00
|
|
|
// Stop the [shared] render pass.
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
vk->vkCmdEndRenderPass(rr->r->cmd);
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_begin_view(struct render_gfx *rr, uint32_t view, struct render_viewport_data *viewport_data)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2020-10-05 22:30:31 +00:00
|
|
|
|
2021-09-23 19:11:53 +00:00
|
|
|
// We currently only support two views.
|
2020-10-05 22:30:31 +00:00
|
|
|
assert(view == 0 || view == 1);
|
2021-11-03 13:28:15 +00:00
|
|
|
assert(rr->rtr != NULL);
|
2021-09-23 19:11:53 +00:00
|
|
|
|
|
|
|
rr->current_view = view;
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Viewport
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkViewport viewport = {
|
2022-04-30 13:44:24 +00:00
|
|
|
.x = (float)viewport_data->x,
|
|
|
|
.y = (float)viewport_data->y,
|
|
|
|
.width = (float)viewport_data->w,
|
|
|
|
.height = (float)viewport_data->h,
|
2020-10-05 22:30:31 +00:00
|
|
|
.minDepth = 0.0f,
|
|
|
|
.maxDepth = 1.0f,
|
|
|
|
};
|
|
|
|
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
vk->vkCmdSetViewport(rr->r->cmd, // commandBuffer
|
2020-10-05 22:30:31 +00:00
|
|
|
0, // firstViewport
|
|
|
|
1, // viewportCount
|
|
|
|
&viewport); // pViewports
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scissor
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkRect2D scissor = {
|
|
|
|
.offset =
|
|
|
|
{
|
|
|
|
.x = viewport_data->x,
|
|
|
|
.y = viewport_data->y,
|
|
|
|
},
|
|
|
|
.extent =
|
|
|
|
{
|
|
|
|
.width = viewport_data->w,
|
|
|
|
.height = viewport_data->h,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
vk->vkCmdSetScissor(rr->r->cmd, // commandBuffer
|
|
|
|
0, // firstScissor
|
|
|
|
1, // scissorCount
|
|
|
|
&scissor); // pScissors
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_end_view(struct render_gfx *rr)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-09-23 19:11:53 +00:00
|
|
|
//! Must have a current target.
|
2021-11-03 13:28:15 +00:00
|
|
|
assert(rr->rtr != NULL);
|
2020-10-05 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_distortion(struct render_gfx *rr)
|
2020-10-05 22:30:31 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2022-03-27 21:10:25 +00:00
|
|
|
struct render_resources *r = rr->r;
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
uint32_t view = rr->current_view;
|
2022-03-27 21:10:25 +00:00
|
|
|
struct render_gfx_view *v = &rr->views[view];
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Descriptors and pipeline.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkDescriptorSet descriptor_sets[1] = {v->mesh.descriptor_set};
|
|
|
|
vk->vkCmdBindDescriptorSets( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2020-10-05 22:30:31 +00:00
|
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
|
|
|
|
r->mesh.pipeline_layout, // layout
|
|
|
|
0, // firstSet
|
|
|
|
ARRAY_SIZE(descriptor_sets), // descriptorSetCount
|
|
|
|
descriptor_sets, // pDescriptorSets
|
|
|
|
0, // dynamicOffsetCount
|
|
|
|
NULL); // pDynamicOffsets
|
|
|
|
|
|
|
|
vk->vkCmdBindPipeline( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2020-10-05 22:30:31 +00:00
|
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
|
2021-11-03 13:28:15 +00:00
|
|
|
rr->rtr->mesh.pipeline); // pipeline
|
2020-10-05 22:30:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Vertex buffer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkBuffer buffers[1] = {r->mesh.vbo.buffer};
|
|
|
|
VkDeviceSize offsets[1] = {0};
|
|
|
|
assert(ARRAY_SIZE(buffers) == ARRAY_SIZE(offsets));
|
|
|
|
|
|
|
|
vk->vkCmdBindVertexBuffers( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2020-10-05 22:30:31 +00:00
|
|
|
0, // firstBinding
|
|
|
|
ARRAY_SIZE(buffers), // bindingCount
|
|
|
|
buffers, // pBuffers
|
|
|
|
offsets); // pOffsets
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Draw with indices or not?
|
|
|
|
*/
|
|
|
|
|
2021-11-08 21:02:03 +00:00
|
|
|
if (r->mesh.index_count_total > 0) {
|
2020-10-05 22:30:31 +00:00
|
|
|
vk->vkCmdBindIndexBuffer( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2020-10-05 22:30:31 +00:00
|
|
|
r->mesh.ibo.buffer, // buffer
|
|
|
|
0, // offset
|
|
|
|
VK_INDEX_TYPE_UINT32); // indexType
|
|
|
|
|
2021-11-08 21:02:03 +00:00
|
|
|
vk->vkCmdDrawIndexed( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2021-11-08 21:02:03 +00:00
|
|
|
r->mesh.index_counts[view], // indexCount
|
|
|
|
1, // instanceCount
|
|
|
|
r->mesh.index_offsets[view], // firstIndex
|
|
|
|
0, // vertexOffset
|
|
|
|
0); // firstInstance
|
2020-10-05 22:30:31 +00:00
|
|
|
} else {
|
|
|
|
vk->vkCmdDraw( //
|
c/render: render_resources has its own command pool;
Currently, there is a single command pool in the vk bundle, shared by
everyone. Since command pools (and command buffers allocated from those
pools) can only be used on one thread at a time, this requires locking.
However, the main point of having these annoying command pool things in
the first place is that you can use one for each thread/lifetime/area in
the app and avoid the overhead of the locks (both computational and
cognitive).
In this change I have given the rendering bits of the compositor its own
command pool. Instead of allocating and freeing a command buffer every
frame, a single command buffer is allocated from the pool during
initialization, and the pool is reset at the beginning of each frame.
Normally, multiple pools would need to be used, but this is not
necessary in monado because frames are serialized. The `TRANSIENT` and
`ONE_TIME_SUBMIT` flags have been added, which can allow for some driver
optimizations. The render code no longer takes out the command pool
mutex. The shared command pool is still there for a few remaining
places where vulkan work needs to be done outside the compositor.
I used the command buffer vulkan helpers when possible, but I would
maybe propose the idea of removing them, since they aren't really
wrapping much at this point. The `C` macro helps a lot and it's a bit
easier to see the Vulkan details in front of you instead of needing to
switch back and forth between the helper.
Later, I think it would be cool to apply and document some constraints
like "the queue is only accessed in functions XYZ, the render_resources
command pool must only be accessed in layer_commit from 1 thread" etc.
2022-05-26 22:19:51 +00:00
|
|
|
r->cmd, // commandBuffer
|
2021-11-08 21:02:03 +00:00
|
|
|
r->mesh.vertex_count, // vertexCount
|
2020-10-05 22:30:31 +00:00
|
|
|
1, // instanceCount
|
|
|
|
0, // firstVertex
|
|
|
|
0); // firstInstance
|
|
|
|
}
|
|
|
|
}
|
2021-04-15 20:25:39 +00:00
|
|
|
|
|
|
|
void
|
2022-03-27 21:10:25 +00:00
|
|
|
render_gfx_update_distortion(struct render_gfx *rr,
|
|
|
|
uint32_t view_index,
|
|
|
|
VkSampler sampler,
|
|
|
|
VkImageView image_view,
|
|
|
|
struct render_gfx_mesh_ubo_data *data)
|
2021-04-15 20:25:39 +00:00
|
|
|
{
|
2021-11-02 13:54:16 +00:00
|
|
|
struct vk_bundle *vk = vk_from_rr(rr);
|
2022-03-27 21:10:25 +00:00
|
|
|
struct render_resources *r = rr->r;
|
|
|
|
struct render_gfx_view *v = &rr->views[view_index];
|
2021-04-15 20:25:39 +00:00
|
|
|
|
2022-03-27 21:10:25 +00:00
|
|
|
render_buffer_write(vk, &r->mesh.ubos[view_index], data, sizeof(struct render_gfx_mesh_ubo_data));
|
2021-09-29 16:35:05 +00:00
|
|
|
|
|
|
|
update_mesh_discriptor_set( //
|
|
|
|
vk, // vk_bundle
|
|
|
|
r->mesh.src_binding, // src_binding
|
|
|
|
sampler, // sampler
|
|
|
|
image_view, // image_view
|
|
|
|
r->mesh.ubo_binding, // ubo_binding
|
|
|
|
r->mesh.ubos[view_index].buffer, // buffer
|
|
|
|
VK_WHOLE_SIZE, // size
|
|
|
|
v->mesh.descriptor_set); // descriptor_set
|
2021-04-15 20:25:39 +00:00
|
|
|
}
|