Texture.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "Texture.h"
  2. #include "Graphics.h"
  3. // make vulkan::Graphics functions available
  4. #define vgfx ((Graphics*)gfx)
  5. namespace love {
  6. namespace graphics {
  7. namespace vulkan {
  8. Texture::Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data)
  9. : love::graphics::Texture(gfx, settings, data), gfx(gfx) {
  10. allocator = vgfx->getVmaAllocator();
  11. device = vgfx->getDevice();
  12. if (data) {
  13. auto sliceData = data->get(0, 0);
  14. auto size = sliceData->getSize();
  15. auto dataPtr = sliceData->getData();
  16. Rect rect;
  17. rect.x = 0;
  18. rect.y = 0;
  19. rect.w = sliceData->getWidth();
  20. rect.h = sliceData->getHeight();
  21. uploadByteData(PIXELFORMAT_BGRA8_UNORM, dataPtr, size, 0, 0, rect);
  22. }
  23. else {
  24. uint8 defaultPixel[] = { 255, 255, 255, 255 };
  25. Rect rect = { 0, 0, 1, 1 };
  26. uploadByteData(PIXELFORMAT_BGRA8_UNORM, defaultPixel, sizeof(defaultPixel), 0, 0, rect);
  27. }
  28. createTextureImageView();
  29. createTextureSampler();
  30. }
  31. Texture::~Texture() {
  32. // vkDestroySampler(device, textureSampler, nullptr);
  33. // vkDestroyImageView(device, textureImageView, nullptr);
  34. // vmaDestroyImage(allocator, textureImage, nullptr);
  35. }
  36. void Texture::createTextureImageView() {
  37. VkImageViewCreateInfo viewInfo{};
  38. viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  39. viewInfo.image = textureImage;
  40. viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  41. viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
  42. viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  43. viewInfo.subresourceRange.baseMipLevel = 0;
  44. viewInfo.subresourceRange.levelCount = 1;
  45. viewInfo.subresourceRange.baseArrayLayer = 0;
  46. viewInfo.subresourceRange.layerCount = 1;
  47. if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS) {
  48. throw love::Exception("could not create texture image view");
  49. }
  50. }
  51. void Texture::createTextureSampler() {
  52. auto physicalDevice = vgfx->getPhysicalDevice();
  53. VkPhysicalDeviceProperties properties{};
  54. vkGetPhysicalDeviceProperties(physicalDevice, &properties);
  55. VkSamplerCreateInfo samplerInfo{};
  56. samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  57. samplerInfo.magFilter = VK_FILTER_LINEAR;
  58. samplerInfo.minFilter = VK_FILTER_LINEAR;
  59. samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  60. samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  61. samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  62. samplerInfo.anisotropyEnable = VK_TRUE;
  63. samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
  64. samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
  65. samplerInfo.unnormalizedCoordinates = VK_FALSE;
  66. samplerInfo.compareEnable = VK_FALSE;
  67. samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
  68. samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
  69. samplerInfo.mipLodBias = 0.0f;
  70. samplerInfo.minLod = 0.0f;
  71. samplerInfo.maxLod = 0.0f;
  72. if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
  73. throw love::Exception("failed to create texture sampler");
  74. }
  75. }
  76. void Texture::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
  77. auto commandBuffer = vgfx->beginSingleTimeCommands();
  78. VkPipelineStageFlags sourceStage;
  79. VkPipelineStageFlags destinationStage;
  80. VkImageMemoryBarrier barrier{};
  81. barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  82. barrier.oldLayout = oldLayout;
  83. barrier.newLayout = newLayout;
  84. barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  85. barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  86. barrier.image = image;
  87. barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  88. barrier.subresourceRange.baseMipLevel = 0;
  89. barrier.subresourceRange.levelCount = 1;
  90. barrier.subresourceRange.baseArrayLayer = 0;
  91. barrier.subresourceRange.layerCount = 1;
  92. if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
  93. barrier.srcAccessMask = 0;
  94. barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  95. sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  96. destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
  97. } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  98. barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  99. barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  100. sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
  101. destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  102. }
  103. else {
  104. throw love::Exception("unsupported lay transition");
  105. }
  106. vkCmdPipelineBarrier(
  107. commandBuffer,
  108. sourceStage, destinationStage,
  109. 0,
  110. 0, nullptr,
  111. 0, nullptr,
  112. 1, &barrier
  113. );
  114. vgfx->endSingleTimeCommands(commandBuffer);
  115. }
  116. void Texture::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
  117. auto commandBuffer = vgfx->beginSingleTimeCommands();
  118. VkBufferImageCopy region{};
  119. region.bufferOffset = 0;
  120. region.bufferRowLength = 0;
  121. region.bufferImageHeight = 0;
  122. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  123. region.imageSubresource.mipLevel = 0;
  124. region.imageSubresource.baseArrayLayer = 0;
  125. region.imageSubresource.layerCount = 1;
  126. region.imageOffset = { 0, 0, 0 };
  127. region.imageExtent = {
  128. width,
  129. height, 1
  130. };
  131. vkCmdCopyBufferToImage(
  132. commandBuffer,
  133. buffer,
  134. image,
  135. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  136. 1,
  137. &region
  138. );
  139. vgfx->endSingleTimeCommands(commandBuffer);
  140. }
  141. void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t size, int level, int slice, const Rect& r) {
  142. VkBuffer stagingBuffer;
  143. VmaAllocation vmaAllocation;
  144. VkBufferCreateInfo bufferCreateInfo{};
  145. bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  146. bufferCreateInfo.size = size;
  147. bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
  148. VmaAllocationCreateInfo allocCreateInfo = {};
  149. allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
  150. allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
  151. VmaAllocationInfo allocInfo;
  152. vmaCreateBuffer(allocator, &bufferCreateInfo, &allocCreateInfo, &stagingBuffer, &vmaAllocation, &allocInfo);
  153. memcpy(allocInfo.pMappedData, data, size);
  154. VkImageCreateInfo imageInfo{};
  155. imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  156. imageInfo.imageType = VK_IMAGE_TYPE_2D;
  157. imageInfo.extent.width = static_cast<uint32_t>(r.w);
  158. imageInfo.extent.height = static_cast<uint32_t>(r.h);
  159. imageInfo.extent.depth = 1;
  160. imageInfo.mipLevels = 1;
  161. imageInfo.arrayLayers = 1;
  162. imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
  163. imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  164. imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  165. imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
  166. imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  167. imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  168. VmaAllocationCreateInfo imageAllocationCreateInfo{};
  169. if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS) {
  170. throw love::Exception("failed to create image");
  171. }
  172. transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
  173. copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(r.w), static_cast<uint32_t>(r.h));
  174. transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  175. vmaDestroyBuffer(allocator, stagingBuffer, vmaAllocation);
  176. }
  177. }
  178. }
  179. }