Started replacing gli with libktx

This commit is contained in:
Sascha Willems 2019-08-02 20:41:44 +02:00
parent 70cfb3e756
commit 1a6042e82d
6 changed files with 125 additions and 119 deletions

3
.gitmodules vendored
View file

@ -4,3 +4,6 @@
[submodule "external/gli"] [submodule "external/gli"]
path = external/gli path = external/gli
url = https://github.com/g-truc/gli url = https://github.com/g-truc/gli
[submodule "external/ktx"]
path = external/ktx
url = https://github.com/KhronosGroup/KTX-Software

View file

@ -126,4 +126,5 @@ ENDIF(WIN32)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
add_subdirectory(base) add_subdirectory(base)
add_subdirectory(examples) add_subdirectory(examples)
add_subdirectory(external)

View file

@ -1,10 +1,10 @@
file(GLOB BASE_SRC "*.cpp" "../external/imgui/*.cpp") file(GLOB BASE_SRC "*.cpp" "*.hpp" "../external/imgui/*.cpp")
file(GLOB BASE_HEADERS "*.hpp") file(GLOB BASE_HEADERS "*.hpp")
if(WIN32) if(WIN32)
add_library(base STATIC ${BASE_SRC}) add_library(base STATIC ${BASE_SRC})
target_link_libraries(base ${Vulkan_LIBRARY} ${ASSIMP_LIBRARIES} ${WINLIBS}) target_link_libraries(base ${Vulkan_LIBRARY} ${ASSIMP_LIBRARIES} ${WINLIBS} ktx)
else(WIN32) else(WIN32)
add_library(base STATIC ${BASE_SRC}) add_library(base STATIC ${BASE_SRC})
target_link_libraries(base ${Vulkan_LIBRARY} ${ASSIMP_LIBRARIES} ${XCB_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(base ${Vulkan_LIBRARY} ${ASSIMP_LIBRARIES} ${XCB_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ktx)
endif(WIN32) endif(WIN32)

View file

@ -1,7 +1,7 @@
/* /*
* Vulkan texture loader * Vulkan texture loader
* *
* Copyright(C) 2016-2017 by Sascha Willems - www.saschawillems.de * Copyright(C) by Sascha Willems - www.saschawillems.de
* *
* This code is licensed under the MIT license(MIT) (http://opensource.org/licenses/MIT) * This code is licensed under the MIT license(MIT) (http://opensource.org/licenses/MIT)
*/ */
@ -15,7 +15,8 @@
#include "vulkan/vulkan.h" #include "vulkan/vulkan.h"
#include <gli/gli.hpp> #include <ktx.h>
#include <ktxvulkan.h>
#include "VulkanTools.h" #include "VulkanTools.h"
#include "VulkanDevice.hpp" #include "VulkanDevice.hpp"
@ -39,11 +40,8 @@ namespace vks
uint32_t mipLevels; uint32_t mipLevels;
uint32_t layerCount; uint32_t layerCount;
VkDescriptorImageInfo descriptor; VkDescriptorImageInfo descriptor;
/** @brief Optional sampler to use with this texture */
VkSampler sampler; VkSampler sampler;
/** @brief Update image descriptor from current sampler, view and image layout */
void updateDescriptor() void updateDescriptor()
{ {
descriptor.sampler = sampler; descriptor.sampler = sampler;
@ -51,7 +49,6 @@ namespace vks
descriptor.imageLayout = imageLayout; descriptor.imageLayout = imageLayout;
} }
/** @brief Release all Vulkan resources held by this texture */
void destroy() void destroy()
{ {
vkDestroyImageView(device->logicalDevice, view, nullptr); vkDestroyImageView(device->logicalDevice, view, nullptr);
@ -62,6 +59,35 @@ namespace vks
} }
vkFreeMemory(device->logicalDevice, deviceMemory, nullptr); vkFreeMemory(device->logicalDevice, deviceMemory, nullptr);
} }
ktxResult loadKTXFile(std::string filename, ktxTexture **target)
{
ktxResult result = KTX_SUCCESS;
#if defined(__ANDROID__)
// Textures are stored inside the apk on Android (compressed)
// So they need to be loaded via the asset manager
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
if (!asset) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
size_t size = AAsset_getLength(asset);
assert(size > 0);
void *textureData = malloc(size);
AAsset_read(asset, textureData, size);
AAsset_close(asset);
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, target);
free(textureData);
#else
if (!vks::tools::fileExists(filename)) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, target);
#endif
return result;
}
}; };
/** @brief 2D texture */ /** @brief 2D texture */
@ -70,7 +96,7 @@ namespace vks
/** /**
* Load a 2D texture including all mip levels * Load a 2D texture including all mip levels
* *
* @param filename File to load (supports .ktx and .dds) * @param filename File to load (supports .ktx)
* @param format Vulkan format of the image data stored in the file * @param format Vulkan format of the image data stored in the file
* @param device Vulkan device to create the texture on * @param device Vulkan device to create the texture on
* @param copyQueue Queue used for the texture staging copy commands (must support transfer) * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
@ -88,35 +114,17 @@ namespace vks
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
bool forceLinear = false) bool forceLinear = false)
{ {
#if defined(__ANDROID__) ktxTexture* ktxTexture;
// Textures are stored inside the apk on Android (compressed) ktxResult result = loadKTXFile(filename, &ktxTexture);
// So they need to be loaded via the asset manager assert(result == KTX_SUCCESS);
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
if (!asset) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
size_t size = AAsset_getLength(asset);
assert(size > 0);
void *textureData = malloc(size);
AAsset_read(asset, textureData, size);
AAsset_close(asset);
gli::texture2d tex2D(gli::load((const char*)textureData, size));
free(textureData);
#else
if (!vks::tools::fileExists(filename)) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
gli::texture2d tex2D(gli::load(filename.c_str()));
#endif
assert(!tex2D.empty());
this->device = device; this->device = device;
width = static_cast<uint32_t>(tex2D[0].extent().x); width = ktxTexture->baseWidth;
height = static_cast<uint32_t>(tex2D[0].extent().y); height = ktxTexture->baseHeight;
mipLevels = static_cast<uint32_t>(tex2D.levels()); mipLevels = ktxTexture->numLevels;
ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture);
ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
// Get device properites for the requested texture format // Get device properites for the requested texture format
VkFormatProperties formatProperties; VkFormatProperties formatProperties;
@ -142,7 +150,7 @@ namespace vks
VkDeviceMemory stagingMemory; VkDeviceMemory stagingMemory;
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
bufferCreateInfo.size = tex2D.size(); bufferCreateInfo.size = ktxTextureSize;
// This buffer is used as a transfer source for the buffer copy // This buffer is used as a transfer source for the buffer copy
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@ -162,28 +170,28 @@ namespace vks
// Copy texture data into staging buffer // Copy texture data into staging buffer
uint8_t *data; uint8_t *data;
VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data)); VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data));
memcpy(data, tex2D.data(), tex2D.size()); memcpy(data, ktxTextureData, ktxTextureSize);
vkUnmapMemory(device->logicalDevice, stagingMemory); vkUnmapMemory(device->logicalDevice, stagingMemory);
// Setup buffer copy regions for each mip level // Setup buffer copy regions for each mip level
std::vector<VkBufferImageCopy> bufferCopyRegions; std::vector<VkBufferImageCopy> bufferCopyRegions;
uint32_t offset = 0;
for (uint32_t i = 0; i < mipLevels; i++) for (uint32_t i = 0; i < mipLevels; i++)
{ {
ktx_size_t offset;
assert(ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset) == KTX_SUCCESS);
VkBufferImageCopy bufferCopyRegion = {}; VkBufferImageCopy bufferCopyRegion = {};
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bufferCopyRegion.imageSubresource.mipLevel = i; bufferCopyRegion.imageSubresource.mipLevel = i;
bufferCopyRegion.imageSubresource.baseArrayLayer = 0; bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageSubresource.layerCount = 1;
bufferCopyRegion.imageExtent.width = static_cast<uint32_t>(tex2D[i].extent().x); bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> i;
bufferCopyRegion.imageExtent.height = static_cast<uint32_t>(tex2D[i].extent().y); bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> i;
bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.imageExtent.depth = 1;
bufferCopyRegion.bufferOffset = offset; bufferCopyRegion.bufferOffset = offset;
bufferCopyRegions.push_back(bufferCopyRegion); bufferCopyRegions.push_back(bufferCopyRegion);
offset += static_cast<uint32_t>(tex2D[i].size());
} }
// Create optimal tiled target image // Create optimal tiled target image
@ -312,7 +320,7 @@ namespace vks
VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, mappableMemory, 0, memReqs.size, 0, &data)); VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, mappableMemory, 0, memReqs.size, 0, &data));
// Copy image data into memory // Copy image data into memory
memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); memcpy(data, ktxTextureData, ktxTextureSize);
vkUnmapMemory(device->logicalDevice, mappableMemory); vkUnmapMemory(device->logicalDevice, mappableMemory);
@ -328,6 +336,8 @@ namespace vks
device->flushCommandBuffer(copyCmd, copyQueue); device->flushCommandBuffer(copyCmd, copyQueue);
} }
ktxTexture_Destroy(ktxTexture);
// Create a defaultsampler // Create a defaultsampler
VkSamplerCreateInfo samplerCreateInfo = {}; VkSamplerCreateInfo samplerCreateInfo = {};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
@ -552,7 +562,7 @@ namespace vks
/** /**
* Load a 2D texture array including all mip levels * Load a 2D texture array including all mip levels
* *
* @param filename File to load (supports .ktx and .dds) * @param filename File to load (supports .ktx)
* @param format Vulkan format of the image data stored in the file * @param format Vulkan format of the image data stored in the file
* @param device Vulkan device to create the texture on * @param device Vulkan device to create the texture on
* @param copyQueue Queue used for the texture staging copy commands (must support transfer) * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
@ -568,36 +578,18 @@ namespace vks
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{ {
#if defined(__ANDROID__) ktxTexture* ktxTexture;
// Textures are stored inside the apk on Android (compressed) ktxResult result = loadKTXFile(filename, &ktxTexture);
// So they need to be loaded via the asset manager assert(result == KTX_SUCCESS);
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
if (!asset) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
size_t size = AAsset_getLength(asset);
assert(size > 0);
void *textureData = malloc(size);
AAsset_read(asset, textureData, size);
AAsset_close(asset);
gli::texture2d_array tex2DArray(gli::load((const char*)textureData, size));
free(textureData);
#else
if (!vks::tools::fileExists(filename)) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
gli::texture2d_array tex2DArray(gli::load(filename));
#endif
assert(!tex2DArray.empty());
this->device = device; this->device = device;
width = static_cast<uint32_t>(tex2DArray.extent().x); width = ktxTexture->baseWidth;
height = static_cast<uint32_t>(tex2DArray.extent().y); height = ktxTexture->baseHeight;
layerCount = static_cast<uint32_t>(tex2DArray.layers()); layerCount = ktxTexture->numLayers;
mipLevels = static_cast<uint32_t>(tex2DArray.levels()); mipLevels = ktxTexture->numLevels;
ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture);
ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
@ -607,7 +599,7 @@ namespace vks
VkDeviceMemory stagingMemory; VkDeviceMemory stagingMemory;
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
bufferCreateInfo.size = tex2DArray.size(); bufferCreateInfo.size = ktxTextureSize;
// This buffer is used as a transfer source for the buffer copy // This buffer is used as a transfer source for the buffer copy
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@ -627,31 +619,30 @@ namespace vks
// Copy texture data into staging buffer // Copy texture data into staging buffer
uint8_t *data; uint8_t *data;
VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data)); VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data));
memcpy(data, tex2DArray.data(), static_cast<size_t>(tex2DArray.size())); memcpy(data, ktxTextureData, ktxTextureSize);
vkUnmapMemory(device->logicalDevice, stagingMemory); vkUnmapMemory(device->logicalDevice, stagingMemory);
// Setup buffer copy regions for each layer including all of it's miplevels // Setup buffer copy regions for each layer including all of it's miplevels
std::vector<VkBufferImageCopy> bufferCopyRegions; std::vector<VkBufferImageCopy> bufferCopyRegions;
size_t offset = 0;
for (uint32_t layer = 0; layer < layerCount; layer++) for (uint32_t layer = 0; layer < layerCount; layer++)
{ {
for (uint32_t level = 0; level < mipLevels; level++) for (uint32_t level = 0; level < mipLevels; level++)
{ {
ktx_size_t offset;
assert(ktxTexture_GetImageOffset(ktxTexture, level, layer, 0, &offset) == KTX_SUCCESS);
VkBufferImageCopy bufferCopyRegion = {}; VkBufferImageCopy bufferCopyRegion = {};
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bufferCopyRegion.imageSubresource.mipLevel = level; bufferCopyRegion.imageSubresource.mipLevel = level;
bufferCopyRegion.imageSubresource.baseArrayLayer = layer; bufferCopyRegion.imageSubresource.baseArrayLayer = layer;
bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageSubresource.layerCount = 1;
bufferCopyRegion.imageExtent.width = static_cast<uint32_t>(tex2DArray[layer][level].extent().x); bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level;
bufferCopyRegion.imageExtent.height = static_cast<uint32_t>(tex2DArray[layer][level].extent().y); bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level;
bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.imageExtent.depth = 1;
bufferCopyRegion.bufferOffset = offset; bufferCopyRegion.bufferOffset = offset;
bufferCopyRegions.push_back(bufferCopyRegion); bufferCopyRegions.push_back(bufferCopyRegion);
// Increase offset into staging buffer for next level / face
offset += tex2DArray[layer][level].size();
} }
} }
@ -750,6 +741,7 @@ namespace vks
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view));
// Clean up staging resources // Clean up staging resources
ktxTexture_Destroy(ktxTexture);
vkFreeMemory(device->logicalDevice, stagingMemory, nullptr); vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr); vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);
@ -764,7 +756,7 @@ namespace vks
/** /**
* Load a cubemap texture including all mip levels from a single file * Load a cubemap texture including all mip levels from a single file
* *
* @param filename File to load (supports .ktx and .dds) * @param filename File to load (supports .ktx)
* @param format Vulkan format of the image data stored in the file * @param format Vulkan format of the image data stored in the file
* @param device Vulkan device to create the texture on * @param device Vulkan device to create the texture on
* @param copyQueue Queue used for the texture staging copy commands (must support transfer) * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
@ -780,35 +772,17 @@ namespace vks
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{ {
#if defined(__ANDROID__) ktxTexture* ktxTexture;
// Textures are stored inside the apk on Android (compressed) ktxResult result = loadKTXFile(filename, &ktxTexture);
// So they need to be loaded via the asset manager assert(result == KTX_SUCCESS);
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
if (!asset) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
size_t size = AAsset_getLength(asset);
assert(size > 0);
void *textureData = malloc(size);
AAsset_read(asset, textureData, size);
AAsset_close(asset);
gli::texture_cube texCube(gli::load((const char*)textureData, size));
free(textureData);
#else
if (!vks::tools::fileExists(filename)) {
vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
}
gli::texture_cube texCube(gli::load(filename));
#endif
assert(!texCube.empty());
this->device = device; this->device = device;
width = static_cast<uint32_t>(texCube.extent().x); width = ktxTexture->baseWidth;
height = static_cast<uint32_t>(texCube.extent().y); height = ktxTexture->baseHeight;
mipLevels = static_cast<uint32_t>(texCube.levels()); mipLevels = ktxTexture->numLevels;
ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture);
ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
@ -818,7 +792,7 @@ namespace vks
VkDeviceMemory stagingMemory; VkDeviceMemory stagingMemory;
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
bufferCreateInfo.size = texCube.size(); bufferCreateInfo.size = ktxTextureSize;
// This buffer is used as a transfer source for the buffer copy // This buffer is used as a transfer source for the buffer copy
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@ -838,31 +812,30 @@ namespace vks
// Copy texture data into staging buffer // Copy texture data into staging buffer
uint8_t *data; uint8_t *data;
VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data)); VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data));
memcpy(data, texCube.data(), texCube.size()); memcpy(data, ktxTextureData, ktxTextureSize);
vkUnmapMemory(device->logicalDevice, stagingMemory); vkUnmapMemory(device->logicalDevice, stagingMemory);
// Setup buffer copy regions for each face including all of it's miplevels // Setup buffer copy regions for each face including all of it's miplevels
std::vector<VkBufferImageCopy> bufferCopyRegions; std::vector<VkBufferImageCopy> bufferCopyRegions;
size_t offset = 0;
for (uint32_t face = 0; face < 6; face++) for (uint32_t face = 0; face < 6; face++)
{ {
for (uint32_t level = 0; level < mipLevels; level++) for (uint32_t level = 0; level < mipLevels; level++)
{ {
ktx_size_t offset;
assert(ktxTexture_GetImageOffset(ktxTexture, level, 0, face, &offset) == KTX_SUCCESS);
VkBufferImageCopy bufferCopyRegion = {}; VkBufferImageCopy bufferCopyRegion = {};
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bufferCopyRegion.imageSubresource.mipLevel = level; bufferCopyRegion.imageSubresource.mipLevel = level;
bufferCopyRegion.imageSubresource.baseArrayLayer = face; bufferCopyRegion.imageSubresource.baseArrayLayer = face;
bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageSubresource.layerCount = 1;
bufferCopyRegion.imageExtent.width = static_cast<uint32_t>(texCube[face][level].extent().x); bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level;
bufferCopyRegion.imageExtent.height = static_cast<uint32_t>(texCube[face][level].extent().y); bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level;
bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.imageExtent.depth = 1;
bufferCopyRegion.bufferOffset = offset; bufferCopyRegion.bufferOffset = offset;
bufferCopyRegions.push_back(bufferCopyRegion); bufferCopyRegions.push_back(bufferCopyRegion);
// Increase offset into staging buffer for next level / face
offset += texCube[face][level].size();
} }
} }
@ -965,6 +938,7 @@ namespace vks
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view));
// Clean up staging resources // Clean up staging resources
ktxTexture_Destroy(ktxTexture);
vkFreeMemory(device->logicalDevice, stagingMemory, nullptr); vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr); vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);

27
external/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.8)
project(external LANGUAGES C CXX)
# libktx
message(STATUS "Adding libktx")
set(KTX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ktx)
set(KTX_SOURCES
${KTX_DIR}/lib/texture.c
${KTX_DIR}/lib/hashlist.c
${KTX_DIR}/lib/checkheader.c
${KTX_DIR}/lib/swap.c
${KTX_DIR}/lib/memstream.c
${KTX_DIR}/lib/filestream.c
${KTX_DIR}/lib/vkloader.c
)
set(KTX_INCLUDE
${KTX_DIR}/include
${KTX_DIR}/lib
${KTX_DIR}/other_include
)
add_library(ktx ${KTX_SOURCES})
target_include_directories(ktx PUBLIC ${KTX_INCLUDE})
set_property(TARGET ktx PROPERTY FOLDER "external")

1
external/ktx vendored Submodule

@ -0,0 +1 @@
Subproject commit 726d14d02c95bb21ec9e43807751b491d295dd3c