anv/dump: Refactor the guts into helpers

Reviewed-by: Chad Versace <chad.versace@intel.com>
This commit is contained in:
Jason Ekstrand
2016-06-15 15:01:45 -07:00
parent adbed7ae7a
commit 6ad183bf89
+175 -121
View File
@@ -27,6 +27,173 @@
* called from GDB or similar to help inspect images and buffers.
*/
struct dump_image {
const char *filename;
VkExtent2D extent;
VkImage image;
VkDeviceMemory memory;
};
static void
dump_image_init(struct anv_device *device, struct dump_image *image,
uint32_t width, uint32_t height, const char *filename)
{
VkDevice vk_device = anv_device_to_handle(device);
MAYBE_UNUSED VkResult result;
image->filename = filename;
image->extent = (VkExtent2D) { width, height };
result = anv_CreateImage(vk_device,
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_R8G8B8A8_UNORM,
.extent = (VkExtent3D) { width, height, 1 },
.mipLevels = 1,
.arrayLayers = 1,
.samples = 1,
.tiling = VK_IMAGE_TILING_LINEAR,
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
.flags = 0,
}, NULL, &image->image);
assert(result == VK_SUCCESS);
VkMemoryRequirements reqs;
anv_GetImageMemoryRequirements(vk_device, image->image, &reqs);
result = anv_AllocateMemory(vk_device,
&(VkMemoryAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = reqs.size,
.memoryTypeIndex = 0,
}, NULL, &image->memory);
assert(result == VK_SUCCESS);
result = anv_BindImageMemory(vk_device, image->image, image->memory, 0);
assert(result == VK_SUCCESS);
}
static void
dump_image_finish(struct anv_device *device, struct dump_image *image)
{
VkDevice vk_device = anv_device_to_handle(device);
anv_DestroyImage(vk_device, image->image, NULL);
anv_FreeMemory(vk_device, image->memory, NULL);
}
static void
dump_image_do_blit(struct anv_device *device, struct dump_image *image,
struct anv_cmd_buffer *cmd_buffer, struct anv_image *src,
VkImageAspectFlagBits aspect,
unsigned miplevel, unsigned array_layer)
{
/* We need to do a blit so the image needs to be declared as sampled. The
* only thing these are used for is making sure we create the correct
* views, so it should be find to just stomp it and set it back.
*/
VkImageUsageFlags old_usage = src->usage;
src->usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
anv_CmdBlitImage(anv_cmd_buffer_to_handle(cmd_buffer),
anv_image_to_handle(src), VK_IMAGE_LAYOUT_GENERAL,
image->image, VK_IMAGE_LAYOUT_GENERAL, 1,
&(VkImageBlit) {
.srcSubresource = {
.aspectMask = aspect,
.mipLevel = miplevel,
.baseArrayLayer = array_layer,
.layerCount = 1,
},
.srcOffsets = {
{ 0, 0, 0 },
{ image->extent.width, image->extent.height, 1 },
},
.dstSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.dstOffsets = {
{ 0, 0, 0 },
{ image->extent.width, image->extent.height, 1 },
},
}, VK_FILTER_NEAREST);
src->usage = old_usage;
ANV_CALL(CmdPipelineBarrier)(anv_cmd_buffer_to_handle(cmd_buffer),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
true, 0, NULL, 0, NULL, 1,
&(VkImageMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_HOST_READ_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = 0,
.dstQueueFamilyIndex = 0,
.image = image->image,
.subresourceRange = (VkImageSubresourceRange) {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
});
}
static void
dump_image_write_to_ppm(struct anv_device *device, struct dump_image *image)
{
VkDevice vk_device = anv_device_to_handle(device);
MAYBE_UNUSED VkResult result;
VkMemoryRequirements reqs;
anv_GetImageMemoryRequirements(vk_device, image->image, &reqs);
uint8_t *map;
result = anv_MapMemory(vk_device, image->memory, 0, reqs.size, 0, (void **)&map);
assert(result == VK_SUCCESS);
VkSubresourceLayout layout;
anv_GetImageSubresourceLayout(vk_device, image->image,
&(VkImageSubresource) {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.arrayLayer = 0,
}, &layout);
map += layout.offset;
FILE *file = fopen(image->filename, "wb");
assert(file);
uint8_t *row = malloc(image->extent.width * 3);
assert(row);
fprintf(file, "P6\n%d %d\n255\n", image->extent.width, image->extent.height);
for (unsigned y = 0; y < image->extent.height; y++) {
for (unsigned x = 0; x < image->extent.width; x++) {
row[x * 3 + 0] = map[x * 4 + 0];
row[x * 3 + 1] = map[x * 4 + 1];
row[x * 3 + 2] = map[x * 4 + 2];
}
fwrite(row, 3, image->extent.width, file);
map += layout.rowPitch;
}
free(row);
fclose(file);
anv_UnmapMemory(vk_device, image->memory);
}
void
anv_dump_image_to_ppm(struct anv_device *device,
struct anv_image *image, unsigned miplevel,
@@ -36,41 +203,11 @@ anv_dump_image_to_ppm(struct anv_device *device,
VkDevice vk_device = anv_device_to_handle(device);
MAYBE_UNUSED VkResult result;
VkExtent2D extent = {
anv_minify(image->extent.width, miplevel),
anv_minify(image->extent.height, miplevel),
};
const uint32_t width = anv_minify(image->extent.width, miplevel);
const uint32_t height = anv_minify(image->extent.height, miplevel);
VkImage copy_image;
result = anv_CreateImage(vk_device,
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_R8G8B8A8_UNORM,
.extent = (VkExtent3D) { extent.width, extent.height, 1 },
.mipLevels = 1,
.arrayLayers = 1,
.samples = 1,
.tiling = VK_IMAGE_TILING_LINEAR,
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
.flags = 0,
}, NULL, &copy_image);
assert(result == VK_SUCCESS);
VkMemoryRequirements reqs;
anv_GetImageMemoryRequirements(vk_device, copy_image, &reqs);
VkDeviceMemory memory;
result = anv_AllocateMemory(vk_device,
&(VkMemoryAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = reqs.size,
.memoryTypeIndex = 0,
}, NULL, &memory);
assert(result == VK_SUCCESS);
result = anv_BindImageMemory(vk_device, copy_image, memory, 0);
assert(result == VK_SUCCESS);
struct dump_image dump;
dump_image_init(device, &dump, width, height, filename);
VkCommandPool commandPool;
result = anv_CreateCommandPool(vk_device,
@@ -98,58 +235,8 @@ anv_dump_image_to_ppm(struct anv_device *device,
});
assert(result == VK_SUCCESS);
VkImageUsageFlags old_usage = image->usage;
image->usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
anv_CmdBlitImage(cmd,
anv_image_to_handle(image), VK_IMAGE_LAYOUT_GENERAL,
copy_image, VK_IMAGE_LAYOUT_GENERAL, 1,
&(VkImageBlit) {
.srcSubresource = {
.aspectMask = aspect,
.mipLevel = miplevel,
.baseArrayLayer = array_layer,
.layerCount = 1,
},
.srcOffsets = {
{ 0, 0, 0 },
{ extent.width, extent.height, 1 },
},
.dstSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.dstOffsets = {
{ 0, 0, 0 },
{ extent.width, extent.height, 1 },
},
}, VK_FILTER_NEAREST);
image->usage = old_usage;
ANV_CALL(CmdPipelineBarrier)(cmd,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
true, 0, NULL, 0, NULL, 1,
&(VkImageMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_HOST_READ_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = 0,
.dstQueueFamilyIndex = 0,
.image = copy_image,
.subresourceRange = (VkImageSubresourceRange) {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
});
dump_image_do_blit(device, &dump, anv_cmd_buffer_from_handle(cmd), image,
aspect, miplevel, array_layer);
result = anv_EndCommandBuffer(cmd);
assert(result == VK_SUCCESS);
@@ -176,39 +263,6 @@ anv_dump_image_to_ppm(struct anv_device *device,
anv_DestroyFence(vk_device, fence, NULL);
anv_DestroyCommandPool(vk_device, commandPool, NULL);
uint8_t *map;
result = anv_MapMemory(vk_device, memory, 0, reqs.size, 0, (void **)&map);
assert(result == VK_SUCCESS);
VkSubresourceLayout layout;
anv_GetImageSubresourceLayout(vk_device, copy_image,
&(VkImageSubresource) {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.arrayLayer = 0,
}, &layout);
map += layout.offset;
/* Now we can finally write the PPM file */
FILE *file = fopen(filename, "wb");
assert(file);
fprintf(file, "P6\n%d %d\n255\n", extent.width, extent.height);
for (unsigned y = 0; y < extent.height; y++) {
uint8_t row[extent.width * 3];
for (unsigned x = 0; x < extent.width; x++) {
row[x * 3 + 0] = map[x * 4 + 0];
row[x * 3 + 1] = map[x * 4 + 1];
row[x * 3 + 2] = map[x * 4 + 2];
}
fwrite(row, 3, extent.width, file);
map += layout.rowPitch;
}
fclose(file);
anv_UnmapMemory(vk_device, memory);
anv_DestroyImage(vk_device, copy_image, NULL);
anv_FreeMemory(vk_device, memory, NULL);
dump_image_write_to_ppm(device, &dump);
dump_image_finish(device, &dump);
}