2020-05-08 19:25:25 +00:00
|
|
|
// Copyright 2020, Collabora, Ltd.
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief Compositor quad rendering.
|
|
|
|
* @author Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
|
|
|
|
* @ingroup comp_main
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "comp_layer.h"
|
|
|
|
|
|
|
|
#include "util/u_misc.h"
|
|
|
|
#include "math/m_api.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
// Projection layers span from -1 to 1, the vertex buffer and quad layers
|
|
|
|
// from -0.5 to 0.5, so this scale matrix needs to be applied for proj layers.
|
|
|
|
static struct xrt_matrix_4x4 proj_scale = {
|
|
|
|
.v = {
|
|
|
|
2, 0, 0, 0,
|
|
|
|
0, 2, 0, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 0, 1
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_set_flip_y(struct comp_render_layer *self, bool flip_y)
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < 2; i++)
|
|
|
|
self->transformation[i].flip_y = flip_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_set_model_matrix(struct comp_render_layer *self,
|
|
|
|
const struct xrt_matrix_4x4 *m)
|
|
|
|
{
|
|
|
|
memcpy(&self->model_matrix, m, sizeof(struct xrt_matrix_4x4));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_update_mvp_matrix(struct comp_render_layer *self,
|
|
|
|
uint32_t eye,
|
|
|
|
const struct xrt_matrix_4x4 *vp)
|
|
|
|
{
|
|
|
|
math_matrix_4x4_multiply(vp, &self->model_matrix,
|
|
|
|
&self->transformation[eye].mvp);
|
|
|
|
memcpy(self->transformation_ubos[eye].data, &self->transformation[eye],
|
|
|
|
sizeof(struct layer_transformation));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
_init_ubos(struct comp_render_layer *self)
|
|
|
|
{
|
|
|
|
VkBufferUsageFlags usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
|
|
|
VkMemoryPropertyFlags properties =
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < 2; i++) {
|
|
|
|
math_matrix_4x4_identity(&self->transformation[i].mvp);
|
|
|
|
|
|
|
|
if (!vk_buffer_init(
|
|
|
|
self->vk, sizeof(struct layer_transformation), usage,
|
|
|
|
properties, &self->transformation_ubos[i].handle,
|
|
|
|
&self->transformation_ubos[i].memory))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
VkResult res = self->vk->vkMapMemory(
|
|
|
|
self->vk->device, self->transformation_ubos[i].memory, 0,
|
|
|
|
VK_WHOLE_SIZE, 0, &self->transformation_ubos[i].data);
|
|
|
|
vk_check_error("vkMapMemory", res, false);
|
|
|
|
|
|
|
|
memcpy(self->transformation_ubos[i].data,
|
|
|
|
&self->transformation[i],
|
|
|
|
sizeof(struct layer_transformation));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_update_descriptor(struct vk_bundle *vk,
|
|
|
|
VkDescriptorSet set,
|
|
|
|
VkBuffer transformation_buffer,
|
|
|
|
VkSampler sampler,
|
|
|
|
VkImageView image_view)
|
|
|
|
{
|
|
|
|
VkWriteDescriptorSet *sets = (VkWriteDescriptorSet[]){
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
.dstSet = set,
|
|
|
|
.dstBinding = 0,
|
|
|
|
.descriptorCount = 1,
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
.pBufferInfo =
|
|
|
|
&(VkDescriptorBufferInfo){
|
|
|
|
.buffer = transformation_buffer,
|
|
|
|
.offset = 0,
|
|
|
|
.range = VK_WHOLE_SIZE,
|
|
|
|
},
|
|
|
|
.pTexelBufferView = NULL,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
.dstSet = set,
|
|
|
|
.dstBinding = 1,
|
|
|
|
.descriptorCount = 1,
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
.pImageInfo =
|
|
|
|
&(VkDescriptorImageInfo){
|
|
|
|
.sampler = sampler,
|
|
|
|
.imageView = image_view,
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
|
|
},
|
|
|
|
.pBufferInfo = NULL,
|
|
|
|
.pTexelBufferView = NULL,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
vk->vkUpdateDescriptorSets(vk->device, 2, sets, 0, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_update_descriptors(struct comp_render_layer *self,
|
|
|
|
VkSampler sampler,
|
|
|
|
VkImageView image_view)
|
|
|
|
{
|
|
|
|
for (uint32_t eye = 0; eye < 2; eye++)
|
|
|
|
_update_descriptor(self->vk, self->descriptor_sets[eye],
|
|
|
|
self->transformation_ubos[eye].handle,
|
|
|
|
sampler, image_view);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_update_stereo_descriptors(struct comp_render_layer *self,
|
|
|
|
VkSampler left_sampler,
|
|
|
|
VkSampler right_sampler,
|
|
|
|
VkImageView left_image_view,
|
|
|
|
VkImageView right_image_view)
|
|
|
|
{
|
|
|
|
_update_descriptor(self->vk, self->descriptor_sets[0],
|
|
|
|
self->transformation_ubos[0].handle, left_sampler,
|
|
|
|
left_image_view);
|
|
|
|
|
|
|
|
_update_descriptor(self->vk, self->descriptor_sets[1],
|
|
|
|
self->transformation_ubos[1].handle, right_sampler,
|
|
|
|
right_image_view);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
_init(struct comp_render_layer *self,
|
|
|
|
struct vk_bundle *vk,
|
|
|
|
VkDescriptorSetLayout *layout)
|
|
|
|
{
|
|
|
|
self->vk = vk;
|
|
|
|
|
2020-06-15 17:39:47 +00:00
|
|
|
self->view_space = true;
|
2020-06-05 13:36:26 +00:00
|
|
|
self->visibility = XRT_LAYER_EYE_VISIBILITY_BOTH;
|
2020-05-08 19:25:25 +00:00
|
|
|
|
|
|
|
math_matrix_4x4_identity(&self->model_matrix);
|
|
|
|
|
|
|
|
if (!_init_ubos(self))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
uint32_t set_count = 2;
|
|
|
|
|
|
|
|
VkDescriptorPoolSize pool_sizes[] = {
|
|
|
|
{
|
|
|
|
.descriptorCount = set_count,
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.descriptorCount = set_count,
|
|
|
|
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!vk_init_descriptor_pool(self->vk, pool_sizes,
|
|
|
|
ARRAY_SIZE(pool_sizes), set_count,
|
|
|
|
&self->descriptor_pool))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (uint32_t eye = 0; eye < set_count; eye++)
|
|
|
|
if (!vk_allocate_descriptor_sets(
|
|
|
|
self->vk, self->descriptor_pool, 1, layout,
|
|
|
|
&self->descriptor_sets[eye]))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_draw(struct comp_render_layer *self,
|
|
|
|
uint32_t eye,
|
|
|
|
VkPipeline pipeline,
|
|
|
|
VkPipelineLayout pipeline_layout,
|
|
|
|
VkCommandBuffer cmd_buffer,
|
|
|
|
const struct vk_buffer *vertex_buffer,
|
2020-06-15 17:39:47 +00:00
|
|
|
const struct xrt_matrix_4x4 *vp_world,
|
|
|
|
const struct xrt_matrix_4x4 *vp_eye)
|
2020-05-08 19:25:25 +00:00
|
|
|
{
|
2020-06-05 13:36:26 +00:00
|
|
|
if (eye == 0 &&
|
|
|
|
(self->visibility & XRT_LAYER_EYE_VISIBILITY_LEFT_BIT) == 0) {
|
2020-05-08 19:25:25 +00:00
|
|
|
return;
|
2020-06-05 13:36:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (eye == 1 &&
|
|
|
|
(self->visibility & XRT_LAYER_EYE_VISIBILITY_RIGHT_BIT) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2020-05-08 19:25:25 +00:00
|
|
|
|
|
|
|
self->vk->vkCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
pipeline);
|
|
|
|
|
2020-06-15 17:39:47 +00:00
|
|
|
// Is this layer viewspace or not.
|
|
|
|
const struct xrt_matrix_4x4 *vp = self->view_space ? vp_eye : vp_world;
|
|
|
|
|
2020-05-08 19:25:25 +00:00
|
|
|
switch (self->type) {
|
2020-06-04 12:29:41 +00:00
|
|
|
case XRT_LAYER_STEREO_PROJECTION:
|
2020-05-08 19:25:25 +00:00
|
|
|
_update_mvp_matrix(self, eye, &proj_scale);
|
|
|
|
break;
|
2020-06-04 12:29:41 +00:00
|
|
|
case XRT_LAYER_QUAD: _update_mvp_matrix(self, eye, vp); break;
|
2020-05-08 19:25:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self->vk->vkCmdBindDescriptorSets(
|
|
|
|
cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1,
|
|
|
|
&self->descriptor_sets[eye], 0, NULL);
|
|
|
|
|
|
|
|
VkDeviceSize offsets[1] = {0};
|
|
|
|
self->vk->vkCmdBindVertexBuffers(cmd_buffer, 0, 1,
|
|
|
|
&vertex_buffer->handle, &offsets[0]);
|
|
|
|
|
|
|
|
self->vk->vkCmdDraw(cmd_buffer, vertex_buffer->size, 1, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct comp_render_layer *
|
2020-07-16 15:30:13 +00:00
|
|
|
comp_layer_create(struct vk_bundle *vk, VkDescriptorSetLayout *layout)
|
2020-05-08 19:25:25 +00:00
|
|
|
{
|
|
|
|
struct comp_render_layer *q = U_TYPED_CALLOC(struct comp_render_layer);
|
|
|
|
|
2020-07-16 15:30:13 +00:00
|
|
|
_init(q, vk, layout);
|
2020-05-08 19:25:25 +00:00
|
|
|
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
comp_layer_destroy(struct comp_render_layer *self)
|
|
|
|
{
|
|
|
|
for (uint32_t eye = 0; eye < 2; eye++)
|
|
|
|
vk_buffer_destroy(&self->transformation_ubos[eye], self->vk);
|
|
|
|
|
|
|
|
self->vk->vkDestroyDescriptorPool(self->vk->device,
|
|
|
|
self->descriptor_pool, NULL);
|
2020-08-05 16:42:52 +00:00
|
|
|
|
|
|
|
free(self);
|
2020-05-08 19:25:25 +00:00
|
|
|
}
|