[Piglit] [v3 06/11] ext_memory_object: Support for setting up vulkan framebuffer
Andres Rodriguez
andresx7 at gmail.com
Thu Dec 21 16:38:18 UTC 2017
On 2017-12-21 11:30 AM, Pohjolainen, Topi wrote:
> On Thu, Dec 21, 2017 at 11:25:04AM -0500, Andres Rodriguez wrote:
>>
>>
>> On 2017-12-21 07:02 AM, Topi Pohjolainen wrote:
>>> v2: Store image size in order to know how much memory to import,
>>> see glImportMemoryFdEXT().
>>>
>>> v3:
>>> - use "goto fail" for all failure paths (Andres)
>>> - use VkExternalMemoryImageCreateInfoKHR (Fredrik)
>>> - check for dedicated using
>>> vkGetImageMemoryRequirements2KHR() (Fredrik)
>>>
>>> Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
>>> ---
>>> tests/spec/ext_memory_object/vk_common.c | 13 ++
>>> tests/spec/ext_memory_object/vk_common.h | 53 +++++
>>> tests/spec/ext_memory_object/vk_fb.c | 346 +++++++++++++++++++++++++++++++
>>> 3 files changed, 412 insertions(+)
>>> create mode 100644 tests/spec/ext_memory_object/vk_fb.c
>>>
>>> diff --git a/tests/spec/ext_memory_object/vk_common.c b/tests/spec/ext_memory_object/vk_common.c
>>> index 2c664742a..eaecdf8cd 100644
>>> --- a/tests/spec/ext_memory_object/vk_common.c
>>> +++ b/tests/spec/ext_memory_object/vk_common.c
>>> @@ -570,3 +570,16 @@ vk_create_fence(VkDevice dev)
>>> return fence;
>>> }
>>> +
>>> +PFN_vkGetImageMemoryRequirements2KHR
>>> +vk_get_proc_addr_for_image_mem_req(VkDevice dev)
>>> +{
>>> + static PFN_vkGetImageMemoryRequirements2KHR get_mem_req = NULL;
>>> +
>>> + if (get_mem_req == NULL)
>>> + get_mem_req = (PFN_vkGetImageMemoryRequirements2KHR)
>>> + vkGetDeviceProcAddr(
>>> + dev, "vkGetImageMemoryRequirements2KHR");
>>> +
>>> + return get_mem_req;
>>> +}
>>> diff --git a/tests/spec/ext_memory_object/vk_common.h b/tests/spec/ext_memory_object/vk_common.h
>>> index b4c22575c..c9d920523 100644
>>> --- a/tests/spec/ext_memory_object/vk_common.h
>>> +++ b/tests/spec/ext_memory_object/vk_common.h
>>> @@ -44,12 +44,62 @@ 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;
>>> +};
>>> +
>>> +static inline VkImageType
>>> +vk_get_image_type(unsigned h, unsigned z)
>>> +{
>>> + if (h == 1)
>>> + return VK_IMAGE_TYPE_1D;
>>> +
>>> + if (z > 1)
>>> + return VK_IMAGE_TYPE_3D;
>>> +
>>> + return VK_IMAGE_TYPE_2D;
>>> +}
>>> +
>>> void
>>> vk_core_init(struct vk_core *core);
>>> void
>>> vk_core_cleanup(struct vk_core *core);
>>> +void
>>> +vk_create_image(struct vk_core *core, 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_destroy_image(VkDevice dev, struct vk_image *image);
>>> +
>>> +void
>>> +vk_setup_fb(struct vk_core *core,
>>> + 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(VkDevice dev,
>>> VkFormat format, unsigned num_samples,
>>> @@ -88,4 +138,7 @@ vk_draw(struct vk_core *core, VkPipeline pipeline, VkBuffer vb, VkFence fence);
>>> VkFence
>>> vk_create_fence(VkDevice dev);
>>> +PFN_vkGetImageMemoryRequirements2KHR
>>> +vk_get_proc_addr_for_image_mem_req(VkDevice dev);
>>> +
>>> #endif
>>> 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..42609e900
>>> --- /dev/null
>>> +++ b/tests/spec/ext_memory_object/vk_fb.c
>>> @@ -0,0 +1,346 @@
>>> +/*
>>> + * 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"
>>> +
>>> +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);
>>> +}
>>> +
>>> +static void
>>> +vk_alloc_image_mem(struct vk_core *core, struct vk_image *image)
>>> +{
>>> + const VkImageMemoryRequirementsInfo2KHR req_info = {
>>> + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
>>> + .image = image->image
>>> + };
>>> + VkMemoryDedicatedRequirementsKHR dedicated_info = {
>>> + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR
>>> + };
>>> + VkMemoryRequirements2KHR mem_reqs = {
>>> + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
>>> + .pNext = &dedicated_info
>>> + };
>>> + PFN_vkGetImageMemoryRequirements2KHR vk_get_image_mem_req_2_khr =
>>> + vk_get_proc_addr_for_image_mem_req(core->dev);
>>> +
>>> + vk_get_image_mem_req_2_khr(core->dev, &req_info, &mem_reqs);
>>> +
>>> + if (dedicated_info.requiresDedicatedAllocation) {
>>> + VkMemoryDedicatedAllocateInfoKHR dedicated_alloc_info = {
>>> + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
>>> + .image = image->image
>>> + };
>>> +
>>> + image->mem = vk_alloc_mem(
>>> + core, &mem_reqs.memoryRequirements,
>>> + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
>>
>> Also need to check if DEVICE_LOCAL_BIT is supported by
>> mem_reqs.memoryTypeBits.
>
> Ok, I'll look into that, thanks!
>
>>
>>
>>> + &dedicated_alloc_info);
>>> + } else {
>>> + image->mem = vk_alloc_mem(
>>> + core, &mem_reqs.memoryRequirements,
>>> + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
>>> + NULL);
>>> + }
>>> +
>>
>> To avoid duplicated codepaths here:
>>
>> void *pExt = VK_NULL_HANDLE;
>> VkMemoryDedicatedAllocateInfoKHR dedicated_alloc_info = { ... };
>> pExt = dedicated_info.requiresDedicatedAllocation ?
>> dedicated_alloc_info : VK_NULL_HANDLE;
>
> I thought about that but didn't like to include dedicated_alloc_info on path
> that wouldn't need it. But I'm just as fine doing it this way. I'll see what
> it looks like when I get the LOCAL_BIT addressed.
>
Yeah, in its current state it is fine. Just a small suggestion since the
file is going to be changed anyways :)
Sometimes these functions grow little by little and end up as giant
monsters. And they don't always get unified when needed.
>>
>>
>>
>>> + image->size = mem_reqs.memoryRequirements.size;
>>> +}
>>> +
>>> +void
>>> +vk_create_image(struct vk_core *core, 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 VkExternalMemoryImageCreateInfoKHR ext_image_info = {
>>> + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
>>> + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
>>> + };
>>> + const VkImageCreateInfo info = {
>>> + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
>>> + .pNext = &ext_image_info,
>>> + .imageType = vk_get_image_type(h, z),
>>> + .tiling = tiling,
>>> + .mipLevels = num_levels,
>>> + .arrayLayers = num_layers,
>>> + .samples = (VkSampleCountFlagBits)num_samples,
>>> + .format = format,
>>> + .extent = {
>>> + .width = w,
>>> + .height = h,
>>> + .depth = z,
>>> + },
>>> + .usage = usage,
>>> + };
>>> +
>>> + image->image = VK_NULL_HANDLE;
>>> + image->mem = VK_NULL_HANDLE;
>>> +
>>> + if (vkCreateImage(
>>> + core->dev, &info, NULL, &image->image) != VK_SUCCESS)
>>> + goto fail;
>>> +
>>> + vk_alloc_image_mem(core, image);
>>> + if (image->mem == VK_NULL_HANDLE)
>>> + goto fail;
>>> +
>>> + if (vkBindImageMemory(
>>> + core->dev, image->image, image->mem, 0) != VK_SUCCESS)
>>> + goto fail;
>>> +
>>> + return;
>>> +
>>> +fail:
>>> + vk_destroy_image(core->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(struct vk_core *core, 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(core, 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(
>>> + core->dev, att->image.image, format, aspect_mask,
>>> + base_level, level_count, base_layer, layer_count);
>>> + if (att->view == VK_NULL_HANDLE) {
>>> + vk_destroy_image(core->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(struct vk_core *core,
>>> + 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));
>>> +
>>> + if (color_format != VK_FORMAT_UNDEFINED) {
>>> + vk_create_attachment(
>>> + core, 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;
>>> + }
>>> +
>>> + if (depth_format != VK_FORMAT_UNDEFINED) {
>>> + const VkImageAspectFlagBits aspect_mask =
>>> + vk_get_depth_stencil_aspect_mask(depth_format);
>>> +
>>> + vk_create_attachment(
>>> + core, 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(
>>> + core->dev, num_samples, color_format, depth_format);
>>> + if (fb->render_pass == VK_NULL_HANDLE)
>>> + goto fail;
>>> +
>>> + fb->fb = vk_create_fb(
>>> + core->dev, fb->render_pass, w, h, layers,
>>> + fb->color.view, fb->depth.view);
>>> + if (fb->fb != VK_NULL_HANDLE)
>>> + return;
>>> +
>>> +fail:
>>> + vk_fb_destroy(core->dev, fb);
>>> + (void)memset(fb, 0, sizeof(*fb));
>>> +}
>>>
More information about the Piglit
mailing list