Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanTexture.cpp
Go to the documentation of this file.
3 #ifdef USING_VULKAN
5 #include "Engine/engine.hpp"
6 
7 namespace Engine
8 {
9 
10  VulkanTexture::VulkanTexture(const eastl::string& filename, int desiredChannels) : Texture(filename, desiredChannels)
11  {
12  eastl::string baseLocation = "Resources/Textures/";
13  baseLocation.append(filename);
14 
15  stbi_uc* textureData = stbi_load(
16  Utility::FileExists(baseLocation) ?
17  baseLocation.c_str() :
18  "Resources/Textures/default.png",
19  &width, &height, &channels, STBI_rgb_alpha);
20 
21  VulkanTexture::CreateTextureWithData(textureData, true);
22 
23  stbi_image_free(textureData);
24  }
25 
26  VulkanTexture::VulkanTexture(int width, int height) : Texture(width, height), image(0), imageView(0), sampler(0),
27  storage(false)
28  {
29  }
30 
31  VulkanRenderer* VulkanTexture::renderer = nullptr;
32  VulkanLogicalDevice *VulkanTexture::device = nullptr;
33  VulkanDescriptorPool* VulkanTexture::descriptorPool = nullptr;
34  VmaAllocator VulkanTexture::allocator = VK_NULL_HANDLE;
35  VkCommandPool VulkanTexture::commandPool = VK_NULL_HANDLE;
36 
37  void VulkanTexture::InitTextureSystem(VulkanRenderer* renderer, VulkanLogicalDevice * device, VulkanDescriptorPool* descriptorPool, VmaAllocator allocator, VkCommandPool commandPool)
38  {
39  VulkanTexture::renderer = renderer;
40  VulkanTexture::device = device;
41  VulkanTexture::descriptorPool = descriptorPool;
42  VulkanTexture::allocator = allocator;
43  VulkanTexture::commandPool = commandPool;
44  }
45 
46  VulkanTexture::~VulkanTexture()
47  {
48  vkQueueWaitIdle(device->GetGraphicsQueue());
49 
50  vkDestroySampler(device->GetDevice(), sampler, nullptr);
51  vkDestroyImageView(device->GetDevice(), imageView, nullptr);
52 
53  vmaDestroyImage(allocator, image, allocation);
54  }
55 
56  void VulkanTexture::CreateTextureWithData(stbi_uc* data, bool genMipMaps, TextureDataSize bytes, bool storage)
57  {
58  this->dataSize = bytes;
59  this->storage = storage;
60 
61  uint32_t byteSize;
62 
63  switch (bytes) {
65  byteSize = 1;
66  break;
68  byteSize = 1;
69  break;
71  byteSize = 2;
72  break;
74  byteSize = 2;
75  break;
77  byteSize = 4;
78  break;
80  byteSize = 4;
81  break;
82  default:
83  byteSize = 1;
84  break;
85  }
86 
87  VkBufferCreateInfo stagingBufferInfo = {};
88  stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
89  stagingBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
90  stagingBufferInfo.size = width * height * 4 * byteSize;
91  stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
92 
93  VmaAllocationCreateInfo stagingBufferAllocInfo = {};
94  stagingBufferAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
95 
96  VkBuffer stagingBuffer;
97  VmaAllocation stagingBufferAllocation;
98 
99  vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingBufferAllocInfo, &stagingBuffer, &stagingBufferAllocation, nullptr);
100 
101  void* dst;
102 
103  vmaMapMemory(allocator, stagingBufferAllocation, &dst);
104  memcpy(dst, data, static_cast<size_t>(width*height * 4 * byteSize));
105  vmaUnmapMemory(allocator, stagingBufferAllocation);
106 
107  VkFormat format;
108 
109  switch (bytes) {
111  format = VK_FORMAT_R8G8B8A8_UNORM;
112  break;
114  format = VK_FORMAT_R8G8B8A8_SNORM;
115  break;
117  format = VK_FORMAT_R16G16B16A16_UNORM;
118  break;
120  format = VK_FORMAT_R16G16B16A16_SFLOAT;
121  break;
123  format = VK_FORMAT_R32G32B32A32_UINT;
124  break;
126  format = VK_FORMAT_R32G32B32A32_SFLOAT;
127  break;
128  default:
129  format = VK_FORMAT_R8G8B8A8_UNORM;
130  break;
131  }
132 
133  VkImageCreateInfo imageCreateInfo = {};
134  imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
135  imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
136  imageCreateInfo.extent.width = static_cast<uint32_t>(width);
137  imageCreateInfo.extent.height = static_cast<uint32_t>(height);
138  imageCreateInfo.extent.depth = 1;
139  imageCreateInfo.mipLevels = 1;
140  imageCreateInfo.arrayLayers = 1;
141  imageCreateInfo.format = format;
142  imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
143  imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
144  imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
145  if (storage)
146  imageCreateInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
147  else
148  imageCreateInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
149  imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
150  imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
151  imageCreateInfo.flags = 0;
152 
153  VmaAllocationCreateInfo imageAllocInfo = {};
154  imageAllocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
155 
156  vmaCreateImage(allocator, &imageCreateInfo, &imageAllocInfo, &image, &allocation, &allocationInfo);
157 
158  VkCommandBuffer commandBuffer;
159 
160  VkCommandBufferAllocateInfo cmdAllocInfo = {};
161  cmdAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
162  cmdAllocInfo.commandPool = commandPool;
163  cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
164  cmdAllocInfo.commandBufferCount = 1;
165 
166  vkAllocateCommandBuffers(device->GetDevice(), &cmdAllocInfo, &commandBuffer);
167 
168  VkCommandBufferBeginInfo cmdBeginInfo = {};
169  cmdBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
170  cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
171 
172  vkBeginCommandBuffer(commandBuffer, &cmdBeginInfo);
173 
174  VkImageMemoryBarrier barrier1 = {};
175  barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
176  barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
177  barrier1.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
178  barrier1.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
179  barrier1.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
180  barrier1.image = image;
181  barrier1.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
182  barrier1.subresourceRange.baseArrayLayer = 0;
183  barrier1.subresourceRange.baseMipLevel = 0;
184  barrier1.subresourceRange.layerCount = 1;
185  barrier1.subresourceRange.levelCount = 1;
186  barrier1.srcAccessMask = 0;
187  barrier1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
188 
189  vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier1);
190 
191  VkBufferImageCopy region;
192  region.bufferOffset = 0;
193  region.bufferRowLength = 0;
194  region.bufferImageHeight = 0;
195 
196  region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
197  region.imageSubresource.baseArrayLayer = 0;
198  region.imageSubresource.layerCount = 1;
199  region.imageSubresource.mipLevel = 0;
200 
201  region.imageOffset = { 0,0,0 };
202  region.imageExtent = {
203  static_cast<uint32_t>(width),
204  static_cast<uint32_t>(height),
205  1
206  };
207 
208  vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
209 
210  VkImageMemoryBarrier barrier2 = {};
211  barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
212  barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
213  if (storage)
214  barrier2.newLayout = VK_IMAGE_LAYOUT_GENERAL;
215  else
216  barrier2.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
217  barrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
218  barrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
219  barrier2.image = image;
220  barrier2.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
221  barrier2.subresourceRange.baseMipLevel = 0;
222  barrier2.subresourceRange.baseArrayLayer = 0;
223  barrier2.subresourceRange.layerCount = 1;
224  barrier2.subresourceRange.levelCount = 1;
225  barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
226  barrier2.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
227 
228  vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2);
229 
230  vkEndCommandBuffer(commandBuffer);
231 
232  VkSubmitInfo submitInfo = {};
233  submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
234  submitInfo.commandBufferCount = 1;
235  submitInfo.pCommandBuffers = &commandBuffer;
236 
237  //vkQueueWaitIdle(device->GetGraphicsQueue());
238 
239  vkQueueSubmit(device->GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
240  vkQueueWaitIdle(device->GetGraphicsQueue());
241  vkFreeCommandBuffers(device->GetDevice(), commandPool, 1, &commandBuffer);
242 
243  vmaDestroyBuffer(allocator, stagingBuffer, stagingBufferAllocation);
244 
245  VkImageViewCreateInfo viewCreateInfo = {};
246  viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
247  viewCreateInfo.image = image;
248  viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
249  viewCreateInfo.format = format;
250  viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
251  viewCreateInfo.subresourceRange.baseArrayLayer = 0;
252  viewCreateInfo.subresourceRange.baseMipLevel = 0;
253  viewCreateInfo.subresourceRange.layerCount = 1;
254  viewCreateInfo.subresourceRange.levelCount = 1;
255 
256  vkCreateImageView(device->GetDevice(), &viewCreateInfo, nullptr, &imageView);
257 
258  VkSamplerCreateInfo samplerInfo = {};
259  samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
260  samplerInfo.magFilter = VK_FILTER_LINEAR;
261  samplerInfo.minFilter = VK_FILTER_LINEAR;
262 
263  samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
264  samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
265  samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
266 
267  samplerInfo.anisotropyEnable = VK_TRUE;
268  samplerInfo.maxAnisotropy = 4;
269 
270  samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
271  samplerInfo.unnormalizedCoordinates = VK_FALSE;
272 
273  samplerInfo.compareEnable = VK_FALSE;
274  samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
275 
276  samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
277  samplerInfo.mipLodBias = 0.f;
278  samplerInfo.minLod = 0.f;
279  samplerInfo.maxLod = 0.f;
280 
281  vkCreateSampler(device->GetDevice(), &samplerInfo, nullptr, &sampler);
282  }
283  void VulkanTexture::SetSampler(VkSamplerCreateInfo samplerInfo)
284  {
285  if (sampler != VK_NULL_HANDLE)
286  vkDestroySampler(device->GetDevice(), sampler, nullptr);
287  vkCreateSampler(device->GetDevice(), &samplerInfo, nullptr, &sampler);
288 
289  for (size_t i = 0, size = descriptorSets.size(); i < size; ++i) {
290  for (size_t j = 0, size2 = descriptorSets[i].size(); j < size2; ++j) {
291  for (size_t k = 0, size3 = descriptorSets[i][j].size(); j < size3; ++k) {
292  if (descriptorSets[i][j][k] != VK_NULL_HANDLE) {
293 
294  VkDescriptorType type;
295  VkImageLayout layout;
296  if (storage) {
297  type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
298  layout = VK_IMAGE_LAYOUT_GENERAL;
299  }
300  else {
301  type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
302  layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
303  }
304 
305  renderer->GetDescriptorPool(k)->DescriptorSetBindToImage(descriptorSets[i][j][k],
306  layout,
307  imageView, sampler, 0, 0,
308  type, 1);
309  }
310  }
311  }
312  }
313  }
314  VkImage VulkanTexture::GetImage() const
315  {
316  return image;
317  }
318  VkImageView VulkanTexture::GetImageView() const
319  {
320  return imageView;
321  }
322  VkSampler VulkanTexture::GetSampler() const
323  {
324  return sampler;
325  }
326  VkDescriptorSet VulkanTexture::CreateDescriptorSet(size_t threadID, size_t pipelineID, size_t set, VkDescriptorSetLayout layout)
327  {
328  if (descriptorSets.size() <= pipelineID) {
329  descriptorSets.resize(pipelineID + 1);
330  }
331  if (descriptorSets[pipelineID].size() <= set) {
332  descriptorSets[pipelineID].resize(set + 1);
333  }
334  if (descriptorSets[pipelineID][set].size() <= threadID) {
335  descriptorSets[pipelineID][set].resize(threadID + 1, VK_NULL_HANDLE);
336  }
337 
338  VkDescriptorSetLayout layouts[] = { layout };
339  renderer->GetDescriptorPool(threadID)->AllocateDescriptorSet(1, layouts, &descriptorSets[pipelineID][set][threadID]);
340 
341  VkDescriptorType type;
342  VkImageLayout imageLayout;
343  if (storage) {
344  type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
345  imageLayout = VK_IMAGE_LAYOUT_GENERAL;
346  }
347  else {
348  type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
349  imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
350  }
351  renderer->GetDescriptorPool(threadID)->DescriptorSetBindToImage(descriptorSets[pipelineID][set][threadID],
352  imageLayout,
353  imageView, sampler, 0, 0,
354  type, 1);
355 
356  return descriptorSets[pipelineID][set][threadID];
357  }
358  VkDescriptorSet VulkanTexture::GetDescriptorSet(size_t threadID, size_t pipelineID, size_t set)
359  {
360  if (pipelineID >= descriptorSets.size())
361  return VK_NULL_HANDLE;
362  if (set >= descriptorSets[pipelineID].size())
363  return VK_NULL_HANDLE;
364  if (threadID >= descriptorSets[pipelineID][set].size())
365  return VK_NULL_HANDLE;
366  return descriptorSets[pipelineID][set][threadID];
367  }
368 }
369 #endif
TextureDataSize dataSize
Definition: Texture.hpp:102
TextureDataSize
Definition: Texture.hpp:11
static bool FileExists(const eastl::string &fileName)
Definition: Utility.cpp:32