[Piglit] [v3 06/11] ext_memory_object: Support for setting up vulkan framebuffer

Pohjolainen, Topi topi.pohjolainen at gmail.com
Thu Dec 21 16:30:39 UTC 2017


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.

> 
> 
> 
> > +	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