2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "anv_private.h"
26 /* This file contains utility functions for help debugging. They can be
27 * called from GDB or similar to help inspect images and buffers.
35 VkDeviceMemory memory
;
39 dump_image_init(struct anv_device
*device
, struct dump_image
*image
,
40 uint32_t width
, uint32_t height
, const char *filename
)
42 VkDevice vk_device
= anv_device_to_handle(device
);
43 MAYBE_UNUSED VkResult result
;
45 image
->filename
= filename
;
46 image
->extent
= (VkExtent2D
) { width
, height
};
48 result
= anv_CreateImage(vk_device
,
49 &(VkImageCreateInfo
) {
50 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
51 .imageType
= VK_IMAGE_TYPE_2D
,
52 .format
= VK_FORMAT_R8G8B8A8_UNORM
,
53 .extent
= (VkExtent3D
) { width
, height
, 1 },
57 .tiling
= VK_IMAGE_TILING_LINEAR
,
58 .usage
= VK_IMAGE_USAGE_TRANSFER_DST_BIT
,
60 }, NULL
, &image
->image
);
61 assert(result
== VK_SUCCESS
);
63 VkMemoryRequirements reqs
;
64 anv_GetImageMemoryRequirements(vk_device
, image
->image
, &reqs
);
66 result
= anv_AllocateMemory(vk_device
,
67 &(VkMemoryAllocateInfo
) {
68 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
69 .allocationSize
= reqs
.size
,
71 }, NULL
, &image
->memory
);
72 assert(result
== VK_SUCCESS
);
74 result
= anv_BindImageMemory(vk_device
, image
->image
, image
->memory
, 0);
75 assert(result
== VK_SUCCESS
);
79 dump_image_finish(struct anv_device
*device
, struct dump_image
*image
)
81 VkDevice vk_device
= anv_device_to_handle(device
);
83 anv_DestroyImage(vk_device
, image
->image
, NULL
);
84 anv_FreeMemory(vk_device
, image
->memory
, NULL
);
88 dump_image_do_blit(struct anv_device
*device
, struct dump_image
*image
,
89 struct anv_cmd_buffer
*cmd_buffer
, struct anv_image
*src
,
90 VkImageAspectFlagBits aspect
,
91 unsigned miplevel
, unsigned array_layer
)
93 /* We need to do a blit so the image needs to be declared as sampled. The
94 * only thing these are used for is making sure we create the correct
95 * views, so it should be find to just stomp it and set it back.
97 VkImageUsageFlags old_usage
= src
->usage
;
98 src
->usage
|= VK_IMAGE_USAGE_SAMPLED_BIT
;
100 anv_CmdBlitImage(anv_cmd_buffer_to_handle(cmd_buffer
),
101 anv_image_to_handle(src
), VK_IMAGE_LAYOUT_GENERAL
,
102 image
->image
, VK_IMAGE_LAYOUT_GENERAL
, 1,
105 .aspectMask
= aspect
,
106 .mipLevel
= miplevel
,
107 .baseArrayLayer
= array_layer
,
112 { image
->extent
.width
, image
->extent
.height
, 1 },
115 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
122 { image
->extent
.width
, image
->extent
.height
, 1 },
124 }, VK_FILTER_NEAREST
);
126 src
->usage
= old_usage
;
128 ANV_CALL(CmdPipelineBarrier
)(anv_cmd_buffer_to_handle(cmd_buffer
),
129 VK_PIPELINE_STAGE_TRANSFER_BIT
,
130 VK_PIPELINE_STAGE_TRANSFER_BIT
,
131 true, 0, NULL
, 0, NULL
, 1,
132 &(VkImageMemoryBarrier
) {
133 .sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
,
134 .srcAccessMask
= VK_ACCESS_HOST_READ_BIT
,
135 .dstAccessMask
= VK_ACCESS_TRANSFER_WRITE_BIT
,
136 .oldLayout
= VK_IMAGE_LAYOUT_GENERAL
,
137 .newLayout
= VK_IMAGE_LAYOUT_GENERAL
,
138 .srcQueueFamilyIndex
= 0,
139 .dstQueueFamilyIndex
= 0,
140 .image
= image
->image
,
141 .subresourceRange
= (VkImageSubresourceRange
) {
142 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
152 dump_image_write_to_ppm(struct anv_device
*device
, struct dump_image
*image
)
154 VkDevice vk_device
= anv_device_to_handle(device
);
155 MAYBE_UNUSED VkResult result
;
157 VkMemoryRequirements reqs
;
158 anv_GetImageMemoryRequirements(vk_device
, image
->image
, &reqs
);
161 result
= anv_MapMemory(vk_device
, image
->memory
, 0, reqs
.size
, 0, (void **)&map
);
162 assert(result
== VK_SUCCESS
);
164 VkSubresourceLayout layout
;
165 anv_GetImageSubresourceLayout(vk_device
, image
->image
,
166 &(VkImageSubresource
) {
167 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
172 map
+= layout
.offset
;
174 FILE *file
= fopen(image
->filename
, "wb");
177 uint8_t *row
= malloc(image
->extent
.width
* 3);
180 fprintf(file
, "P6\n%d %d\n255\n", image
->extent
.width
, image
->extent
.height
);
181 for (unsigned y
= 0; y
< image
->extent
.height
; y
++) {
182 for (unsigned x
= 0; x
< image
->extent
.width
; x
++) {
183 row
[x
* 3 + 0] = map
[x
* 4 + 0];
184 row
[x
* 3 + 1] = map
[x
* 4 + 1];
185 row
[x
* 3 + 2] = map
[x
* 4 + 2];
187 fwrite(row
, 3, image
->extent
.width
, file
);
189 map
+= layout
.rowPitch
;
194 anv_UnmapMemory(vk_device
, image
->memory
);
198 anv_dump_image_to_ppm(struct anv_device
*device
,
199 struct anv_image
*image
, unsigned miplevel
,
200 unsigned array_layer
, VkImageAspectFlagBits aspect
,
201 const char *filename
)
203 VkDevice vk_device
= anv_device_to_handle(device
);
204 MAYBE_UNUSED VkResult result
;
206 const uint32_t width
= anv_minify(image
->extent
.width
, miplevel
);
207 const uint32_t height
= anv_minify(image
->extent
.height
, miplevel
);
209 struct dump_image dump
;
210 dump_image_init(device
, &dump
, width
, height
, filename
);
212 VkCommandPool commandPool
;
213 result
= anv_CreateCommandPool(vk_device
,
214 &(VkCommandPoolCreateInfo
) {
215 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
216 .queueFamilyIndex
= 0,
218 }, NULL
, &commandPool
);
219 assert(result
== VK_SUCCESS
);
222 result
= anv_AllocateCommandBuffers(vk_device
,
223 &(VkCommandBufferAllocateInfo
) {
224 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
225 .commandPool
= commandPool
,
226 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
227 .commandBufferCount
= 1,
229 assert(result
== VK_SUCCESS
);
231 result
= anv_BeginCommandBuffer(cmd
,
232 &(VkCommandBufferBeginInfo
) {
233 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
234 .flags
= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
,
236 assert(result
== VK_SUCCESS
);
238 dump_image_do_blit(device
, &dump
, anv_cmd_buffer_from_handle(cmd
), image
,
239 aspect
, miplevel
, array_layer
);
241 result
= anv_EndCommandBuffer(cmd
);
242 assert(result
== VK_SUCCESS
);
245 result
= anv_CreateFence(vk_device
,
246 &(VkFenceCreateInfo
) {
247 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
250 assert(result
== VK_SUCCESS
);
252 result
= anv_QueueSubmit(anv_queue_to_handle(&device
->queue
), 1,
254 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
255 .commandBufferCount
= 1,
256 .pCommandBuffers
= &cmd
,
258 assert(result
== VK_SUCCESS
);
260 result
= anv_WaitForFences(vk_device
, 1, &fence
, true, UINT64_MAX
);
261 assert(result
== VK_SUCCESS
);
263 anv_DestroyFence(vk_device
, fence
, NULL
);
264 anv_DestroyCommandPool(vk_device
, commandPool
, NULL
);
266 dump_image_write_to_ppm(device
, &dump
);
267 dump_image_finish(device
, &dump
);