[Piglit] [v2 4/7] ext_memory_object: Support for setting up vulkan framebuffer
Andres Rodriguez
andresx7 at gmail.com
Tue Dec 19 01:22:25 UTC 2017
On 2017-12-18 08:17 AM, Topi Pohjolainen wrote:
> v2: Store image size in order to know how much memory to import,
> see glImportMemoryFdEXT().
>
> Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
> ---
> tests/spec/ext_memory_object/vk_common.h | 34 ++++
> tests/spec/ext_memory_object/vk_fb.c | 304 +++++++++++++++++++++++++++++++
> 2 files changed, 338 insertions(+)
> create mode 100644 tests/spec/ext_memory_object/vk_fb.c
>
> diff --git a/tests/spec/ext_memory_object/vk_common.h b/tests/spec/ext_memory_object/vk_common.h
> index 590735253..3ad8fd6c3 100644
> --- a/tests/spec/ext_memory_object/vk_common.h
> +++ b/tests/spec/ext_memory_object/vk_common.h
> @@ -34,12 +34,46 @@ struct vk_vertex_buffer {
> VkDeviceMemory mem;
> };
>
> +struct vk_image {
> + VkImage image;
> + VkDeviceMemory mem;
> + VkDeviceSize size;
> +};
> +
> +struct vk_attachment {
> + struct vk_image image;
> + VkImageView view;
> +};
> +
> +struct vk_fb {
> + struct vk_attachment color;
> + struct vk_attachment depth;
> + VkRenderPass render_pass;
> + VkFramebuffer fb;
> +};
> +
> VkDevice
> vk_init(void);
>
> void
> vk_cleanup(void);
>
> +void
> +vk_create_image(VkDevice dev, VkFormat format,
> + unsigned w, unsigned h, unsigned z, unsigned num_samples,
> + unsigned num_levels, unsigned num_layers,
> + VkImageUsageFlagBits usage, VkImageTiling tiling,
> + struct vk_image *image);
> +
> +void
> +vk_setup_fb(VkDevice dev, unsigned w, unsigned h, unsigned num_samples,
> + VkFormat color_fmt, VkImageTiling color_tiling,
> + VkFormat depth_fmt, VkImageTiling depth_tiling,
> + unsigned layers, struct vk_fb *fb);
> +
> +void
> +vk_fb_destroy(VkDevice dev, struct vk_fb *fb);
> +
> VkRenderPass
> vk_create_render_pass(VkFormat format, unsigned num_samples,
> VkImageLayout sub_pass_layout,
> diff --git a/tests/spec/ext_memory_object/vk_fb.c b/tests/spec/ext_memory_object/vk_fb.c
> new file mode 100644
> index 000000000..4cb2b3722
> --- /dev/null
> +++ b/tests/spec/ext_memory_object/vk_fb.c
> @@ -0,0 +1,304 @@
> +/*
> + * Copyright 2017 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "vk_common.h"
> +#include "piglit-util-gl.h"
> +
> +static void
> +vk_destroy_image(VkDevice dev, struct vk_image *image)
> +{
> + if (image->image != VK_NULL_HANDLE)
> + vkDestroyImage(dev, image->image, NULL);
> +
> + if (image->mem != VK_NULL_HANDLE)
> + vkFreeMemory(dev, image->mem, NULL);
> +}
> +
> +void
> +vk_create_image(VkDevice dev, VkFormat format,
> + unsigned w, unsigned h, unsigned z, unsigned num_samples,
> + unsigned num_levels, unsigned num_layers,
> + VkImageUsageFlagBits usage, VkImageTiling tiling,
> + struct vk_image *image)
> +{
> + const VkImageType image_type =
> + z > 1 ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
> + const VkImageCreateInfo info = {
> + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
> + .imageType = image_type,
> + .tiling = tiling,
> + .mipLevels = num_levels,
> + .arrayLayers = num_layers,
> + .samples = (VkSampleCountFlagBits)num_samples,
> + .format = format,
> + .extent = {
> + .width = w,
> + .height = h,
> + .depth = z,
> + },
> + .usage = usage,
> + };
> + VkMemoryRequirements mem_reqs;
> +
> + image->image = VK_NULL_HANDLE;
> + image->mem = VK_NULL_HANDLE;
> +
> + if (vkCreateImage(dev, &info, NULL, &image->image) != VK_SUCCESS)
> + goto fail;
> +
> + vkGetImageMemoryRequirements(dev, image->image, &mem_reqs);
> +
> + image->mem = vk_alloc_mem(
> + dev, &mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
> + if (image->mem == VK_NULL_HANDLE)
> + goto fail;
> +
> + image->size = mem_reqs.size;
> +
> + if (vkBindImageMemory(dev, image->image, image->mem, 0) == VK_SUCCESS)
> + return;
Small style nitpick, this is backwards from most other calls which are
of the style:
if (vkCall())
handleFailure();
Which makes it a little weird when skimming through the code. It would
probably be more standard to do
if (vkBindImageMemory() != VK_SUCCESS
goto fail;
return;
That way there is also no implicit fall-through to the failure handler.
> +
> +fail:
> + vk_destroy_image(dev, image);
> + image->image = VK_NULL_HANDLE;
> + image->mem = VK_NULL_HANDLE;
> +}
> +
> +static VkImageView
> +vk_create_image_view(VkDevice dev, VkImage image, VkFormat format,
> + VkImageAspectFlagBits aspect_mask,
> + unsigned base_level, unsigned level_count,
> + unsigned base_layer, unsigned layer_count)
> +{
> + const VkImageViewType type = layer_count > 1 ?
> + VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
> +
> + const VkImageViewCreateInfo info = {
> + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
> + .viewType = type,
> + .image = image,
> + .format = format,
> + .subresourceRange = {
> + .aspectMask = aspect_mask,
> + .baseMipLevel = base_level,
> + .levelCount = level_count,
> + .baseArrayLayer = base_layer,
> + .layerCount = layer_count,
> + },
> + };
> + VkImageView view = VK_NULL_HANDLE;
> +
> + if (vkCreateImageView(dev, &info, NULL, &view) != VK_SUCCESS)
> + view = VK_NULL_HANDLE;
> +
> + return view;
> +}
> +
> +static void
> +vk_create_attachment(VkDevice dev, VkFormat format,
> + unsigned w, unsigned h, unsigned num_samples,
> + VkImageAspectFlagBits aspect_mask,
> + VkImageUsageFlagBits usage, VkImageTiling tiling,
> + unsigned base_level, unsigned level_count,
> + unsigned base_layer, unsigned layer_count,
> + struct vk_attachment *att)
> +{
> + att->image.image = VK_NULL_HANDLE;
> + vk_create_image(dev, format, w, h, 1, num_samples,
> + level_count, layer_count, usage, tiling, &att->image);
> + if (att->image.image == VK_NULL_HANDLE)
> + return;
> +
> + att->view = vk_create_image_view(
> + dev, att->image.image, format, aspect_mask,
> + base_level, level_count, base_layer, layer_count);
> + if (att->view == VK_NULL_HANDLE) {
> + vk_destroy_image(dev, &att->image);
> + att->image.image = VK_NULL_HANDLE;
> + att->image.mem = VK_NULL_HANDLE;
> + }
> +}
> +
> +static VkRenderPass
> +vk_create_fb_render_pass(VkDevice dev, unsigned num_samples,
> + VkFormat color_format, VkFormat depth_format)
> +{
> + const bool has_depth = depth_format != VK_FORMAT_UNDEFINED;
> + const VkAttachmentDescription attachments[] = {
> + {
> + .samples = (VkSampleCountFlagBits)num_samples,
> + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
> + .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
> + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
> + .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
> + .format = color_format
> + },
> + {
> + .samples = VK_SAMPLE_COUNT_1_BIT,
> + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
> + .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
> + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
> + .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
> + .format = depth_format
> + }
> + };
> + const VkAttachmentReference color_ref = {
> + .attachment = 0,
> + .layout = VK_IMAGE_LAYOUT_GENERAL,
> + };
> + const VkAttachmentReference depth_ref = {
> + .attachment = 1,
> + .layout = VK_IMAGE_LAYOUT_GENERAL,
> + };
> + const VkSubpassDescription sub_pass = {
> + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
> + .colorAttachmentCount = 1,
> + .pColorAttachments = &color_ref,
> + .pDepthStencilAttachment = has_depth ? &depth_ref : NULL,
> + };
> + const VkRenderPassCreateInfo info = {
> + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
> + .attachmentCount = has_depth ? 2 : 1,
> + .pAttachments = attachments,
> + .subpassCount = 1,
> + .pSubpasses = &sub_pass,
> + };
> + VkRenderPass pass = VK_NULL_HANDLE;
> + if (vkCreateRenderPass(dev, &info, NULL, &pass) != VK_SUCCESS)
> + pass = VK_NULL_HANDLE;
> +
> + return pass;
> +}
> +
> +static VkFramebuffer
> +vk_create_fb(VkDevice dev, VkRenderPass render_pass,
> + unsigned w, unsigned h, unsigned layers,
> + VkImageView color_view, VkImageView depth_view)
> +{
> + const VkImageView attachments[2] = { color_view, depth_view };
> + const VkFramebufferCreateInfo info = {
> + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
> + .renderPass = render_pass,
> + .width = w,
> + .height = h,
> + .layers = layers,
> + .attachmentCount = depth_view != VK_NULL_HANDLE ? 2 : 1,
> + .pAttachments = attachments,
> + };
> + VkFramebuffer fb = VK_NULL_HANDLE;
> +
> + if (vkCreateFramebuffer(dev, &info, NULL, &fb) != VK_SUCCESS)
> + fb = VK_NULL_HANDLE;
> +
> + return fb;
> +}
> +
> +static VkImageAspectFlagBits
> +vk_get_depth_stencil_aspect_mask(VkFormat format)
> +{
> + switch (format) {
> + case VK_FORMAT_D16_UNORM:
> + case VK_FORMAT_X8_D24_UNORM_PACK32:
> + case VK_FORMAT_D32_SFLOAT:
> + return VK_IMAGE_ASPECT_DEPTH_BIT;
> + case VK_FORMAT_S8_UINT:
> + return VK_IMAGE_ASPECT_STENCIL_BIT;
> + case VK_FORMAT_D16_UNORM_S8_UINT:
> + case VK_FORMAT_D24_UNORM_S8_UINT:
> + case VK_FORMAT_D32_SFLOAT_S8_UINT:
> + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
> + default:
> + assert(!"Invalid depthstencil format");
> + }
> +}
> +
> +static void
> +vk_destroy_attachment(VkDevice dev, struct vk_attachment *att)
> +{
> + if (att->view != VK_NULL_HANDLE)
> + vkDestroyImageView(dev, att->view, NULL);
> +
> + vk_destroy_image(dev, &att->image);
> +}
> +
> +void
> +vk_fb_destroy(VkDevice dev, struct vk_fb *fb)
> +{
> + if (fb->fb != VK_NULL_HANDLE)
> + vkDestroyFramebuffer(dev, fb->fb, NULL);
> +
> + if (fb->render_pass != VK_NULL_HANDLE)
> + vkDestroyRenderPass(dev, fb->render_pass, NULL);
> +
> + vk_destroy_attachment(dev, &fb->color);
> + vk_destroy_attachment(dev, &fb->depth);
> +}
> +
> +void
> +vk_setup_fb(VkDevice dev, unsigned w, unsigned h, unsigned num_samples,
> + VkFormat color_format, VkImageTiling color_tiling,
> + VkFormat depth_format, VkImageTiling depth_tiling,
> + unsigned layers, struct vk_fb *fb)
> +{
> + const VkImageUsageFlagBits usage = VK_IMAGE_USAGE_SAMPLED_BIT |
> + VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
> +
> + (void)memset(fb, 0, sizeof(*fb));
Is there a reason for the cast here (silencing a warning or something
like that)?
> +
> + if (color_format != VK_FORMAT_UNDEFINED) {
> + vk_create_attachment(
> + dev, color_format, w, h, num_samples,
> + VK_IMAGE_ASPECT_COLOR_BIT,
> + usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
> + color_tiling, 0, 1, 0, layers, &fb->color);
> + if (fb->color.image.image == VK_NULL_HANDLE)
> + return;
Might want to 'goto fail' here in case something else is added, doesn't
hurt and might prevent a future leak if someone adds code above this
condition.
> + }
> +
> + if (depth_format != VK_FORMAT_UNDEFINED) {
> + const VkImageAspectFlagBits aspect_mask =
> + vk_get_depth_stencil_aspect_mask(depth_format);
> +
> + vk_create_attachment(
> + dev, depth_format, w, h, num_samples,
> + aspect_mask,
> + usage | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
> + depth_tiling, 0, 1, 0, layers, &fb->depth);
> + if (fb->depth.image.image == VK_NULL_HANDLE)
> + goto fail;
> + }
> +
> + fb->render_pass = vk_create_fb_render_pass(
> + dev, num_samples, color_format, depth_format);
> + if (fb->render_pass == VK_NULL_HANDLE)
> + goto fail;
> +
> + fb->fb = vk_create_fb(dev, fb->render_pass, w, h, layers,
> + fb->color.view, fb->depth.view);
> + if (fb->fb != VK_NULL_HANDLE)
> + return;
> +
> +fail:
> + vk_fb_destroy(dev, fb);
> + (void)memset(fb, 0, sizeof(*fb));
> +}
>
More information about the Piglit
mailing list