summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony-LunarG <tony@lunarg.com>2018-09-21 13:47:06 -0600
committerTony Barbour <tony@lunarg.com>2018-09-24 13:29:17 -0600
commitbc9fc056ea7b181725cfb8a4eda03ed9da85c17f (patch)
treea7d4dbd0bee9c38df16828f74298e3cd4099a694
parent267a7288e96e097b7ee538d13f24fd6acc29047a (diff)
downloadVulkan-Tools-bc9fc056ea7b181725cfb8a4eda03ed9da85c17f.tar.gz
Vulkan-Tools-bc9fc056ea7b181725cfb8a4eda03ed9da85c17f.tar.bz2
Vulkan-Tools-bc9fc056ea7b181725cfb8a4eda03ed9da85c17f.zip
cube: Use staging buffer instead of staging image
There is no guarantee that linear images are supported Change-Id: Ie59f3bf7bfc1d77e17f1d06ffc524e886dca46a6
-rw-r--r--cube/cube.c95
-rw-r--r--cube/cube.cpp87
2 files changed, 144 insertions, 38 deletions
diff --git a/cube/cube.c b/cube/cube.c
index ea9517e8..fb239361 100644
--- a/cube/cube.c
+++ b/cube/cube.c
@@ -161,6 +161,7 @@ struct texture_object {
VkSampler sampler;
VkImage image;
+ VkBuffer buffer;
VkImageLayout imageLayout;
VkMemoryAllocateInfo mem_alloc;
@@ -1488,6 +1489,65 @@ bool loadTexture(const char *filename, uint8_t *rgba_data, VkSubresourceLayout *
return true;
}
+static void demo_prepare_texture_buffer(struct demo *demo, const char *filename, struct texture_object *tex_obj) {
+ int32_t tex_width;
+ int32_t tex_height;
+ VkResult U_ASSERT_ONLY err;
+ bool U_ASSERT_ONLY pass;
+
+ if (!loadTexture(filename, NULL, NULL, &tex_width, &tex_height)) {
+ ERR_EXIT("Failed to load textures", "Load Texture Failure");
+ }
+
+ tex_obj->tex_width = tex_width;
+ tex_obj->tex_height = tex_height;
+
+ const VkBufferCreateInfo buffer_create_info = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .pNext = NULL,
+ .flags = 0,
+ .size = tex_width * tex_height * 4,
+ .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .queueFamilyIndexCount = 0,
+ .pQueueFamilyIndices = NULL};
+
+ err = vkCreateBuffer(demo->device, &buffer_create_info, NULL, &tex_obj->buffer);
+ assert(!err);
+
+ VkMemoryRequirements mem_reqs;
+ vkGetBufferMemoryRequirements(demo->device, tex_obj->buffer, &mem_reqs);
+
+ tex_obj->mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ tex_obj->mem_alloc.pNext = NULL;
+ tex_obj->mem_alloc.allocationSize = mem_reqs.size;
+ tex_obj->mem_alloc.memoryTypeIndex = 0;
+
+ VkFlags requirements = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits, requirements, &tex_obj->mem_alloc.memoryTypeIndex);
+ assert(pass);
+
+ err = vkAllocateMemory(demo->device, &tex_obj->mem_alloc, NULL, &(tex_obj->mem));
+ assert(!err);
+
+ /* bind memory */
+ err = vkBindBufferMemory(demo->device, tex_obj->buffer, tex_obj->mem, 0);
+ assert(!err);
+
+ VkSubresourceLayout layout;
+ memset(&layout, 0, sizeof(layout));
+ layout.rowPitch = tex_width * 4;
+
+ void *data;
+ err = vkMapMemory(demo->device, tex_obj->mem, 0, tex_obj->mem_alloc.allocationSize, 0, &data);
+ assert(!err);
+
+ if (!loadTexture(filename, data, &layout, &tex_width, &tex_height)) {
+ fprintf(stderr, "Error loading texture: %s\n", filename);
+ }
+
+ vkUnmapMemory(demo->device, tex_obj->mem);
+}
+
static void demo_prepare_texture_image(struct demo *demo, const char *filename, struct texture_object *tex_obj,
VkImageTiling tiling, VkImageUsageFlags usage, VkFlags required_props) {
const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
@@ -1565,10 +1625,11 @@ static void demo_prepare_texture_image(struct demo *demo, const char *filename,
tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
-static void demo_destroy_texture_image(struct demo *demo, struct texture_object *tex_objs) {
+static void demo_destroy_texture(struct demo *demo, struct texture_object *tex_objs) {
/* clean up staging resources */
vkFreeMemory(demo->device, tex_objs->mem, NULL);
- vkDestroyImage(demo->device, tex_objs->image, NULL);
+ if (tex_objs->image) vkDestroyImage(demo->device, tex_objs->image, NULL);
+ if (tex_objs->buffer) vkDestroyBuffer(demo->device, tex_objs->buffer, NULL);
}
static void demo_prepare_textures(struct demo *demo) {
@@ -1595,31 +1656,27 @@ static void demo_prepare_textures(struct demo *demo) {
/* Must use staging buffer to copy linear texture to optimized */
memset(&demo->staging_texture, 0, sizeof(demo->staging_texture));
- demo_prepare_texture_image(demo, tex_files[i], &demo->staging_texture, VK_IMAGE_TILING_LINEAR,
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+ demo_prepare_texture_buffer(demo, tex_files[i], &demo->staging_texture);
demo_prepare_texture_image(demo, tex_files[i], &demo->textures[i], VK_IMAGE_TILING_OPTIMAL,
(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- demo_set_image_layout(demo, demo->staging_texture.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT);
-
demo_set_image_layout(demo, demo->textures[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkImageCopy copy_region = {
- .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
- .srcOffset = {0, 0, 0},
- .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
- .dstOffset = {0, 0, 0},
- .extent = {demo->staging_texture.tex_width, demo->staging_texture.tex_height, 1},
+ VkBufferImageCopy copy_region = {
+ .bufferOffset = 0,
+ .bufferRowLength = demo->staging_texture.tex_width,
+ .bufferImageHeight = demo->staging_texture.tex_height,
+ .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
+ .imageOffset = {0, 0, 0},
+ .imageExtent = {demo->staging_texture.tex_width, demo->staging_texture.tex_height, 1},
};
- vkCmdCopyImage(demo->cmd, demo->staging_texture.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
+
+ vkCmdCopyBufferToImage(demo->cmd, demo->staging_texture.buffer, demo->textures[i].image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
demo_set_image_layout(demo, demo->textures[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
demo->textures[i].imageLayout, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
@@ -2186,8 +2243,8 @@ static void demo_prepare(struct demo *demo) {
* that need to be flushed before beginning the render loop.
*/
demo_flush_init_cmd(demo);
- if (demo->staging_texture.image) {
- demo_destroy_texture_image(demo, &demo->staging_texture);
+ if (demo->staging_texture.buffer) {
+ demo_destroy_texture(demo, &demo->staging_texture);
}
demo->current_buffer = 0;
diff --git a/cube/cube.cpp b/cube/cube.cpp
index 6ff11900..5c68442c 100644
--- a/cube/cube.cpp
+++ b/cube/cube.cpp
@@ -78,6 +78,7 @@ struct texture_object {
vk::Sampler sampler;
vk::Image image;
+ vk::Buffer buffer;
vk::ImageLayout imageLayout{vk::ImageLayout::eUndefined};
vk::MemoryAllocateInfo mem_alloc;
@@ -216,7 +217,7 @@ struct Demo {
vk::Bool32 check_layers(uint32_t, const char *const *, uint32_t, vk::LayerProperties *);
void cleanup();
void create_device();
- void destroy_texture_image(texture_object *);
+ void destroy_texture(texture_object *);
void draw();
void draw_build_cmd(vk::CommandBuffer);
void flush_init_cmd();
@@ -238,6 +239,7 @@ struct Demo {
void prepare_pipeline();
void prepare_render_pass();
void prepare_texture_image(const char *, texture_object *, vk::ImageTiling, vk::ImageUsageFlags, vk::MemoryPropertyFlags);
+ void prepare_texture_buffer(const char *, texture_object *);
void prepare_textures();
void resize();
@@ -710,10 +712,11 @@ void Demo::create_device() {
VERIFY(result == vk::Result::eSuccess);
}
-void Demo::destroy_texture_image(texture_object *tex_objs) {
+void Demo::destroy_texture(texture_object *tex_objs) {
// clean up staging resources
device.freeMemory(tex_objs->mem, nullptr);
- device.destroyImage(tex_objs->image, nullptr);
+ if (tex_objs->image) device.destroyImage(tex_objs->image, nullptr);
+ if (tex_objs->buffer) device.destroyBuffer(tex_objs->buffer, nullptr);
}
void Demo::draw() {
@@ -1499,8 +1502,8 @@ void Demo::prepare() {
* that need to be flushed before beginning the render loop.
*/
flush_init_cmd();
- if (staging_texture.image) {
- destroy_texture_image(&staging_texture);
+ if (staging_texture.buffer) {
+ destroy_texture(&staging_texture);
}
current_buffer = 0;
@@ -2016,6 +2019,56 @@ vk::ShaderModule Demo::prepare_shader_module(const uint32_t *code, size_t size)
return module;
}
+void Demo::prepare_texture_buffer(const char *filename, texture_object *tex_obj) {
+ int32_t tex_width;
+ int32_t tex_height;
+
+ if (!loadTexture(filename, NULL, NULL, &tex_width, &tex_height)) {
+ ERR_EXIT("Failed to load textures", "Load Texture Failure");
+ }
+
+ tex_obj->tex_width = tex_width;
+ tex_obj->tex_height = tex_height;
+
+ auto const buffer_create_info = vk::BufferCreateInfo()
+ .setSize(tex_width * tex_height * 4)
+ .setUsage(vk::BufferUsageFlagBits::eTransferSrc)
+ .setSharingMode(vk::SharingMode::eExclusive)
+ .setQueueFamilyIndexCount(0)
+ .setPQueueFamilyIndices(nullptr);
+
+ auto result = device.createBuffer(&buffer_create_info, nullptr, &tex_obj->buffer);
+ VERIFY(result == vk::Result::eSuccess);
+
+ vk::MemoryRequirements mem_reqs;
+ device.getBufferMemoryRequirements(tex_obj->buffer, &mem_reqs);
+
+ tex_obj->mem_alloc.setAllocationSize(mem_reqs.size);
+ tex_obj->mem_alloc.setMemoryTypeIndex(0);
+
+ vk::MemoryPropertyFlags requirements = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent;
+ auto pass = memory_type_from_properties(mem_reqs.memoryTypeBits, requirements, &tex_obj->mem_alloc.memoryTypeIndex);
+ VERIFY(pass == true);
+
+ result = device.allocateMemory(&tex_obj->mem_alloc, nullptr, &(tex_obj->mem));
+ VERIFY(result == vk::Result::eSuccess);
+
+ result = device.bindBufferMemory(tex_obj->buffer, tex_obj->mem, 0);
+ VERIFY(result == vk::Result::eSuccess);
+
+ vk::SubresourceLayout layout;
+ memset(&layout, 0, sizeof(layout));
+ layout.rowPitch = tex_width * 4;
+ auto data = device.mapMemory(tex_obj->mem, 0, tex_obj->mem_alloc.allocationSize);
+ VERIFY(data.result == vk::Result::eSuccess);
+
+ if (!loadTexture(filename, (uint8_t *)data.value, &layout, &tex_width, &tex_height)) {
+ fprintf(stderr, "Error loading texture: %s\n", filename);
+ }
+
+ device.unmapMemory(tex_obj->mem);
+}
+
void Demo::prepare_texture_image(const char *filename, texture_object *tex_obj, vk::ImageTiling tiling, vk::ImageUsageFlags usage,
vk::MemoryPropertyFlags required_props) {
int32_t tex_width;
@@ -2096,17 +2149,12 @@ void Demo::prepare_textures() {
} else if (props.optimalTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage) {
/* Must use staging buffer to copy linear texture to optimized */
- prepare_texture_image(tex_files[i], &staging_texture, vk::ImageTiling::eLinear, vk::ImageUsageFlagBits::eTransferSrc,
- vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+ prepare_texture_buffer(tex_files[i], &staging_texture);
prepare_texture_image(tex_files[i], &textures[i], vk::ImageTiling::eOptimal,
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
vk::MemoryPropertyFlagBits::eDeviceLocal);
- set_image_layout(staging_texture.image, vk::ImageAspectFlagBits::eColor, vk::ImageLayout::ePreinitialized,
- vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits(), vk::PipelineStageFlagBits::eTopOfPipe,
- vk::PipelineStageFlagBits::eTransfer);
-
set_image_layout(textures[i].image, vk::ImageAspectFlagBits::eColor, vk::ImageLayout::ePreinitialized,
vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits(), vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eTransfer);
@@ -2117,15 +2165,16 @@ void Demo::prepare_textures() {
.setBaseArrayLayer(0)
.setLayerCount(1);
- auto const copy_region = vk::ImageCopy()
- .setSrcSubresource(subresource)
- .setSrcOffset({0, 0, 0})
- .setDstSubresource(subresource)
- .setDstOffset({0, 0, 0})
- .setExtent({(uint32_t)staging_texture.tex_width, (uint32_t)staging_texture.tex_height, 1});
+ auto const copy_region =
+ vk::BufferImageCopy()
+ .setBufferOffset(0)
+ .setBufferRowLength(staging_texture.tex_width)
+ .setBufferImageHeight(staging_texture.tex_height)
+ .setImageSubresource(subresource)
+ .setImageOffset({0, 0, 0})
+ .setImageExtent({(uint32_t)staging_texture.tex_width, (uint32_t)staging_texture.tex_height, 1});
- cmd.copyImage(staging_texture.image, vk::ImageLayout::eTransferSrcOptimal, textures[i].image,
- vk::ImageLayout::eTransferDstOptimal, 1, &copy_region);
+ cmd.copyBufferToImage(staging_texture.buffer, textures[i].image, vk::ImageLayout::eTransferDstOptimal, 1, &copy_region);
set_image_layout(textures[i].image, vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal,
textures[i].imageLayout, vk::AccessFlagBits::eTransferWrite, vk::PipelineStageFlagBits::eTransfer,