Merge pull request #637 from SaschaWillems/libktx
Replace gli with libktx
This commit is contained in:
commit
bb3b336e53
22 changed files with 306 additions and 243 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
[submodule "external/glm"]
|
[submodule "external/glm"]
|
||||||
path = external/glm
|
path = external/glm
|
||||||
url = https://github.com/g-truc/glm
|
url = https://github.com/g-truc/glm
|
||||||
[submodule "external/gli"]
|
[submodule "external/ktx"]
|
||||||
path = external/gli
|
path = external/ktx
|
||||||
url = https://github.com/g-truc/gli
|
url = https://github.com/KhronosGroup/KTX-Software
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ endif()
|
||||||
|
|
||||||
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
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 )
|
file(GLOB SOURCE *.cpp )
|
||||||
|
|
||||||
|
|
@ -127,3 +127,4 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
|
||||||
|
|
||||||
add_subdirectory(base)
|
add_subdirectory(base)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
|
add_subdirectory(external)
|
||||||
|
|
@ -12,10 +12,31 @@ include_directories(../../../external/imgui)
|
||||||
include_directories(../../../external/assimp)
|
include_directories(../../../external/assimp)
|
||||||
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
||||||
|
|
||||||
|
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(
|
target_link_libraries(
|
||||||
libbase
|
libbase
|
||||||
android
|
android
|
||||||
log
|
log
|
||||||
z
|
z
|
||||||
libassimp
|
libassimp
|
||||||
|
libktx
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* Heightmap terrain generator
|
* 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)
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
#include "VulkanDevice.hpp"
|
#include "VulkanDevice.hpp"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
namespace vks
|
namespace vks
|
||||||
{
|
{
|
||||||
|
|
@ -75,27 +76,31 @@ namespace vks
|
||||||
assert(device);
|
assert(device);
|
||||||
assert(copyQueue != VK_NULL_HANDLE);
|
assert(copyQueue != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
ktxResult result;
|
||||||
|
ktxTexture* ktxTexture;
|
||||||
#if defined(__ANDROID__)
|
#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);
|
assert(asset);
|
||||||
size_t size = AAsset_getLength(asset);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
void *textureData = malloc(size);
|
void *textureData = malloc(size);
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
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);
|
free(textureData);
|
||||||
#else
|
#else
|
||||||
gli::texture2d heightTex(gli::load(filename));
|
result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
#endif
|
#endif
|
||||||
dim = static_cast<uint32_t>(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];
|
heightdata = new uint16_t[dim * dim];
|
||||||
memcpy(heightdata, heightTex.data(), heightTex.size());
|
memcpy(heightdata, ktxImage, ktxSize);
|
||||||
this->scale = dim / patchsize;
|
this->scale = dim / patchsize;
|
||||||
this->heightScale = scale.y;
|
ktxTexture_Destroy(ktxTexture);
|
||||||
|
|
||||||
// Generate vertices
|
// Generate vertices
|
||||||
|
|
||||||
Vertex * vertices = new Vertex[patchsize * patchsize * 4];
|
Vertex * vertices = new Vertex[patchsize * patchsize * 4];
|
||||||
|
|
||||||
const float wx = 2.0f;
|
const float wx = 2.0f;
|
||||||
|
|
|
||||||
|
|
@ -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,30 @@ 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__)
|
||||||
|
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 */
|
/** @brief 2D texture */
|
||||||
|
|
@ -70,7 +91,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 +109,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 +145,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 +165,29 @@ 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;
|
||||||
|
KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset);
|
||||||
|
assert(result == 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 +316,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, memReqs.size);
|
||||||
|
|
||||||
vkUnmapMemory(device->logicalDevice, mappableMemory);
|
vkUnmapMemory(device->logicalDevice, mappableMemory);
|
||||||
|
|
||||||
|
|
@ -328,6 +332,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 +558,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 +574,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 +595,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 +615,31 @@ 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;
|
||||||
|
KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, level, layer, 0, &offset);
|
||||||
|
assert(result == 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 +738,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 +753,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 +769,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 +789,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 +809,31 @@ 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;
|
||||||
|
KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, level, 0, face, &offset);
|
||||||
|
assert(result == 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 +936,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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#define TINYGLTF_IMPLEMENTATION
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
|
|
@ -25,6 +24,8 @@
|
||||||
#include "VulkanTexture.hpp"
|
#include "VulkanTexture.hpp"
|
||||||
#include "VulkanModel.hpp"
|
#include "VulkanModel.hpp"
|
||||||
#include "frustum.hpp"
|
#include "frustum.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
#define VERTEX_BUFFER_BIND_ID 0
|
#define VERTEX_BUFFER_BIND_ID 0
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
|
|
@ -398,23 +399,30 @@ public:
|
||||||
HeightMap(std::string filename, uint32_t patchsize)
|
HeightMap(std::string filename, uint32_t patchsize)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
ktxResult result;
|
||||||
|
ktxTexture* ktxTexture;
|
||||||
#if defined(__ANDROID__)
|
#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);
|
assert(asset);
|
||||||
size_t size = AAsset_getLength(asset);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
void *textureData = malloc(size);
|
ktx_uint8_t* textureData = new ktx_uint8_t[size];
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
AAsset_close(asset);
|
||||||
gli::texture2d heightTex(gli::load((const char*)textureData, size));
|
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
free(textureData);
|
delete[] textureData;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
gli::texture2d heightTex(gli::load(filename));
|
result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
#endif
|
#endif
|
||||||
dim = static_cast<uint32_t>(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];
|
heightdata = new uint16_t[dim * dim];
|
||||||
memcpy(heightdata, heightTex.data(), heightTex.size());
|
memcpy(heightdata, ktxImage, ktxSize);
|
||||||
this->scale = dim / patchsize;
|
this->scale = dim / patchsize;
|
||||||
|
ktxTexture_Destroy(ktxTexture);
|
||||||
};
|
};
|
||||||
|
|
||||||
~HeightMap()
|
~HeightMap()
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanDevice.hpp"
|
#include "VulkanDevice.hpp"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
#define VERTEX_BUFFER_BIND_ID 0
|
#define VERTEX_BUFFER_BIND_ID 0
|
||||||
#define ENABLE_VALIDATION false
|
#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
|
// Texture data contains 4 channels (RGBA) with unnormalized 8-bit values, this is the most commonly supported format
|
||||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
|
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
|
||||||
|
ktxResult result;
|
||||||
|
ktxTexture* ktxTexture;
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
// Textures are stored inside the apk on Android (compressed)
|
// Textures are stored inside the apk on Android (compressed)
|
||||||
// So they need to be loaded via the asset manager
|
// So they need to be loaded via the asset manager
|
||||||
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
|
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);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
void *textureData = malloc(size);
|
ktx_uint8_t *textureData = new ktx_uint8_t[size];
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
AAsset_close(asset);
|
||||||
|
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
gli::texture2d tex2D(gli::load((const char*)textureData, size));
|
delete[] textureData;
|
||||||
#else
|
#else
|
||||||
gli::texture2d tex2D(gli::load(filename));
|
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
|
#endif
|
||||||
|
assert(result == KTX_SUCCESS);
|
||||||
|
|
||||||
assert(!tex2D.empty());
|
// Get properties required for using and upload texture data from the ktx texture object
|
||||||
|
texture.width = ktxTexture->baseWidth;
|
||||||
texture.width = static_cast<uint32_t>(tex2D[0].extent().x);
|
texture.height = ktxTexture->baseHeight;
|
||||||
texture.height = static_cast<uint32_t>(tex2D[0].extent().y);
|
texture.mipLevels = ktxTexture->numLevels;
|
||||||
texture.mipLevels = static_cast<uint32_t>(tex2D.levels());
|
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
|
// We prefer using staging to copy the texture data to a device local optimal image
|
||||||
VkBool32 useStaging = true;
|
VkBool32 useStaging = true;
|
||||||
|
|
@ -182,7 +192,7 @@ public:
|
||||||
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;
|
||||||
|
|
@ -199,7 +209,7 @@ public:
|
||||||
// Copy texture data into host local staging buffer
|
// Copy texture data into host local staging buffer
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&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);
|
vkUnmapMemory(device, stagingMemory);
|
||||||
|
|
||||||
// Setup buffer copy regions for each mip level
|
// Setup buffer copy regions for each mip level
|
||||||
|
|
@ -207,19 +217,20 @@ public:
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < texture.mipLevels; i++) {
|
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 = {};
|
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 on the device
|
// Create optimal tiled target image on the device
|
||||||
|
|
@ -347,7 +358,7 @@ public:
|
||||||
void *data;
|
void *data;
|
||||||
VK_CHECK_RESULT(vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data));
|
VK_CHECK_RESULT(vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data));
|
||||||
// Copy image data of the first mip level into memory
|
// 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);
|
vkUnmapMemory(device, mappableMemory);
|
||||||
|
|
||||||
// Linear tiled images don't need to be staged and can be directly used as textures
|
// 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);
|
VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ktxTexture_Destroy(ktxTexture);
|
||||||
|
|
||||||
// Create a texture sampler
|
// Create a texture sampler
|
||||||
// In Vulkan textures are accessed by samplers
|
// 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
|
// 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
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanTexture.hpp"
|
#include "VulkanTexture.hpp"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
|
|
||||||
|
|
@ -104,28 +106,38 @@ public:
|
||||||
|
|
||||||
void loadTextureArray(std::string filename, VkFormat format)
|
void loadTextureArray(std::string filename, VkFormat format)
|
||||||
{
|
{
|
||||||
|
ktxResult result;
|
||||||
|
ktxTexture* ktxTexture;
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
// Textures are stored inside the apk on Android (compressed)
|
// Textures are stored inside the apk on Android (compressed)
|
||||||
// So they need to be loaded via the asset manager
|
// So they need to be loaded via the asset manager
|
||||||
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
|
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);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
void *textureData = malloc(size);
|
ktx_uint8_t *textureData = new ktx_uint8_t[size];
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
AAsset_close(asset);
|
||||||
|
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
gli::texture2d_array tex2DArray(gli::load((const char*)textureData, size));
|
delete[] textureData;
|
||||||
#else
|
#else
|
||||||
gli::texture2d_array tex2DArray(gli::load(filename));
|
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
|
#endif
|
||||||
|
assert(result == KTX_SUCCESS);
|
||||||
|
|
||||||
assert(!tex2DArray.empty());
|
// Get properties required for using and upload texture data from the ktx texture object
|
||||||
|
textureArray.width = ktxTexture->baseWidth;
|
||||||
textureArray.width = tex2DArray.extent().x;
|
textureArray.height = ktxTexture->baseHeight;
|
||||||
textureArray.height = tex2DArray.extent().y;
|
layerCount = ktxTexture->numLayers;
|
||||||
layerCount = tex2DArray.layers();
|
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;
|
||||||
|
|
@ -135,7 +147,7 @@ public:
|
||||||
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;
|
||||||
|
|
@ -155,29 +167,29 @@ public:
|
||||||
// Copy texture data into staging buffer
|
// Copy texture data into staging buffer
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&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);
|
vkUnmapMemory(device, stagingMemory);
|
||||||
|
|
||||||
// Setup buffer copy regions for array layers
|
// Setup buffer copy regions for array layers
|
||||||
std::vector<VkBufferImageCopy> bufferCopyRegions;
|
std::vector<VkBufferImageCopy> 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++)
|
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 = {};
|
VkBufferImageCopy bufferCopyRegion = {};
|
||||||
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
bufferCopyRegion.imageSubresource.mipLevel = 0;
|
bufferCopyRegion.imageSubresource.mipLevel = 0;
|
||||||
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][0].extent().x);
|
bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth;
|
||||||
bufferCopyRegion.imageExtent.height = static_cast<uint32_t>(tex2DArray[layer][0].extent().y);
|
bufferCopyRegion.imageExtent.height = ktxTexture->baseHeight;
|
||||||
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][0].size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create optimal tiled target image
|
// Create optimal tiled target image
|
||||||
|
|
@ -271,6 +283,7 @@ public:
|
||||||
// Clean up staging resources
|
// Clean up staging resources
|
||||||
vkFreeMemory(device, stagingMemory, nullptr);
|
vkFreeMemory(device, stagingMemory, nullptr);
|
||||||
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
||||||
|
ktxTexture_Destroy(ktxTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadTextures()
|
void loadTextures()
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,13 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
#include "VulkanTexture.hpp"
|
#include "VulkanTexture.hpp"
|
||||||
#include "VulkanModel.hpp"
|
#include "VulkanModel.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
|
|
||||||
|
|
@ -127,28 +127,38 @@ public:
|
||||||
|
|
||||||
void loadCubemap(std::string filename, VkFormat format, bool forceLinearTiling)
|
void loadCubemap(std::string filename, VkFormat format, bool forceLinearTiling)
|
||||||
{
|
{
|
||||||
|
ktxResult result;
|
||||||
|
ktxTexture* ktxTexture;
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
// Textures are stored inside the apk on Android (compressed)
|
// Textures are stored inside the apk on Android (compressed)
|
||||||
// So they need to be loaded via the asset manager
|
// So they need to be loaded via the asset manager
|
||||||
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
|
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);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
void *textureData = malloc(size);
|
ktx_uint8_t *textureData = new ktx_uint8_t[size];
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
AAsset_close(asset);
|
||||||
|
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
gli::texture_cube texCube(gli::load((const char*)textureData, size));
|
delete[] textureData;
|
||||||
#else
|
#else
|
||||||
gli::texture_cube texCube(gli::load(filename));
|
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
|
#endif
|
||||||
|
assert(result == KTX_SUCCESS);
|
||||||
|
|
||||||
assert(!texCube.empty());
|
// Get properties required for using and upload texture data from the ktx texture object
|
||||||
|
cubeMap.width = ktxTexture->baseWidth;
|
||||||
cubeMap.width = texCube.extent().x;
|
cubeMap.height = ktxTexture->baseHeight;
|
||||||
cubeMap.height = texCube.extent().y;
|
cubeMap.mipLevels = ktxTexture->numLevels;
|
||||||
cubeMap.mipLevels = texCube.levels();
|
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;
|
||||||
|
|
@ -158,7 +168,7 @@ public:
|
||||||
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;
|
||||||
|
|
@ -176,7 +186,7 @@ public:
|
||||||
// Copy texture data into staging buffer
|
// Copy texture data into staging buffer
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&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);
|
vkUnmapMemory(device, stagingMemory);
|
||||||
|
|
||||||
// Create optimal tiled target image
|
// Create optimal tiled target image
|
||||||
|
|
@ -215,20 +225,19 @@ public:
|
||||||
{
|
{
|
||||||
for (uint32_t level = 0; level < cubeMap.mipLevels; level++)
|
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 = {};
|
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 = texCube[face][level].extent().x;
|
bufferCopyRegion.imageExtent.width = ktxTexture->baseWidth >> level;
|
||||||
bufferCopyRegion.imageExtent.height = 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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,6 +315,7 @@ public:
|
||||||
// Clean up staging resources
|
// Clean up staging resources
|
||||||
vkFreeMemory(device, stagingMemory, nullptr);
|
vkFreeMemory(device, stagingMemory, nullptr);
|
||||||
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
||||||
|
ktxTexture_Destroy(ktxTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadTextures()
|
void loadTextures()
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// todo: Fallback for sampler selection on devices that don't support shaderSampledImageArrayDynamicIndexing
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -19,13 +17,14 @@
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gli/gli.hpp>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanDevice.hpp"
|
#include "VulkanDevice.hpp"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
#include "VulkanModel.hpp"
|
#include "VulkanModel.hpp"
|
||||||
|
#include <ktx.h>
|
||||||
|
#include <ktxvulkan.h>
|
||||||
|
|
||||||
#define VERTEX_BUFFER_BIND_ID 0
|
#define VERTEX_BUFFER_BIND_ID 0
|
||||||
#define ENABLE_VALIDATION false
|
#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__)
|
#if defined(__ANDROID__)
|
||||||
// Textures are stored inside the apk on Android (compressed)
|
// Textures are stored inside the apk on Android (compressed)
|
||||||
// So they need to be loaded via the asset manager
|
// So they need to be loaded via the asset manager
|
||||||
AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, fileName.c_str(), AASSET_MODE_STREAMING);
|
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);
|
size_t size = AAsset_getLength(asset);
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
void *textureData = malloc(size);
|
ktx_uint8_t *textureData = new ktx_uint8_t[size];
|
||||||
AAsset_read(asset, textureData, size);
|
AAsset_read(asset, textureData, size);
|
||||||
AAsset_close(asset);
|
AAsset_close(asset);
|
||||||
|
result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
|
||||||
gli::texture2d tex2D(gli::load((const char*)textureData, size));
|
delete[] textureData;
|
||||||
#else
|
#else
|
||||||
gli::texture2d tex2D(gli::load(fileName));
|
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
|
#endif
|
||||||
|
assert(result == KTX_SUCCESS);
|
||||||
|
|
||||||
assert(!tex2D.empty());
|
texture.width = ktxTexture->baseWidth;
|
||||||
|
texture.height = ktxTexture->baseHeight;
|
||||||
VkFormatProperties formatProperties;
|
ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture);
|
||||||
|
ktx_size_t ktxTextureSize = ktxTexture_GetImageSize(ktxTexture, 0);
|
||||||
texture.width = static_cast<uint32_t>(tex2D[0].extent().x);
|
|
||||||
texture.height = static_cast<uint32_t>(tex2D[0].extent().y);
|
|
||||||
|
|
||||||
// calculate num of mip maps
|
// calculate num of mip maps
|
||||||
// numLevels = 1 + floor(log2(max(w, h, d)))
|
// numLevels = 1 + floor(log2(max(w, h, d)))
|
||||||
|
|
@ -148,8 +154,8 @@ public:
|
||||||
texture.mipLevels = floor(log2(std::max(texture.width, texture.height))) + 1;
|
texture.mipLevels = floor(log2(std::max(texture.width, texture.height))) + 1;
|
||||||
|
|
||||||
// Get device properites for the requested texture format
|
// Get device properites for the requested texture format
|
||||||
|
VkFormatProperties formatProperties;
|
||||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
|
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
|
||||||
|
|
||||||
// Mip-chain generation requires support for blit source and destination
|
// 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_SRC_BIT);
|
||||||
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT);
|
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT);
|
||||||
|
|
@ -162,7 +168,7 @@ public:
|
||||||
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;
|
||||||
|
|
@ -176,7 +182,7 @@ public:
|
||||||
// Copy texture data into staging buffer
|
// Copy texture data into staging buffer
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&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);
|
vkUnmapMemory(device, stagingMemory);
|
||||||
|
|
||||||
// Create optimal tiled target image
|
// Create optimal tiled target image
|
||||||
|
|
@ -246,6 +252,7 @@ public:
|
||||||
// Clean up staging resources
|
// Clean up staging resources
|
||||||
vkFreeMemory(device, stagingMemory, nullptr);
|
vkFreeMemory(device, stagingMemory, nullptr);
|
||||||
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
vkDestroyBuffer(device, stagingBuffer, nullptr);
|
||||||
|
ktxTexture_Destroy(ktxTexture);
|
||||||
|
|
||||||
// Generate the mip chain
|
// Generate the mip chain
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
|
||||||
26
external/CMakeLists.txt
vendored
Normal file
26
external/CMakeLists.txt
vendored
Normal file
|
|
@ -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")
|
||||||
1
external/gli
vendored
1
external/gli
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7da5f50931225e9819a26d5cb323c5f42da50bcd
|
|
||||||
1
external/ktx
vendored
Submodule
1
external/ktx
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 726d14d02c95bb21ec9e43807751b491d295dd3c
|
||||||
Loading…
Add table
Add a link
Reference in a new issue