diff --git a/.gitmodules b/.gitmodules index 614b2d14..2203fcc8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "external/glm"] path = external/glm url = https://github.com/g-truc/glm -[submodule "external/gli"] - path = external/gli - url = https://github.com/g-truc/gli +[submodule "external/ktx"] + path = external/ktx + url = https://github.com/KhronosGroup/KTX-Software diff --git a/CMakeLists.txt b/CMakeLists.txt index e54ba6ef..1e1a1d4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ endif() add_definitions(-D_CRT_SECURE_NO_WARNINGS) -add_definitions(-std=c++11) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") file(GLOB SOURCE *.cpp ) @@ -126,4 +126,5 @@ ENDIF(WIN32) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") add_subdirectory(base) -add_subdirectory(examples) \ No newline at end of file +add_subdirectory(examples) +add_subdirectory(external) \ No newline at end of file diff --git a/android/examples/base/CMakeLists.txt b/android/examples/base/CMakeLists.txt index 8d9e2130..812fa2db 100644 --- a/android/examples/base/CMakeLists.txt +++ b/android/examples/base/CMakeLists.txt @@ -12,10 +12,31 @@ include_directories(../../../external/imgui) include_directories(../../../external/assimp) include_directories(${ANDROID_NDK}/sources/android/native_app_glue) -target_link_libraries( - libbase - android - log - z - libassimp +set(KTX_DIR ../../../external/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 +) +set(KTX_INCLUDE + ${KTX_DIR}/include + ${KTX_DIR}/lib + ${KTX_DIR}/other_include +) + +add_library(libktx ${KTX_SOURCES}) +target_include_directories(libktx PUBLIC ${KTX_INCLUDE}) +set_property(TARGET libktx PROPERTY FOLDER "external") + + +target_link_libraries( + libbase + android + log + z + libassimp + libktx ) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 9061efdb..c284fd29 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -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") if(WIN32) 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) 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) \ No newline at end of file diff --git a/base/VulkanHeightmap.hpp b/base/VulkanHeightmap.hpp index b8c5033e..c96a3faa 100644 --- a/base/VulkanHeightmap.hpp +++ b/base/VulkanHeightmap.hpp @@ -1,18 +1,19 @@ /* * Heightmap terrain generator * -* Copyright (C) 2016 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) */ #include #include -#include #include "vulkan/vulkan.h" #include "VulkanDevice.hpp" #include "VulkanBuffer.hpp" +#include +#include namespace vks { @@ -75,27 +76,31 @@ namespace vks assert(device); assert(copyQueue != VK_NULL_HANDLE); + ktxResult result; + ktxTexture* ktxTexture; #if defined(__ANDROID__) - AAsset* asset = AAssetManager_open(assetManager, filename.c_str(), AASSET_MODE_STREAMING); + AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); assert(asset); size_t size = AAsset_getLength(asset); assert(size > 0); void *textureData = malloc(size); AAsset_read(asset, textureData, size); AAsset_close(asset); - gli::texture2d heightTex(gli::load((const char*)textureData, size)); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, target); free(textureData); #else - gli::texture2d heightTex(gli::load(filename)); + result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); #endif - dim = static_cast(heightTex.extent().x); + assert(result == KTX_SUCCESS); + ktx_size_t ktxSize = ktxTexture_GetImageSize(ktxTexture, 0); + ktx_uint8_t* ktxImage = ktxTexture_GetData(ktxTexture); + dim = ktxTexture->baseWidth; heightdata = new uint16_t[dim * dim]; - memcpy(heightdata, heightTex.data(), heightTex.size()); + memcpy(heightdata, ktxImage, ktxSize); this->scale = dim / patchsize; - this->heightScale = scale.y; + ktxTexture_Destroy(ktxTexture); // Generate vertices - Vertex * vertices = new Vertex[patchsize * patchsize * 4]; const float wx = 2.0f; diff --git a/base/VulkanTexture.hpp b/base/VulkanTexture.hpp index 0052097f..c23c1fd2 100644 --- a/base/VulkanTexture.hpp +++ b/base/VulkanTexture.hpp @@ -1,7 +1,7 @@ /* * 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) */ @@ -15,7 +15,8 @@ #include "vulkan/vulkan.h" -#include +#include +#include #include "VulkanTools.h" #include "VulkanDevice.hpp" @@ -39,11 +40,8 @@ namespace vks uint32_t mipLevels; uint32_t layerCount; VkDescriptorImageInfo descriptor; - - /** @brief Optional sampler to use with this texture */ VkSampler sampler; - /** @brief Update image descriptor from current sampler, view and image layout */ void updateDescriptor() { descriptor.sampler = sampler; @@ -51,7 +49,6 @@ namespace vks descriptor.imageLayout = imageLayout; } - /** @brief Release all Vulkan resources held by this texture */ void destroy() { vkDestroyImageView(device->logicalDevice, view, nullptr); @@ -62,6 +59,30 @@ namespace vks } vkFreeMemory(device->logicalDevice, deviceMemory, nullptr); } + + ktxResult loadKTXFile(std::string filename, ktxTexture **target) + { + ktxResult result = KTX_SUCCESS; +#if defined(__ANDROID__) + 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); + ktx_uint8_t *textureData = new ktx_uint8_t[size]; + AAsset_read(asset, textureData, size); + AAsset_close(asset); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, target); + delete[] 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 */ @@ -70,7 +91,7 @@ namespace vks /** * 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 device Vulkan device to create the texture on * @param copyQueue Queue used for the texture staging copy commands (must support transfer) @@ -88,35 +109,17 @@ namespace vks VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, bool forceLinear = false) { -#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); - - 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()); + ktxTexture* ktxTexture; + ktxResult result = loadKTXFile(filename, &ktxTexture); + assert(result == KTX_SUCCESS); this->device = device; - width = static_cast(tex2D[0].extent().x); - height = static_cast(tex2D[0].extent().y); - mipLevels = static_cast(tex2D.levels()); + width = ktxTexture->baseWidth; + height = ktxTexture->baseHeight; + 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 VkFormatProperties formatProperties; @@ -142,7 +145,7 @@ namespace vks VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = tex2D.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -162,28 +165,29 @@ namespace vks // Copy texture data into staging buffer uint8_t *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); // Setup buffer copy regions for each mip level std::vector bufferCopyRegions; - uint32_t offset = 0; for (uint32_t i = 0; i < mipLevels; i++) { + ktx_size_t offset; + KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset); + assert(result == KTX_SUCCESS); + VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = i; bufferCopyRegion.imageSubresource.baseArrayLayer = 0; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = static_cast(tex2D[i].extent().x); - bufferCopyRegion.imageExtent.height = static_cast(tex2D[i].extent().y); + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> i; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> i; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; bufferCopyRegions.push_back(bufferCopyRegion); - - offset += static_cast(tex2D[i].size()); } // Create optimal tiled target image @@ -312,7 +316,7 @@ namespace vks VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, mappableMemory, 0, memReqs.size, 0, &data)); // Copy image data into memory - memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); + memcpy(data, ktxTextureData, memReqs.size); vkUnmapMemory(device->logicalDevice, mappableMemory); @@ -328,6 +332,8 @@ namespace vks device->flushCommandBuffer(copyCmd, copyQueue); } + ktxTexture_Destroy(ktxTexture); + // Create a defaultsampler VkSamplerCreateInfo samplerCreateInfo = {}; samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; @@ -552,7 +558,7 @@ namespace vks /** * 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 device Vulkan device to create the texture on * @param copyQueue Queue used for the texture staging copy commands (must support transfer) @@ -568,36 +574,18 @@ namespace vks VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { -#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); - - 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()); + ktxTexture* ktxTexture; + ktxResult result = loadKTXFile(filename, &ktxTexture); + assert(result == KTX_SUCCESS); this->device = device; - width = static_cast(tex2DArray.extent().x); - height = static_cast(tex2DArray.extent().y); - layerCount = static_cast(tex2DArray.layers()); - mipLevels = static_cast(tex2DArray.levels()); + width = ktxTexture->baseWidth; + height = ktxTexture->baseHeight; + layerCount = ktxTexture->numLayers; + mipLevels = ktxTexture->numLevels; + + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; @@ -607,7 +595,7 @@ namespace vks VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = tex2DArray.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -627,31 +615,31 @@ namespace vks // Copy texture data into staging buffer uint8_t *data; VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, tex2DArray.data(), static_cast(tex2DArray.size())); + memcpy(data, ktxTextureData, ktxTextureSize); vkUnmapMemory(device->logicalDevice, stagingMemory); // Setup buffer copy regions for each layer including all of it's miplevels std::vector bufferCopyRegions; - size_t offset = 0; for (uint32_t layer = 0; layer < layerCount; layer++) { for (uint32_t level = 0; level < mipLevels; level++) { + ktx_size_t offset; + KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, level, layer, 0, &offset); + assert(result == KTX_SUCCESS); + VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = level; bufferCopyRegion.imageSubresource.baseArrayLayer = layer; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = static_cast(tex2DArray[layer][level].extent().x); - bufferCopyRegion.imageExtent.height = static_cast(tex2DArray[layer][level].extent().y); + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; bufferCopyRegions.push_back(bufferCopyRegion); - - // Increase offset into staging buffer for next level / face - offset += tex2DArray[layer][level].size(); } } @@ -750,6 +738,7 @@ namespace vks VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); // Clean up staging resources + ktxTexture_Destroy(ktxTexture); vkFreeMemory(device->logicalDevice, stagingMemory, nullptr); vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr); @@ -764,7 +753,7 @@ namespace vks /** * 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 device Vulkan device to create the texture on * @param copyQueue Queue used for the texture staging copy commands (must support transfer) @@ -780,35 +769,17 @@ namespace vks VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { -#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); - - 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()); + ktxTexture* ktxTexture; + ktxResult result = loadKTXFile(filename, &ktxTexture); + assert(result == KTX_SUCCESS); this->device = device; - width = static_cast(texCube.extent().x); - height = static_cast(texCube.extent().y); - mipLevels = static_cast(texCube.levels()); + width = ktxTexture->baseWidth; + height = ktxTexture->baseHeight; + mipLevels = ktxTexture->numLevels; + + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; @@ -818,7 +789,7 @@ namespace vks VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = texCube.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -838,31 +809,31 @@ namespace vks // Copy texture data into staging buffer uint8_t *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); // Setup buffer copy regions for each face including all of it's miplevels std::vector bufferCopyRegions; - size_t offset = 0; for (uint32_t face = 0; face < 6; face++) { for (uint32_t level = 0; level < mipLevels; level++) { + ktx_size_t offset; + KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, level, 0, face, &offset); + assert(result == KTX_SUCCESS); + VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = level; bufferCopyRegion.imageSubresource.baseArrayLayer = face; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = static_cast(texCube[face][level].extent().x); - bufferCopyRegion.imageExtent.height = static_cast(texCube[face][level].extent().y); + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; bufferCopyRegions.push_back(bufferCopyRegion); - - // Increase offset into staging buffer for next level / face - offset += texCube[face][level].size(); } } @@ -965,6 +936,7 @@ namespace vks VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); // Clean up staging resources + ktxTexture_Destroy(ktxTexture); vkFreeMemory(device->logicalDevice, stagingMemory, nullptr); vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr); diff --git a/base/VulkanglTFModel.hpp b/base/VulkanglTFModel.hpp index f3138f32..73ab2497 100644 --- a/base/VulkanglTFModel.hpp +++ b/base/VulkanglTFModel.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION diff --git a/examples/displacement/displacement.cpp b/examples/displacement/displacement.cpp index 7f550f40..c955101d 100644 --- a/examples/displacement/displacement.cpp +++ b/examples/displacement/displacement.cpp @@ -16,7 +16,6 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include #include #include "vulkanexamplebase.h" diff --git a/examples/hdr/hdr.cpp b/examples/hdr/hdr.cpp index d1f10c0d..93dd6d92 100644 --- a/examples/hdr/hdr.cpp +++ b/examples/hdr/hdr.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" diff --git a/examples/imgui/main.cpp b/examples/imgui/main.cpp index 4b6ae4ab..cc86b47f 100644 --- a/examples/imgui/main.cpp +++ b/examples/imgui/main.cpp @@ -18,7 +18,6 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include #include diff --git a/examples/inlineuniformblocks/inlineuniformblocks.cpp b/examples/inlineuniformblocks/inlineuniformblocks.cpp index 193a82e8..a9e2a9eb 100644 --- a/examples/inlineuniformblocks/inlineuniformblocks.cpp +++ b/examples/inlineuniformblocks/inlineuniformblocks.cpp @@ -21,8 +21,6 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" diff --git a/examples/pbrbasic/pbrbasic.cpp b/examples/pbrbasic/pbrbasic.cpp index 8cd0dee4..a2f28184 100644 --- a/examples/pbrbasic/pbrbasic.cpp +++ b/examples/pbrbasic/pbrbasic.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" diff --git a/examples/pbribl/pbribl.cpp b/examples/pbribl/pbribl.cpp index bc16f0f7..cf936adf 100644 --- a/examples/pbribl/pbribl.cpp +++ b/examples/pbribl/pbribl.cpp @@ -22,8 +22,6 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" diff --git a/examples/pbrtexture/main.cpp b/examples/pbrtexture/main.cpp index db0c3f8c..e951c256 100644 --- a/examples/pbrtexture/main.cpp +++ b/examples/pbrtexture/main.cpp @@ -22,8 +22,6 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" diff --git a/examples/terraintessellation/terraintessellation.cpp b/examples/terraintessellation/terraintessellation.cpp index a3856c9e..284431d5 100644 --- a/examples/terraintessellation/terraintessellation.cpp +++ b/examples/terraintessellation/terraintessellation.cpp @@ -17,7 +17,6 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include #include #include "vulkanexamplebase.h" @@ -25,6 +24,8 @@ #include "VulkanTexture.hpp" #include "VulkanModel.hpp" #include "frustum.hpp" +#include +#include #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false @@ -396,25 +397,32 @@ public: HeightMap(std::string filename, uint32_t patchsize, AAssetManager* assetManager) #else HeightMap(std::string filename, uint32_t patchsize) -#endif +#endif { + ktxResult result; + ktxTexture* ktxTexture; #if defined(__ANDROID__) - AAsset* asset = AAssetManager_open(assetManager, filename.c_str(), AASSET_MODE_STREAMING); + AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING); assert(asset); size_t size = AAsset_getLength(asset); assert(size > 0); - void *textureData = malloc(size); + ktx_uint8_t* textureData = new ktx_uint8_t[size]; AAsset_read(asset, textureData, size); AAsset_close(asset); - gli::texture2d heightTex(gli::load((const char*)textureData, size)); - free(textureData); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); + delete[] textureData; + #else - gli::texture2d heightTex(gli::load(filename)); + result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); #endif - dim = static_cast(heightTex.extent().x); + assert(result == KTX_SUCCESS); + ktx_size_t ktxSize = ktxTexture_GetImageSize(ktxTexture, 0); + ktx_uint8_t* ktxImage = ktxTexture_GetData(ktxTexture); + dim = ktxTexture->baseWidth; heightdata = new uint16_t[dim * dim]; - memcpy(heightdata, heightTex.data(), heightTex.size()); + memcpy(heightdata, ktxImage, ktxSize); this->scale = dim / patchsize; + ktxTexture_Destroy(ktxTexture); }; ~HeightMap() diff --git a/examples/texture/texture.cpp b/examples/texture/texture.cpp index 01350edd..2fd5dd41 100644 --- a/examples/texture/texture.cpp +++ b/examples/texture/texture.cpp @@ -15,13 +15,13 @@ #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include -#include -#include #include #include "vulkanexamplebase.h" #include "VulkanDevice.hpp" #include "VulkanBuffer.hpp" +#include +#include #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false @@ -133,28 +133,38 @@ public: // Texture data contains 4 channels (RGBA) with unnormalized 8-bit values, this is the most commonly supported format VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + ktxResult result; + ktxTexture* ktxTexture; + #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); - assert(asset); + 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); + ktx_uint8_t *textureData = new ktx_uint8_t[size]; AAsset_read(asset, textureData, size); AAsset_close(asset); - - gli::texture2d tex2D(gli::load((const char*)textureData, size)); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); + delete[] textureData; #else - gli::texture2d tex2D(gli::load(filename)); -#endif + 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, &ktxTexture); +#endif + assert(result == KTX_SUCCESS); - assert(!tex2D.empty()); - - texture.width = static_cast(tex2D[0].extent().x); - texture.height = static_cast(tex2D[0].extent().y); - texture.mipLevels = static_cast(tex2D.levels()); + // Get properties required for using and upload texture data from the ktx texture object + texture.width = ktxTexture->baseWidth; + texture.height = ktxTexture->baseHeight; + texture.mipLevels = ktxTexture->numLevels; + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); // We prefer using staging to copy the texture data to a device local optimal image VkBool32 useStaging = true; @@ -182,7 +192,7 @@ public: VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = tex2D.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -199,7 +209,7 @@ public: // Copy texture data into host local staging buffer uint8_t *data; VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, tex2D.data(), tex2D.size()); + memcpy(data, ktxTextureData, ktxTextureSize); vkUnmapMemory(device, stagingMemory); // Setup buffer copy regions for each mip level @@ -207,19 +217,20 @@ public: uint32_t offset = 0; for (uint32_t i = 0; i < texture.mipLevels; i++) { + // Calculate offset into staging buffer for the current mip level + ktx_size_t offset; + assert(ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset) == KTX_SUCCESS); + // Setup a buffer image copy structure for the current mip level VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = i; bufferCopyRegion.imageSubresource.baseArrayLayer = 0; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = static_cast(tex2D[i].extent().x); - bufferCopyRegion.imageExtent.height = static_cast(tex2D[i].extent().y); + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> i; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> i; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - - offset += static_cast(tex2D[i].size()); } // Create optimal tiled target image on the device @@ -347,7 +358,7 @@ public: void *data; VK_CHECK_RESULT(vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data)); // Copy image data of the first mip level into memory - memcpy(data, tex2D[0].data(), tex2D[0].size()); + memcpy(data, ktxTextureData, memReqs.size); vkUnmapMemory(device, mappableMemory); // Linear tiled images don't need to be staged and can be directly used as textures @@ -389,6 +400,8 @@ public: VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true); } + ktxTexture_Destroy(ktxTexture); + // Create a texture sampler // In Vulkan textures are accessed by samplers // This separates all the sampling information from the texture data. This means you could have multiple sampler objects for the same texture with different settings diff --git a/examples/texturearray/texturearray.cpp b/examples/texturearray/texturearray.cpp index eaca5801..fd5b4236 100644 --- a/examples/texturearray/texturearray.cpp +++ b/examples/texturearray/texturearray.cpp @@ -22,6 +22,8 @@ #include "vulkanexamplebase.h" #include "VulkanTexture.hpp" #include "VulkanBuffer.hpp" +#include +#include #define ENABLE_VALIDATION false @@ -104,28 +106,38 @@ public: void loadTextureArray(std::string filename, VkFormat format) { + ktxResult result; + ktxTexture* ktxTexture; + #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); - assert(asset); + 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); + ktx_uint8_t *textureData = new ktx_uint8_t[size]; AAsset_read(asset, textureData, size); AAsset_close(asset); - - gli::texture2d_array tex2DArray(gli::load((const char*)textureData, size)); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); + delete[] textureData; #else - gli::texture2d_array tex2DArray(gli::load(filename)); -#endif + 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, &ktxTexture); +#endif + assert(result == KTX_SUCCESS); - assert(!tex2DArray.empty()); - - textureArray.width = tex2DArray.extent().x; - textureArray.height = tex2DArray.extent().y; - layerCount = tex2DArray.layers(); + // Get properties required for using and upload texture data from the ktx texture object + textureArray.width = ktxTexture->baseWidth; + textureArray.height = ktxTexture->baseHeight; + layerCount = ktxTexture->numLayers; + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; @@ -135,7 +147,7 @@ public: VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = tex2DArray.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -155,29 +167,29 @@ public: // Copy texture data into staging buffer uint8_t *data; VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, tex2DArray.data(), tex2DArray.size()); + memcpy(data, ktxTextureData, ktxTextureSize); vkUnmapMemory(device, stagingMemory); // Setup buffer copy regions for array layers std::vector bufferCopyRegions; - size_t offset = 0; + // To keep this simple, we will only load layers and no mip level for (uint32_t layer = 0; layer < layerCount; layer++) { + // Calculate offset into staging buffer for the current array layer + ktx_size_t offset; + assert(ktxTexture_GetImageOffset(ktxTexture, 0, layer, 0, &offset) == KTX_SUCCESS); + // Setup a buffer image copy structure for the current array layer VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = 0; bufferCopyRegion.imageSubresource.baseArrayLayer = layer; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = static_cast(tex2DArray[layer][0].extent().x); - bufferCopyRegion.imageExtent.height = static_cast(tex2DArray[layer][0].extent().y); + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - - // Increase offset into staging buffer for next level / face - offset += tex2DArray[layer][0].size(); } // Create optimal tiled target image @@ -271,6 +283,7 @@ public: // Clean up staging resources vkFreeMemory(device, stagingMemory, nullptr); vkDestroyBuffer(device, stagingBuffer, nullptr); + ktxTexture_Destroy(ktxTexture); } void loadTextures() diff --git a/examples/texturecubemap/texturecubemap.cpp b/examples/texturecubemap/texturecubemap.cpp index cbb2fc20..af95675b 100644 --- a/examples/texturecubemap/texturecubemap.cpp +++ b/examples/texturecubemap/texturecubemap.cpp @@ -17,13 +17,13 @@ #include #include -#include - #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" #include "VulkanTexture.hpp" #include "VulkanModel.hpp" +#include +#include #define ENABLE_VALIDATION false @@ -127,28 +127,38 @@ public: void loadCubemap(std::string filename, VkFormat format, bool forceLinearTiling) { + ktxResult result; + ktxTexture* ktxTexture; + #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); - assert(asset); + 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); + ktx_uint8_t *textureData = new ktx_uint8_t[size]; AAsset_read(asset, textureData, size); AAsset_close(asset); - - gli::texture_cube texCube(gli::load((const char*)textureData, size)); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); + delete[] textureData; #else - gli::texture_cube texCube(gli::load(filename)); -#endif + 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, &ktxTexture); +#endif + assert(result == KTX_SUCCESS); - assert(!texCube.empty()); - - cubeMap.width = texCube.extent().x; - cubeMap.height = texCube.extent().y; - cubeMap.mipLevels = texCube.levels(); + // Get properties required for using and upload texture data from the ktx texture object + cubeMap.width = ktxTexture->baseWidth; + cubeMap.height = ktxTexture->baseHeight; + cubeMap.mipLevels = ktxTexture->numLevels; + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture); VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo(); VkMemoryRequirements memReqs; @@ -158,7 +168,7 @@ public: VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = texCube.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -176,7 +186,7 @@ public: // Copy texture data into staging buffer uint8_t *data; VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, texCube.data(), texCube.size()); + memcpy(data, ktxTextureData, ktxTextureSize); vkUnmapMemory(device, stagingMemory); // Create optimal tiled target image @@ -215,20 +225,19 @@ public: { for (uint32_t level = 0; level < cubeMap.mipLevels; level++) { + // Calculate offset into staging buffer for the current mip level and face + ktx_size_t offset; + assert(ktxTexture_GetImageOffset(ktxTexture, level, 0, face, &offset) == KTX_SUCCESS); VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = level; bufferCopyRegion.imageSubresource.baseArrayLayer = face; bufferCopyRegion.imageSubresource.layerCount = 1; - bufferCopyRegion.imageExtent.width = texCube[face][level].extent().x; - bufferCopyRegion.imageExtent.height = texCube[face][level].extent().y; + bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level; + bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight >> level; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; - bufferCopyRegions.push_back(bufferCopyRegion); - - // Increase offset into staging buffer for next level / face - offset += texCube[face][level].size(); } } @@ -306,6 +315,7 @@ public: // Clean up staging resources vkFreeMemory(device, stagingMemory, nullptr); vkDestroyBuffer(device, stagingBuffer, nullptr); + ktxTexture_Destroy(ktxTexture); } void loadTextures() diff --git a/examples/texturemipmapgen/texturemipmapgen.cpp b/examples/texturemipmapgen/texturemipmapgen.cpp index 50fd04f6..04c98e33 100644 --- a/examples/texturemipmapgen/texturemipmapgen.cpp +++ b/examples/texturemipmapgen/texturemipmapgen.cpp @@ -6,8 +6,6 @@ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ -// todo: Fallback for sampler selection on devices that don't support shaderSampledImageArrayDynamicIndexing - #include #include #include @@ -19,13 +17,14 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include #include #include "vulkanexamplebase.h" #include "VulkanDevice.hpp" #include "VulkanBuffer.hpp" #include "VulkanModel.hpp" +#include +#include #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false @@ -116,31 +115,38 @@ public: } } - void loadTexture(std::string fileName, VkFormat format, bool forceLinearTiling) + void loadTexture(std::string filename, VkFormat format, bool forceLinearTiling) { + ktxResult result; + ktxTexture* ktxTexture; + #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); - assert(asset); + 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); + ktx_uint8_t *textureData = new ktx_uint8_t[size]; AAsset_read(asset, textureData, size); AAsset_close(asset); - - gli::texture2d tex2D(gli::load((const char*)textureData, size)); + result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture); + delete[] textureData; #else - gli::texture2d tex2D(gli::load(fileName)); -#endif + 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, &ktxTexture); +#endif + assert(result == KTX_SUCCESS); - assert(!tex2D.empty()); - - VkFormatProperties formatProperties; - - texture.width = static_cast(tex2D[0].extent().x); - texture.height = static_cast(tex2D[0].extent().y); + texture.width = ktxTexture->baseWidth; + texture.height = ktxTexture->baseHeight; + ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture); + ktx_size_t ktxTextureSize = ktxTexture_GetImageSize(ktxTexture, 0); // calculate num of mip maps // numLevels = 1 + floor(log2(max(w, h, d))) @@ -148,8 +154,8 @@ public: texture.mipLevels = floor(log2(std::max(texture.width, texture.height))) + 1; // Get device properites for the requested texture format + VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); - // Mip-chain generation requires support for blit source and destination assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT); assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT); @@ -162,7 +168,7 @@ public: VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(); - bufferCreateInfo.size = tex2D.size(); + bufferCreateInfo.size = ktxTextureSize; // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -176,7 +182,7 @@ public: // Copy texture data into staging buffer uint8_t *data; VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data)); - memcpy(data, tex2D.data(), tex2D.size()); + memcpy(data, ktxTextureData, ktxTextureSize); vkUnmapMemory(device, stagingMemory); // Create optimal tiled target image @@ -246,6 +252,7 @@ public: // Clean up staging resources vkFreeMemory(device, stagingMemory, nullptr); vkDestroyBuffer(device, stagingBuffer, nullptr); + ktxTexture_Destroy(ktxTexture); // Generate the mip chain // --------------------------------------------------------------- diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt new file mode 100644 index 00000000..ddb84b70 --- /dev/null +++ b/external/CMakeLists.txt @@ -0,0 +1,26 @@ +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 +) +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") diff --git a/external/gli b/external/gli deleted file mode 160000 index 7da5f509..00000000 --- a/external/gli +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7da5f50931225e9819a26d5cb323c5f42da50bcd diff --git a/external/ktx b/external/ktx new file mode 160000 index 00000000..726d14d0 --- /dev/null +++ b/external/ktx @@ -0,0 +1 @@ +Subproject commit 726d14d02c95bb21ec9e43807751b491d295dd3c