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.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 | 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, + &dedicated_alloc_info); + } else { + image->mem = vk_alloc_mem( + core, &mem_reqs.memoryRequirements, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 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