2
3
4
5
9#include "Render/Vulkan/VulkanImage.h"
10#include "Render/Vulkan/VulkanRenderBackend.h"
11#include "Core/Library/FileLibrary.h"
12#include "Systems/ResourceSystem.h"
13#include "Resources/Texture/Transcoder.h"
17#include "Resources/Texture/Texture2D.h"
18#include "Resources/Texture/Texture2DCube.h"
23
24
32 std::filesystem::path path(fileName);
33 if (path.is_absolute())
35 if (path.extension().string() ==
"ktx")
37 LoadBin(fileName,
"", outTexture);
41 LoadSrc(fileName,
"", outTexture,
false);
49 [&](
const std::string& it) {
50 LoadBin(fileName, it, outTexture);
52 [&](
const std::string& it) {
55
56
57 std::unique_ptr<Texture2D> texture = std::make_unique<Texture2D>();
58 LoadSrc(fileName, it, texture.get());
59 LoadBin(fileName, it, outTexture);
70 const std::string& fileName,
71 std::function<
void(
const std::string&)> binF,
72 std::function<
void(
const std::string&)> srcF
77 const std::vector<std::string> splitString = StringLibrary::SplitString(fileName,
'.');
79 for (
auto& it : ResourceSystem::GetSearchFolder())
81 std::string filePath = it + binTexturePath + splitString[0] +
".ktx";
82 if (FileLibrary::FileLibrary_Exists(filePath.c_str()))
88 for (
auto& it : ResourceSystem::GetSearchFolder())
90 std::string filePath = it + defaultTexturePath + fileName;
91 if (FileLibrary::FileLibrary_Exists(filePath.c_str()))
99 ss <<
"File: " << fileName <<
" Not Find";
101 SPICES_CORE_ERROR(ss.str())
116 std::vector<std::string> splitString = StringLibrary::SplitString(fileName,
'.');
117 binPath = it + binTexturePath + splitString[0] +
".ktx";
120 ktxTexture2* texture =
nullptr;
121 Transcoder::LoadFromKTX(binPath, texture);
124
125
127 auto resourceptr = outTexture->GetResource<
VulkanImage>();
129 VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT;
130 bool hostCopy = VulkanImage::IsHostCopyable(resourceptr->m_VulkanState,
static_cast<VkFormat>(texture->vkFormat));
131 usage |= hostCopy ? VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT : VK_IMAGE_USAGE_TRANSFER_DST_BIT;
134
135
136 resourceptr->CreateImage(
137 resourceptr->m_VulkanState ,
139 static_cast<VkImageType>(texture->numDimensions - 1),
141 texture->baseHeight ,
143 VK_SAMPLE_COUNT_1_BIT ,
144 static_cast<VkFormat>(texture->vkFormat) ,
145 VK_IMAGE_TILING_OPTIMAL ,
148 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
155
156
157 resourceptr->TransitionImageLayout(
158 resourceptr->m_Format,
159 VK_IMAGE_LAYOUT_UNDEFINED,
160 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
163 std::vector<VkMemoryToImageCopyEXT> copies;
164 for (uint32_t mip_level = 0; mip_level < texture->numLevels; mip_level++)
166 VkMemoryToImageCopyEXT memoryCopy{};
167 memoryCopy.sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT;
168 memoryCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
169 memoryCopy.imageSubresource.mipLevel = mip_level;
170 memoryCopy.imageSubresource.baseArrayLayer = 0;
171 memoryCopy.imageSubresource.layerCount = 1;
172 memoryCopy.imageExtent.width = std::max((uint32_t)1, texture->baseWidth >> mip_level);
173 memoryCopy.imageExtent.height = std::max((uint32_t)1, texture->baseHeight >> mip_level);
174 memoryCopy.imageExtent.depth = 1;
175 memoryCopy.pHostPointer = texture->pData + Transcoder::GetMipmapOffset(texture, mip_level);
177 copies.push_back(memoryCopy);
181
182
183 resourceptr->CopyMemoryToImageHost(copies);
188
189
191 resourceptr->m_VulkanState,
194 VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
195 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
196 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
200
201
202 stagingBuffer.WriteToBuffer(texture->pData);
205
206
207 resourceptr->TransitionImageLayout(
208 resourceptr->m_Format ,
209 VK_IMAGE_LAYOUT_UNDEFINED ,
210 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
213 std::vector<VkBufferImageCopy> regions;
214 for (uint32_t mip_level = 0; mip_level < texture->numLevels; mip_level++)
216 VkBufferImageCopy region {};
217 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
218 region.imageSubresource.mipLevel = mip_level;
219 region.imageSubresource.baseArrayLayer = 0;
220 region.imageSubresource.layerCount = 1;
221 region.imageExtent.width = std::max((uint32_t)1, texture->baseWidth >> mip_level);
222 region.imageExtent.height = std::max((uint32_t)1, texture->baseHeight >> mip_level);
223 region.imageExtent.depth = 1;
224 region.bufferOffset = Transcoder::GetMipmapOffset(texture, mip_level);
226 regions.push_back(region);
230
231
232 resourceptr->CopyBufferToImage(
233 stagingBuffer.Get() ,
234 resourceptr->m_Image ,
235 static_cast<uint32_t>(resourceptr->m_Width) ,
236 static_cast<uint32_t>(resourceptr->m_Height),
241
242
243 resourceptr->TransitionImageLayout(
244 resourceptr->m_Format ,
245 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
246 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
251
252
253 resourceptr->CreateImageView(
254 resourceptr->m_Format ,
255 VK_IMAGE_VIEW_TYPE_2D ,
256 VK_IMAGE_ASPECT_COLOR_BIT
260
261
262 resourceptr->CreateSampler();
265
266
267 Transcoder::DestroyktxTexture2(texture);
276 std::string filePath;
280 assert(!isCreateCompressTexture);
286 const std::vector<std::string> splitString = StringLibrary::SplitString(fileName,
'.');
288 binPath = it + binTexturePath + splitString[0] +
".ktx";
292
293
297 stbi_uc* pixels = stbi_load(filePath.c_str(), &width, &height, &texChannels, STBI_rgb_alpha);
300 SPICES_CORE_ERROR(
"Failed to load texture image!")
304
305
307 auto resourceptr = outTexture->GetResource<
VulkanImage>();
310
311
312 resourceptr->m_Width = width;
313 resourceptr->m_Height = height;
314 resourceptr->m_MipLevels =
static_cast<uint32_t>(std::floor(std::log2(std::max(resourceptr->m_Width, resourceptr->m_Height)))) + 1;
316 VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT;
317 const bool hostCopy = VulkanImage::IsHostCopyable(resourceptr->m_VulkanState, VK_FORMAT_R8G8B8A8_UNORM);
318 usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
319 if (hostCopy) usage |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
322
323
324 resourceptr->CreateImage(
325 resourceptr->m_VulkanState,
328 resourceptr->m_Width ,
329 resourceptr->m_Height ,
331 VK_SAMPLE_COUNT_1_BIT ,
332 VK_FORMAT_R8G8B8A8_UNORM ,
333 VK_IMAGE_TILING_OPTIMAL ,
336 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
337 resourceptr->m_MipLevels
341
342
343 resourceptr->TransitionImageLayout(
344 resourceptr->m_Format,
345 VK_IMAGE_LAYOUT_UNDEFINED,
346 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
350
351
352
353 const VkDeviceSize imageSize =
static_cast<uint64_t>(resourceptr->m_Width * resourceptr->m_Height * 4 * 1);
356
357
359 resourceptr->m_VulkanState,
362 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
363 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
364 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
368
369
370 stagingBuffer.WriteToBuffer(pixels);
373
374
375 resourceptr->CopyBufferToImage(
376 stagingBuffer.Get() ,
377 resourceptr->m_Image ,
378 static_cast<uint32_t>(resourceptr->m_Width) ,
379 static_cast<uint32_t>(resourceptr->m_Height)
383
384
385 stbi_image_free(pixels);
388
389
390 resourceptr->GenerateMipmaps(
391 resourceptr->m_Format,
392 resourceptr->m_Width,
393 resourceptr->m_Height
397
398
399 resourceptr->CreateImageView(
400 resourceptr->m_Format ,
401 VK_IMAGE_VIEW_TYPE_2D ,
402 VK_IMAGE_ASPECT_COLOR_BIT
406
407
408 resourceptr->CreateSampler();
410 auto deviceCopyF = [&](uint32_t w, uint32_t h,
int mip, std::vector<
unsigned char>& data) {
413
414
415 VkBufferImageCopy region{};
416 region.bufferOffset = 0;
417 region.bufferRowLength = 0;
418 region.bufferImageHeight = 0;
420 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
421 region.imageSubresource.mipLevel = resourceptr->m_MipLevels - 1 - mip;
422 region.imageSubresource.baseArrayLayer = 0;
423 region.imageSubresource.layerCount = resourceptr->m_Layers;
425 region.imageOffset.x = 0;
426 region.imageOffset.y = 0;
427 region.imageExtent = { w, h, 1 };
429 const uint32_t size = w * h * 4;
432
433
435 resourceptr->m_VulkanState,
438 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
439 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
442 resourceptr->CopyImageToBuffer(copyStagingBuffer.Get(), { region });
444 copyStagingBuffer.WriteFromBuffer(
reinterpret_cast<
void*>(data.data()));
447 auto hostCopyF = [&](uint32_t w, uint32_t h,
int mip, std::vector<
unsigned char>& data) {
450
451
452 VkImageToMemoryCopyEXT memoryCopy{};
453 memoryCopy.sType = VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT;
454 memoryCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
455 memoryCopy.imageSubresource.mipLevel = resourceptr->m_MipLevels - 1 - mip;
456 memoryCopy.imageSubresource.baseArrayLayer = 0;
457 memoryCopy.imageSubresource.layerCount = resourceptr->m_Layers;
458 memoryCopy.imageOffset = { 0, 0, 0 };
459 memoryCopy.imageExtent = { w, h, 1 };
460 memoryCopy.pHostPointer = data.data();
462 resourceptr->CopyImageToMemoryHost({ memoryCopy });
465 if (!isCreateCompressTexture)
470 ktxTexture2* ktxTexture = Transcoder::CreateKTX2Texture(resourceptr->m_Width, resourceptr->m_Height);
471 for (uint32_t i = 0; i < resourceptr->m_MipLevels; i++)
473 const uint32_t w = std::max(1, resourceptr->m_Width >> resourceptr->m_MipLevels - 1 - i);
474 const uint32_t h = std::max(1, resourceptr->m_Height >> resourceptr->m_MipLevels - 1 - i);
475 const uint32_t size = w * h * 4;
477 std::vector<
unsigned char> data;
482 hostCopyF(w, h, i, data);
486 deviceCopyF(w, h, i, data);
490
491
492 Transcoder::WriteData(ktxTexture, resourceptr->m_MipLevels - 1 - i, data.data(), size);
496
497
498 Transcoder::SaveToDisk(ktxTexture, binPath);
#define SPICES_PROFILE_ZONE
Texture2DCube Class. This class defines the basic behaves of Texture2DCube.
Texture2D Class. This class defines the basic behaves of texture2D.
static void Load(const std::string &fileName, Texture2DCube *outTexture)
Load image to a Texture2DCube object.
static void Load(const std::string &fileName, Texture2D *outTexture)
Load image to a Texture2D object.
static bool LoadSrc(const std::string &fileName, const std::string &it, Texture2D *outTexture, bool isCreateCompressTexture=true)
Function of load a src file.
static bool LoadBin(const std::string &fileName, const std::string &it, Texture2D *outTexture)
Function of load a ktx file.
TextureLoader Class. This class only defines static function for load data from image file.
This Class is a Wrapper of VulkanBuffer.
static VulkanState & GetState()
Get VulkanState in use.
This class defines the render backend behaves of Vulkan.
const std::string binTexturePath
const std::string defaultTexturePath
Const variable: Original Image File Path.