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)

v4:
    - check also memoryTypeBits and
      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT (Andres)
    - unify allocation code paths (Andres)

CC: Andres Rodriguez <andre...@gmail.com>
Signed-off-by: Topi Pohjolainen <topi.pohjolai...@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     | 340 +++++++++++++++++++++++++++++++
 3 files changed, 406 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 164b61108..916ec44a5 100644
--- a/tests/spec/ext_memory_object/vk_common.c
+++ b/tests/spec/ext_memory_object/vk_common.c
@@ -572,3 +572,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..31e746dd6
--- /dev/null
+++ b/tests/spec/ext_memory_object/vk_fb.c
@@ -0,0 +1,340 @@
+/*
+ * 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
+       };
+       const VkMemoryDedicatedAllocateInfoKHR dedicated_alloc_info = {
+               .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_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);
+
+       image->mem = vk_alloc_mem(
+               core, &mem_reqs.memoryRequirements,
+               mem_reqs.memoryRequirements.memoryTypeBits &
+               VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+               dedicated_info.requiresDedicatedAllocation ?
+                       &dedicated_alloc_info : NULL);
+
+       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));
+}
-- 
2.14.1

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to