SpiecsEngine
 
Loading...
Searching...
No Matches

◆ LoadSrc()

bool Spices::TextureLoader::LoadSrc ( const std::string & fileName,
const std::string & it,
Texture2D * outTexture,
bool isCreateCompressTexture = true )
staticprivate

Function of load a src file.

Parameters
[in]fileNamesrc file name.
[in]itfile direct folder.
[in]outTexturePointer of texture.
[in]isCreateCompressTextureCreate Ktx texture in disk if true.
Returns
Returns true if load file succeed.

Load Texture data.

Instance the VulkanImage as Texture2D Resource.

Set resource values.

Instance the Resource.

Transform Image Layout from undefined to transfer_dst.

Get Texture bytes.

Note
4 means 4 channels per texel, 1 means 1 bytes per texel channel.(RGBA8 Format support only)

Instance a staginBuffer.

Copy the data from texture bytes to staginBuffer.

Copy the data from staginBuffer to Image.

Release texture bytes.

Generate Image Mipmaps.

Create Image View.

Create Image Sampler.

Instance a VkBufferImageCopy.

The temp buffer image date copy to.

Instance a VkImageToMemoryCopyEXT.

Write mipmap data to ktxTexture.

Save to disk.

Load Texture data.

Instance the VulkanImage as Texture2D Resource.

Set resource values.

Instance the Resource.

Transform Image Layout from undefined to transfer_dst.

Get Texture bytes.

Note
4 means 4 channels per texel, 1 means 1 bytes per texel channel.(RGBA8 Format support only)

Instance a staginBuffer.

Copy the data from texture bytes to staginBuffer.

Copy the data from staginBuffer to Image.

Release texture bytes.

Generate Image Mipmaps.

Create Image View.

Create Image Sampler.

Instance a VkBufferImageCopy.

The temp buffer image date copy to.

Instance a VkImageToMemoryCopyEXT.

Write mipmap data to ktxTexture.

Save to disk.

Definition at line 272 of file TextureLoader.cpp.

273 {
275
276 std::string filePath;
277 std::string binPath;
278 if (it == "")
279 {
280 assert(!isCreateCompressTexture);
281
282 filePath = fileName;
283 }
284 else
285 {
286 const std::vector<std::string> splitString = StringLibrary::SplitString(fileName, '.');
287 filePath = it + defaultTexturePath + fileName;
288 binPath = it + binTexturePath + splitString[0] + ".ktx";
289 }
290
294 int width;
295 int height;
296 int texChannels;
297 stbi_uc* pixels = stbi_load(filePath.c_str(), &width, &height, &texChannels, STBI_rgb_alpha);
298 if (!pixels)
299 {
300 SPICES_CORE_ERROR("Failed to load texture image!")
301 }
302
306 outTexture->m_Resource = std::make_shared<VulkanImage>(VulkanRenderBackend::GetState());
307 auto resourceptr = outTexture->GetResource<VulkanImage>();
308
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;
315
316 VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT; // Can be Used for Sample
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;
320
324 resourceptr->CreateImage(
325 resourceptr->m_VulkanState,
326 fileName ,
327 VK_IMAGE_TYPE_2D ,
328 resourceptr->m_Width ,
329 resourceptr->m_Height ,
330 1 , // 1 layers.
331 VK_SAMPLE_COUNT_1_BIT , // No MASS.
332 VK_FORMAT_R8G8B8A8_UNORM , // RGBA8 Format.
333 VK_IMAGE_TILING_OPTIMAL , // Tiling Optimal.
334 usage ,
335 0 ,
336 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
337 resourceptr->m_MipLevels
338 );
339
343 resourceptr->TransitionImageLayout(
344 resourceptr->m_Format,
345 VK_IMAGE_LAYOUT_UNDEFINED,
346 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
347 );
348
353 const VkDeviceSize imageSize = static_cast<uint64_t>(resourceptr->m_Width * resourceptr->m_Height * 4 * 1);
354
358 VulkanBuffer stagingBuffer(
359 resourceptr->m_VulkanState,
360 "StagingBuffer",
361 imageSize,
362 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
363 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
364 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
365 );
366
370 stagingBuffer.WriteToBuffer(pixels);
371
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)
380 );
381
385 stbi_image_free(pixels);
386
390 resourceptr->GenerateMipmaps(
391 resourceptr->m_Format,
392 resourceptr->m_Width,
393 resourceptr->m_Height
394 );
395
399 resourceptr->CreateImageView(
400 resourceptr->m_Format ,
401 VK_IMAGE_VIEW_TYPE_2D ,
402 VK_IMAGE_ASPECT_COLOR_BIT
403 );
404
408 resourceptr->CreateSampler();
409
410 auto deviceCopyF = [&](uint32_t w, uint32_t h, int mip, std::vector<unsigned char>& data) {
411
415 VkBufferImageCopy region{};
416 region.bufferOffset = 0;
417 region.bufferRowLength = 0;
418 region.bufferImageHeight = 0;
419
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;
424
425 region.imageOffset.x = 0;
426 region.imageOffset.y = 0;
427 region.imageExtent = { w, h, 1 };
428
429 const uint32_t size = w * h * 4;
430
434 VulkanBuffer copyStagingBuffer(
435 resourceptr->m_VulkanState,
436 "StagingBuffer",
437 size,
438 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
439 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
440 );
441
442 resourceptr->CopyImageToBuffer(copyStagingBuffer.Get(), { region });
443
444 copyStagingBuffer.WriteFromBuffer(reinterpret_cast<void*>(data.data()));
445 };
446
447 auto hostCopyF = [&](uint32_t w, uint32_t h, int mip, std::vector<unsigned char>& data) {
448
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();
461
462 resourceptr->CopyImageToMemoryHost({ memoryCopy });
463 };
464
465 if (!isCreateCompressTexture)
466 {
467 return true;
468 }
469
470 ktxTexture2* ktxTexture = Transcoder::CreateKTX2Texture(resourceptr->m_Width, resourceptr->m_Height);
471 for (uint32_t i = 0; i < resourceptr->m_MipLevels; i++)
472 {
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;
476
477 std::vector<unsigned char> data;
478 data.resize(size);
479
480 if (hostCopy)
481 {
482 hostCopyF(w, h, i, data);
483 }
484 else
485 {
486 deviceCopyF(w, h, i, data);
487 }
488
492 Transcoder::WriteData(ktxTexture, resourceptr->m_MipLevels - 1 - i, data.data(), size);
493 }
494
498 Transcoder::SaveToDisk(ktxTexture, binPath);
499
500 return true;
501 }
#define SPICES_PROFILE_ZONE
static std::vector< std::string > SplitString(const std::string &input, char delimiter)
Split a string to a string vector container use a char.
static bool SaveToDisk(ktxTexture2 *texture, const std::string &filePath)
Save a src image data to a ktx file.
static bool WriteData(ktxTexture2 *texture, uint32_t mipLevel, const unsigned char *data, uint32_t size)
Write Data to ktxtexture.
static ktxTexture2 * CreateKTX2Texture(int &width, int &height)
Create a ktx2 Texture.
bool IsHostCopyable() const
Check if this image format can copy from host to gpu directly.
static VulkanState & GetState()
Get VulkanState in use.
const std::string binTexturePath
const std::string defaultTexturePath
Const variable: Original Image File Path.

References Spices::defaultTexturePath, and Spices::VulkanRenderBackend::GetState().

Referenced by Load().