33 mVulkanRenderer ( aVulkanRenderer ), mTexture{&aTexture}
35 VkImageCreateInfo image_create_info{};
36 image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
37 image_create_info.pNext =
nullptr;
38 image_create_info.flags = 0;
39 image_create_info.imageType = VK_IMAGE_TYPE_2D;
40 image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
41 VkFormatProperties format_properties{};
42 vkGetPhysicalDeviceFormatProperties ( mVulkanRenderer.GetPhysicalDevice(), image_create_info.format, &format_properties );
43 image_create_info.extent.width = aTexture.
GetWidth();
44 image_create_info.extent.height = aTexture.
GetHeight();
45 image_create_info.extent.depth = 1;
46 image_create_info.mipLevels = 1;
47 image_create_info.arrayLayers = 1;
48 image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
49 image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
50 image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
51 image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
52 image_create_info.queueFamilyIndexCount = 0;
53 image_create_info.pQueueFamilyIndices =
nullptr;
54 image_create_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
55 if ( VkResult result = vkCreateImage ( mVulkanRenderer.GetDevice(), &image_create_info,
nullptr, &mVkImage ) )
57 std::ostringstream stream;
60 throw std::runtime_error ( stream.str().c_str() );
63 VkMemoryRequirements memory_requirements{};
64 vkGetImageMemoryRequirements ( mVulkanRenderer.GetDevice(), mVkImage, &memory_requirements );
65 VkMemoryAllocateInfo memory_allocate_info{};
66 memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
67 memory_allocate_info.pNext =
nullptr;
68 memory_allocate_info.allocationSize = memory_requirements.size;
69 memory_allocate_info.memoryTypeIndex = mVulkanRenderer.FindMemoryTypeIndex ( memory_requirements.memoryTypeBits,
70 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT );
71 if ( memory_allocate_info.memoryTypeIndex == std::numeric_limits<uint32_t>::max() )
73 std::cout <<
LogLevel::Error <<
"Unable to find a suitable memory type index" << std::endl;
74 throw std::runtime_error (
"Unable to find a suitable memory type index" );
76 if ( VkResult result = vkAllocateMemory ( mVulkanRenderer.GetDevice(), &memory_allocate_info,
nullptr, &mVkDeviceMemory ) )
78 std::ostringstream stream;
81 throw std::runtime_error ( stream.str().c_str() );
83 if ( VkResult result = vkBindImageMemory ( mVulkanRenderer.GetDevice(), mVkImage, mVkDeviceMemory, 0 ) )
85 std::ostringstream stream;
88 throw std::runtime_error ( stream.str().c_str() );
93 mVkDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
94 VkImageViewCreateInfo image_view_create_info = {};
95 image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
96 image_view_create_info.image = mVkImage;
97 image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
98 image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
99 image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
100 image_view_create_info.subresourceRange.baseMipLevel = 0;
101 image_view_create_info.subresourceRange.levelCount = 1;
102 image_view_create_info.subresourceRange.baseArrayLayer = 0;
103 image_view_create_info.subresourceRange.layerCount = 1;
104 if ( VkResult result = vkCreateImageView ( mVulkanRenderer.GetDevice(), &image_view_create_info,
nullptr, &mVkDescriptorImageInfo.imageView ) )
106 std::ostringstream stream;
109 throw std::runtime_error ( stream.str().c_str() );
112 VkSamplerCreateInfo sampler_create_info{};
113 sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
114 sampler_create_info.pNext =
nullptr;
115 sampler_create_info.flags = 0;
116 sampler_create_info.magFilter = VK_FILTER_NEAREST;
117 sampler_create_info.minFilter = VK_FILTER_NEAREST;
118 sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
119 sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
120 sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
121 sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
122 sampler_create_info.mipLodBias = 0.0f;
123 sampler_create_info.anisotropyEnable = VK_FALSE;
124 sampler_create_info.maxAnisotropy = 1.0f;
125 sampler_create_info.compareEnable = VK_FALSE;
126 sampler_create_info.compareOp = VK_COMPARE_OP_NEVER;
127 sampler_create_info.minLod = 0.0f;
128 sampler_create_info.maxLod = 1.0f;
129 sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
130 sampler_create_info.unnormalizedCoordinates = VK_FALSE;
131 if ( VkResult result = vkCreateSampler ( mVulkanRenderer.GetDevice(), &sampler_create_info,
nullptr, &mVkDescriptorImageInfo.sampler ) )
133 std::ostringstream stream;
136 throw std::runtime_error ( stream.str().c_str() );
141 VkBuffer image_buffer{};
142 VkDeviceMemory image_buffer_memory{};
144 VkBufferCreateInfo buffer_create_info = {};
145 buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
146 buffer_create_info.size =
static_cast<size_t> ( aTexture.
GetWidth() ) *
static_cast<size_t> ( aTexture.
GetHeight() ) * 4;
147 buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
148 buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
150 if ( VkResult result = vkCreateBuffer ( mVulkanRenderer.GetDevice(), &buffer_create_info,
nullptr, &image_buffer ) )
152 std::ostringstream stream;
155 throw std::runtime_error ( stream.str().c_str() );
158 memset ( &memory_requirements, 0,
sizeof ( VkMemoryRequirements ) );
159 vkGetBufferMemoryRequirements ( mVulkanRenderer.GetDevice(), image_buffer, &memory_requirements );
160 memset ( &memory_allocate_info, 0,
sizeof ( VkMemoryAllocateInfo ) );
161 memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
162 memory_allocate_info.allocationSize = memory_requirements.size;
163 memory_allocate_info.memoryTypeIndex = mVulkanRenderer.FindMemoryTypeIndex ( memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT );
165 if ( VkResult result = vkAllocateMemory ( mVulkanRenderer.GetDevice(), &memory_allocate_info,
nullptr, &image_buffer_memory ) )
167 std::ostringstream stream;
170 throw std::runtime_error ( stream.str().c_str() );
173 if ( VkResult result = vkBindBufferMemory ( mVulkanRenderer.GetDevice(), image_buffer, image_buffer_memory, 0 ) )
175 std::ostringstream stream;
178 throw std::runtime_error ( stream.str().c_str() );
181 void* image_memory =
nullptr;
182 if ( VkResult result = vkMapMemory ( mVulkanRenderer.GetDevice(), image_buffer_memory, 0, VK_WHOLE_SIZE, 0, &image_memory ) )
184 std::ostringstream stream;
187 throw std::runtime_error ( stream.str().c_str() );
206 const auto* read_pointer =
reinterpret_cast<const uint16_t*
> ( aTexture.
GetPixels().data() );
207 auto* write_pointer =
static_cast<uint8_t*
> ( image_memory );
209 for ( uint32_t i = 0; i < data_size; i += 4 )
211 write_pointer[i] = read_pointer[i] / 256;
212 write_pointer[i + 1] = read_pointer[i + 1] / 256;
213 write_pointer[i + 2] = read_pointer[i + 2] / 256;
214 write_pointer[i + 3] = read_pointer[i + 3] / 256;
222 const uint8_t* read_pointer = aTexture.
GetPixels().data();
223 auto* write_pointer =
static_cast<uint8_t*
> ( image_memory );
225 for ( uint32_t i = 0; i < data_size; i += 3 )
227 write_pointer[0] = read_pointer[i];
228 write_pointer[1] = read_pointer[i + 1];
229 write_pointer[2] = read_pointer[i + 2];
230 write_pointer[3] = 255;
237 const auto* read_pointer =
reinterpret_cast<const uint16_t*
> ( aTexture.
GetPixels().data() );
238 auto* write_pointer =
static_cast<uint8_t*
> ( image_memory );
240 for ( uint32_t i = 0; i < data_size; i += 3 )
242 write_pointer[0] = read_pointer[i] / 256;
243 write_pointer[1] = read_pointer[i + 1] / 256;
244 write_pointer[2] = read_pointer[i + 2] / 256;
245 write_pointer[3] = 255;
250 vkUnmapMemory ( mVulkanRenderer.GetDevice(), image_buffer_memory );
254 VkCommandBuffer command_buffer = mVulkanRenderer.BeginSingleTimeCommands();
255 VkImageMemoryBarrier image_memory_barrier{};
256 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
257 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
258 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
259 image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
260 image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
261 image_memory_barrier.image = mVkImage;
262 image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
263 image_memory_barrier.subresourceRange.baseMipLevel = 0;
264 image_memory_barrier.subresourceRange.levelCount = 1;
265 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
266 image_memory_barrier.subresourceRange.layerCount = 1;
267 image_memory_barrier.srcAccessMask = 0;
268 image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
269 vkCmdPipelineBarrier (
271 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
275 1, &image_memory_barrier
277 VkBufferImageCopy buffer_image_copy{};
278 buffer_image_copy.bufferOffset = 0;
279 buffer_image_copy.bufferRowLength = 0;
280 buffer_image_copy.bufferImageHeight = 0;
281 buffer_image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
282 buffer_image_copy.imageSubresource.mipLevel = 0;
283 buffer_image_copy.imageSubresource.baseArrayLayer = 0;
284 buffer_image_copy.imageSubresource.layerCount = 1;
285 buffer_image_copy.imageOffset = { 0, 0, 0 };
286 buffer_image_copy.imageExtent = { aTexture.
GetWidth(), aTexture.
GetHeight(), 1 };
287 vkCmdCopyBufferToImage ( command_buffer, image_buffer, mVkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy );
289 image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
290 image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
291 image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
292 image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
293 vkCmdPipelineBarrier (
295 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
299 1, &image_memory_barrier
301 mVulkanRenderer.EndSingleTimeCommands ( command_buffer );
302 vkDestroyBuffer ( mVulkanRenderer.GetDevice(), image_buffer,
nullptr );
303 vkFreeMemory ( mVulkanRenderer.GetDevice(), image_buffer_memory,
nullptr );