TextureVK.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2024 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Renderer/VK/TextureVK.h>
  6. #include <Renderer/VK/RendererVK.h>
  7. #include <Renderer/VK/FatalErrorIfFailedVK.h>
  8. #include <Image/BlitSurface.h>
  9. TextureVK::TextureVK(RendererVK *inRenderer, const Surface *inSurface) :
  10. Texture(inSurface->GetWidth(), inSurface->GetHeight()),
  11. mRenderer(inRenderer)
  12. {
  13. ESurfaceFormat format = inSurface->GetFormat();
  14. VkFormat vk_format = VK_FORMAT_B8G8R8A8_UNORM;
  15. switch (format)
  16. {
  17. case ESurfaceFormat::A4L4: vk_format = VK_FORMAT_R8G8_UNORM; format = ESurfaceFormat::A8L8; break;
  18. case ESurfaceFormat::L8: vk_format = VK_FORMAT_R8_UNORM; break;
  19. case ESurfaceFormat::A8: vk_format = VK_FORMAT_A8_UNORM_KHR; break;
  20. case ESurfaceFormat::A8L8: vk_format = VK_FORMAT_R8G8_UNORM; break;
  21. case ESurfaceFormat::R5G6B5: vk_format = VK_FORMAT_B5G6R5_UNORM_PACK16; break;
  22. case ESurfaceFormat::X1R5G5B5: vk_format = VK_FORMAT_B5G5R5A1_UNORM_PACK16; format = ESurfaceFormat::A1R5G5B5; break;
  23. case ESurfaceFormat::X4R4G4B4: vk_format = VK_FORMAT_B4G4R4A4_UNORM_PACK16; format = ESurfaceFormat::A4R4G4B4; break;
  24. case ESurfaceFormat::A1R5G5B5: vk_format = VK_FORMAT_B5G5R5A1_UNORM_PACK16; break;
  25. case ESurfaceFormat::A4R4G4B4: vk_format = VK_FORMAT_B4G4R4A4_UNORM_PACK16; break;
  26. case ESurfaceFormat::R8G8B8: vk_format = VK_FORMAT_B8G8R8_UNORM; break;
  27. case ESurfaceFormat::B8G8R8: vk_format = VK_FORMAT_B8G8R8_UNORM; break;
  28. case ESurfaceFormat::X8R8G8B8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::A8R8G8B8; break;
  29. case ESurfaceFormat::X8B8G8R8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::X8R8G8B8; break;
  30. case ESurfaceFormat::A8R8G8B8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;
  31. case ESurfaceFormat::A8B8G8R8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::A8R8G8B8; break;
  32. case ESurfaceFormat::Invalid:
  33. default: JPH_ASSERT(false); break;
  34. }
  35. // Blit the surface to another temporary surface if the format changed
  36. const Surface *surface = inSurface;
  37. Ref<Surface> tmp;
  38. if (format != inSurface->GetFormat())
  39. {
  40. tmp = new SoftwareSurface(mWidth, mHeight, format);
  41. BlitSurface(inSurface, tmp);
  42. surface = tmp;
  43. }
  44. int bpp = surface->GetBytesPerPixel();
  45. VkDeviceSize image_size = VkDeviceSize(mWidth) * mHeight * bpp;
  46. VkDevice device = mRenderer->GetDevice();
  47. BufferVK staging_buffer;
  48. mRenderer->CreateBuffer(image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer);
  49. // Copy data to upload texture
  50. surface->Lock(ESurfaceLockMode::Read);
  51. void *data;
  52. vkMapMemory(device, staging_buffer.mMemory, staging_buffer.mOffset, image_size, 0, &data);
  53. for (int y = 0; y < mHeight; ++y)
  54. memcpy(reinterpret_cast<uint8 *>(data) + y * mWidth * bpp, surface->GetData() + y * surface->GetStride(), mWidth * bpp);
  55. vkUnmapMemory(device, staging_buffer.mMemory);
  56. surface->UnLock();
  57. // Create destination image
  58. mRenderer->CreateImage(mWidth, mHeight, vk_format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mImage, mImageMemory);
  59. VkCommandBuffer command_buffer = mRenderer->StartTempCommandBuffer();
  60. // Make the image suitable for transferring to
  61. TransitionImageLayout(command_buffer, mImage, vk_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
  62. // Copy the data to the destination image
  63. VkBufferImageCopy region = {};
  64. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  65. region.imageSubresource.layerCount = 1;
  66. region.imageExtent = { uint32(mWidth), uint32(mHeight), 1 };
  67. vkCmdCopyBufferToImage(command_buffer, staging_buffer.mBuffer, mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
  68. // Make the image suitable for sampling
  69. TransitionImageLayout(command_buffer, mImage, vk_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  70. mRenderer->EndTempCommandBuffer(command_buffer);
  71. // Destroy temporary buffer
  72. mRenderer->FreeBuffer(staging_buffer);
  73. CreateImageViewAndDescriptorSet(vk_format, VK_IMAGE_ASPECT_COLOR_BIT, mRenderer->GetTextureSamplerRepeat());
  74. }
  75. TextureVK::TextureVK(RendererVK *inRenderer, int inWidth, int inHeight) :
  76. Texture(inWidth, inHeight),
  77. mRenderer(inRenderer)
  78. {
  79. VkFormat vk_format = mRenderer->FindDepthFormat();
  80. // Create render target
  81. mRenderer->CreateImage(mWidth, mHeight, vk_format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mImage, mImageMemory);
  82. CreateImageViewAndDescriptorSet(vk_format, VK_IMAGE_ASPECT_DEPTH_BIT, mRenderer->GetTextureSamplerShadow());
  83. }
  84. TextureVK::~TextureVK()
  85. {
  86. if (mImage != VK_NULL_HANDLE)
  87. {
  88. VkDevice device = mRenderer->GetDevice();
  89. vkDeviceWaitIdle(device);
  90. vkDestroyImageView(device, mImageView, nullptr);
  91. mRenderer->DestroyImage(mImage, mImageMemory);
  92. }
  93. }
  94. void TextureVK::Bind() const
  95. {
  96. if (mDescriptorSet != VK_NULL_HANDLE)
  97. vkCmdBindDescriptorSets(mRenderer->GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, mRenderer->GetPipelineLayout(), 1, 1, &mDescriptorSet, 0, nullptr);
  98. }
  99. void TextureVK::CreateImageViewAndDescriptorSet(VkFormat inFormat, VkImageAspectFlags inAspectFlags, VkSampler inSampler)
  100. {
  101. VkDevice device = mRenderer->GetDevice();
  102. // Create image view
  103. mImageView = mRenderer->CreateImageView(mImage, inFormat, inAspectFlags);
  104. // Allocate descriptor set for binding the texture
  105. VkDescriptorSetLayout layout = mRenderer->GetDescriptorSetLayoutTexture();
  106. VkDescriptorSetAllocateInfo descriptor_set_alloc_info = {};
  107. descriptor_set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  108. descriptor_set_alloc_info.descriptorPool = mRenderer->GetDescriptorPool();
  109. descriptor_set_alloc_info.descriptorSetCount = 1;
  110. descriptor_set_alloc_info.pSetLayouts = &layout;
  111. FatalErrorIfFailed(vkAllocateDescriptorSets(device, &descriptor_set_alloc_info, &mDescriptorSet));
  112. VkDescriptorImageInfo image_info = {};
  113. image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  114. image_info.imageView = mImageView;
  115. image_info.sampler = inSampler;
  116. VkWriteDescriptorSet descriptor_write = {};
  117. descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  118. descriptor_write.dstSet = mDescriptorSet;
  119. descriptor_write.dstBinding = 0;
  120. descriptor_write.dstArrayElement = 0;
  121. descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  122. descriptor_write.descriptorCount = 1;
  123. descriptor_write.pImageInfo = &image_info;
  124. vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, nullptr);
  125. }
  126. void TextureVK::TransitionImageLayout(VkCommandBuffer inCommandBuffer, VkImage inImage, VkFormat inFormat, VkImageLayout inOldLayout, VkImageLayout inNewLayout)
  127. {
  128. VkImageMemoryBarrier barrier = {};
  129. barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  130. barrier.oldLayout = inOldLayout;
  131. barrier.newLayout = inNewLayout;
  132. barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  133. barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  134. barrier.image = inImage;
  135. barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  136. barrier.subresourceRange.levelCount = 1;
  137. barrier.subresourceRange.layerCount = 1;
  138. if (inOldLayout == VK_IMAGE_LAYOUT_UNDEFINED && inNewLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
  139. {
  140. barrier.srcAccessMask = 0;
  141. barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  142. vkCmdPipelineBarrier(inCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
  143. }
  144. else if (inOldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && inNewLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
  145. {
  146. barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  147. barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  148. vkCmdPipelineBarrier(inCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
  149. }
  150. }