82 if (gltfimage.uri.find_last_of(
".") != std::string::npos) {
83 if (gltfimage.uri.substr(gltfimage.uri.find_last_of(
".") + 1) ==
"ktx") {
93 unsigned char* buffer =
nullptr;
94 VkDeviceSize bufferSize = 0;
95 bool deleteBuffer =
false;
96 if (gltfimage.component == 3) {
99 bufferSize = gltfimage.width * gltfimage.height * 4;
100 buffer =
new unsigned char[bufferSize];
101 unsigned char* rgba = buffer;
102 unsigned char* rgb = &gltfimage.image[0];
103 for (
size_t i = 0; i < gltfimage.width * gltfimage.height; ++i) {
104 for (int32_t j = 0; j < 3; ++j) {
113 buffer = &gltfimage.image[0];
114 bufferSize = gltfimage.image.size();
117 format = VK_FORMAT_R8G8B8A8_UNORM;
119 VkFormatProperties formatProperties;
121 width = gltfimage.width;
122 height = gltfimage.height;
125 vkGetPhysicalDeviceFormatProperties(
ctx->physicalDeviceHandle(), format, &formatProperties);
126 assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT);
127 assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT);
129 VkMemoryAllocateInfo memAllocInfo{};
130 memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
131 VkMemoryRequirements memReqs{};
133 VkBuffer stagingBuffer;
134 VkDeviceMemory stagingMemory;
136 VkBufferCreateInfo bufferCreateInfo{};
137 bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
138 bufferCreateInfo.size = bufferSize;
139 bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
140 bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
141 VK_CHECK_RESULT(vkCreateBuffer(
ctx->deviceHandle(), &bufferCreateInfo,
nullptr, &stagingBuffer));
142 vkGetBufferMemoryRequirements(
ctx->deviceHandle(), stagingBuffer, &memReqs);
143 memAllocInfo.allocationSize = memReqs.size;
144 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
145 VK_CHECK_RESULT(vkAllocateMemory(
ctx->deviceHandle(), &memAllocInfo,
nullptr, &stagingMemory));
146 VK_CHECK_RESULT(vkBindBufferMemory(
ctx->deviceHandle(), stagingBuffer, stagingMemory, 0));
149 VK_CHECK_RESULT(vkMapMemory(
ctx->deviceHandle(), stagingMemory, 0, memReqs.size, 0, (
void**)&data));
150 memcpy(data, buffer, bufferSize);
151 vkUnmapMemory(
ctx->deviceHandle(), stagingMemory);
153 VkImageCreateInfo imageCreateInfo{};
154 imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
155 imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
156 imageCreateInfo.format = format;
158 imageCreateInfo.arrayLayers = 1;
159 imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
160 imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
161 imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
162 imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
163 imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
165 imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
167 vkGetImageMemoryRequirements(
ctx->deviceHandle(),
image, &memReqs);
168 memAllocInfo.allocationSize = memReqs.size;
169 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
173 VkCommandBuffer copyCmd =
ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY,
true);
175 VkImageSubresourceRange subresourceRange = {};
176 subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
177 subresourceRange.levelCount = 1;
178 subresourceRange.layerCount = 1;
181 VkImageMemoryBarrier imageMemoryBarrier{};
182 imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
183 imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
184 imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
185 imageMemoryBarrier.srcAccessMask = 0;
186 imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
187 imageMemoryBarrier.image =
image;
188 imageMemoryBarrier.subresourceRange = subresourceRange;
189 vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
192 VkBufferImageCopy bufferCopyRegion = {};
193 bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
194 bufferCopyRegion.imageSubresource.mipLevel = 0;
195 bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
196 bufferCopyRegion.imageSubresource.layerCount = 1;
197 bufferCopyRegion.imageExtent.width =
width;
198 bufferCopyRegion.imageExtent.height =
height;
199 bufferCopyRegion.imageExtent.depth = 1;
201 vkCmdCopyBufferToImage(copyCmd, stagingBuffer,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
204 VkImageMemoryBarrier imageMemoryBarrier{};
205 imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
206 imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
207 imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
208 imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
209 imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
210 imageMemoryBarrier.image =
image;
211 imageMemoryBarrier.subresourceRange = subresourceRange;
212 vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
215 ctx->flushCommandBuffer(copyCmd,
ctx->graphicsQueueHandle(),
true);
217 vkFreeMemory(
ctx->deviceHandle(), stagingMemory,
nullptr);
218 vkDestroyBuffer(
ctx->deviceHandle(), stagingBuffer,
nullptr);
221 VkCommandBuffer blitCmd =
ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY,
true);
222 for (uint32_t i = 1; i <
mipLevels; i++) {
223 VkImageBlit imageBlit{};
225 imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
226 imageBlit.srcSubresource.layerCount = 1;
227 imageBlit.srcSubresource.mipLevel = i - 1;
228 imageBlit.srcOffsets[1].x = int32_t(
width >> (i - 1));
229 imageBlit.srcOffsets[1].y = int32_t(
height >> (i - 1));
230 imageBlit.srcOffsets[1].z = 1;
232 imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
233 imageBlit.dstSubresource.layerCount = 1;
234 imageBlit.dstSubresource.mipLevel = i;
235 imageBlit.dstOffsets[1].x = int32_t(
width >> i);
236 imageBlit.dstOffsets[1].y = int32_t(
height >> i);
237 imageBlit.dstOffsets[1].z = 1;
239 VkImageSubresourceRange mipSubRange = {};
240 mipSubRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
241 mipSubRange.baseMipLevel = i;
242 mipSubRange.levelCount = 1;
243 mipSubRange.layerCount = 1;
246 VkImageMemoryBarrier imageMemoryBarrier{};
247 imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
248 imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
249 imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
250 imageMemoryBarrier.srcAccessMask = 0;
251 imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
252 imageMemoryBarrier.image =
image;
253 imageMemoryBarrier.subresourceRange = mipSubRange;
254 vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
257 vkCmdBlitImage(blitCmd,
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR);
260 VkImageMemoryBarrier imageMemoryBarrier{};
261 imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
262 imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
263 imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
264 imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
265 imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
266 imageMemoryBarrier.image =
image;
267 imageMemoryBarrier.subresourceRange = mipSubRange;
268 vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
273 imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
276 VkImageMemoryBarrier imageMemoryBarrier{};
277 imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
278 imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
279 imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
280 imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
281 imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
282 imageMemoryBarrier.image =
image;
283 imageMemoryBarrier.subresourceRange = subresourceRange;
284 vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &imageMemoryBarrier);
287 ctx->flushCommandBuffer(blitCmd,
ctx->graphicsQueueHandle(),
true);
291 std::string filename = path +
"/" + gltfimage.uri;
293 ktxTexture* ktxTexture;
295 ktxResult result = KTX_SUCCESS;
296#if defined(__ANDROID__)
297 AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
299 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);
301 size_t size = AAsset_getLength(asset);
303 ktx_uint8_t* textureData =
new ktx_uint8_t[size];
304 AAsset_read(asset, textureData, size);
306 result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
307 delete[] textureData;
310 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);
312 result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
314 assert(result == KTX_SUCCESS);
316 width = ktxTexture->baseWidth;
317 height = ktxTexture->baseHeight;
320 ktx_uint8_t* ktxTextureData = ktxTexture_GetData(ktxTexture);
321 ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
323 format = VK_FORMAT_R8G8B8A8_UNORM;
326 VkFormatProperties formatProperties;
327 vkGetPhysicalDeviceFormatProperties(
ctx->physicalDeviceHandle(), format, &formatProperties);
329 VkCommandBuffer copyCmd =
ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY,
true);
330 VkBuffer stagingBuffer;
331 VkDeviceMemory stagingMemory;
334 bufferCreateInfo.size = ktxTextureSize;
336 bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
337 bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
338 VK_CHECK_RESULT(vkCreateBuffer(
ctx->deviceHandle(), &bufferCreateInfo,
nullptr, &stagingBuffer));
341 VkMemoryRequirements memReqs;
342 vkGetBufferMemoryRequirements(
ctx->deviceHandle(), stagingBuffer, &memReqs);
343 memAllocInfo.allocationSize = memReqs.size;
344 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
345 VK_CHECK_RESULT(vkAllocateMemory(
ctx->deviceHandle(), &memAllocInfo,
nullptr, &stagingMemory));
346 VK_CHECK_RESULT(vkBindBufferMemory(
ctx->deviceHandle(), stagingBuffer, stagingMemory, 0));
349 VK_CHECK_RESULT(vkMapMemory(
ctx->deviceHandle(), stagingMemory, 0, memReqs.size, 0, (
void**)&data));
350 memcpy(data, ktxTextureData, ktxTextureSize);
351 vkUnmapMemory(
ctx->deviceHandle(), stagingMemory);
353 std::vector<VkBufferImageCopy> bufferCopyRegions;
357 KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset);
358 assert(result == KTX_SUCCESS);
359 VkBufferImageCopy bufferCopyRegion = {};
360 bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
361 bufferCopyRegion.imageSubresource.mipLevel = i;
362 bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
363 bufferCopyRegion.imageSubresource.layerCount = 1;
364 bufferCopyRegion.imageExtent.width = std::max(1u, ktxTexture->baseWidth >> i);
365 bufferCopyRegion.imageExtent.height = std::max(1u, ktxTexture->baseHeight >> i);
366 bufferCopyRegion.imageExtent.depth = 1;
367 bufferCopyRegion.bufferOffset = offset;
368 bufferCopyRegions.push_back(bufferCopyRegion);
373 imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
374 imageCreateInfo.format = format;
376 imageCreateInfo.arrayLayers = 1;
377 imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
378 imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
379 imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
380 imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
382 imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
385 vkGetImageMemoryRequirements(
ctx->deviceHandle(),
image, &memReqs);
386 memAllocInfo.allocationSize = memReqs.size;
387 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
391 VkImageSubresourceRange subresourceRange = {};
392 subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
393 subresourceRange.baseMipLevel = 0;
395 subresourceRange.layerCount = 1;
398 vkCmdCopyBufferToImage(copyCmd, stagingBuffer,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
static_cast<uint32_t
>(bufferCopyRegions.size()), bufferCopyRegions.data());
400 ctx->flushCommandBuffer(copyCmd,
ctx->graphicsQueueHandle());
401 this->
imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
403 vkFreeMemory(
ctx->deviceHandle(), stagingMemory,
nullptr);
404 vkDestroyBuffer(
ctx->deviceHandle(), stagingBuffer,
nullptr);
406 ktxTexture_Destroy(ktxTexture);
409 VkSamplerCreateInfo samplerInfo{};
410 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
411 samplerInfo.magFilter = VK_FILTER_LINEAR;
412 samplerInfo.minFilter = VK_FILTER_LINEAR;
413 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
414 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
415 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
416 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
417 samplerInfo.compareOp = VK_COMPARE_OP_NEVER;
418 samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
419 samplerInfo.maxAnisotropy = 1.0;
420 samplerInfo.anisotropyEnable = VK_FALSE;
422 samplerInfo.maxAnisotropy = 8.0f;
423 samplerInfo.anisotropyEnable = VK_TRUE;
426 VkImageViewCreateInfo viewInfo{};
427 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
428 viewInfo.image =
image;
429 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
430 viewInfo.format = format;
431 viewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
432 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
433 viewInfo.subresourceRange.layerCount = 1;
434 viewInfo.subresourceRange.levelCount =
mipLevels;
642 unsigned char* buffer =
new unsigned char[bufferSize];
643 memset(buffer, 0, bufferSize);
645 VkBuffer stagingBuffer;
646 VkDeviceMemory stagingMemory;
648 bufferCreateInfo.size = bufferSize;
650 bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
651 bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
652 VK_CHECK_RESULT(vkCreateBuffer(
ctx->deviceHandle(), &bufferCreateInfo,
nullptr, &stagingBuffer));
655 VkMemoryRequirements memReqs;
656 vkGetBufferMemoryRequirements(
ctx->deviceHandle(), stagingBuffer, &memReqs);
657 memAllocInfo.allocationSize = memReqs.size;
658 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
659 VK_CHECK_RESULT(vkAllocateMemory(
ctx->deviceHandle(), &memAllocInfo,
nullptr, &stagingMemory));
660 VK_CHECK_RESULT(vkBindBufferMemory(
ctx->deviceHandle(), stagingBuffer, stagingMemory, 0));
664 VK_CHECK_RESULT(vkMapMemory(
ctx->deviceHandle(), stagingMemory, 0, memReqs.size, 0, (
void**)&data));
665 memcpy(data, buffer, bufferSize);
666 vkUnmapMemory(
ctx->deviceHandle(), stagingMemory);
668 VkBufferImageCopy bufferCopyRegion = {};
669 bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
670 bufferCopyRegion.imageSubresource.layerCount = 1;
671 bufferCopyRegion.imageExtent.width =
emptyTexture.width;
672 bufferCopyRegion.imageExtent.height =
emptyTexture.height;
673 bufferCopyRegion.imageExtent.depth = 1;
677 imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
678 imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
679 imageCreateInfo.mipLevels = 1;
680 imageCreateInfo.arrayLayers = 1;
681 imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
682 imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
683 imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
684 imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
686 imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
689 vkGetImageMemoryRequirements(
ctx->deviceHandle(),
emptyTexture.image, &memReqs);
690 memAllocInfo.allocationSize = memReqs.size;
691 memAllocInfo.memoryTypeIndex =
ctx->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
695 VkImageSubresourceRange subresourceRange{};
696 subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
697 subresourceRange.baseMipLevel = 0;
698 subresourceRange.levelCount = 1;
699 subresourceRange.layerCount = 1;
701 VkCommandBuffer copyCmd =
ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY,
true);
703 vkCmdCopyBufferToImage(copyCmd, stagingBuffer,
emptyTexture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
705 ctx->flushCommandBuffer(copyCmd,
ctx->graphicsQueueHandle());
706 emptyTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
709 vkFreeMemory(
ctx->deviceHandle(), stagingMemory,
nullptr);
710 vkDestroyBuffer(
ctx->deviceHandle(), stagingBuffer,
nullptr);
713 samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
714 samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
715 samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
716 samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
717 samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
718 samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
719 samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
720 samplerCreateInfo.maxAnisotropy = 1.0f;
724 viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
725 viewCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
726 viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
727 viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
728 viewCreateInfo.subresourceRange.levelCount = 1;
732 emptyTexture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
774void vkglTF::Model::loadNode(
vkglTF::Node *parent,
const tinygltf::Node &node, uint32_t nodeIndex,
const tinygltf::Model &model, std::vector<uint32_t>& indexBuffer, std::vector<Vertex>& vertexBuffer,
float globalscale)
777 newNode->
index = nodeIndex;
779 newNode->
name = node.name;
781 newNode->
matrix = glm::mat4(1.0f);
784 glm::vec3 translation = glm::vec3(0.0f);
785 if (node.translation.size() == 3) {
786 translation = glm::make_vec3(node.translation.data());
789 glm::mat4 rotation = glm::mat4(1.0f);
790 if (node.rotation.size() == 4) {
791 glm::quat q = glm::make_quat(node.rotation.data());
794 glm::vec3 scale = glm::vec3(1.0f);
795 if (node.scale.size() == 3) {
796 scale = glm::make_vec3(node.scale.data());
797 newNode->
scale = scale;
799 if (node.matrix.size() == 16) {
800 newNode->
matrix = glm::make_mat4x4(node.matrix.data());
801 if (globalscale != 1.0f) {
807 if (node.children.size() > 0) {
808 for (
auto i = 0; i < node.children.size(); i++) {
809 loadNode(newNode, model.nodes[node.children[i]], node.
children[i], model, indexBuffer, vertexBuffer, globalscale);
814 if (node.mesh > -1) {
815 const tinygltf::Mesh mesh = model.meshes[node.mesh];
817 newMesh->
name = mesh.name;
818 for (
size_t j = 0; j < mesh.primitives.size(); j++) {
819 const tinygltf::Primitive &primitive = mesh.primitives[j];
820 if (primitive.indices < 0) {
823 uint32_t indexStart =
static_cast<uint32_t
>(indexBuffer.size());
824 uint32_t vertexStart =
static_cast<uint32_t
>(vertexBuffer.size());
825 uint32_t indexCount = 0;
826 uint32_t vertexCount = 0;
829 bool hasSkin =
false;
832 const float *bufferPos =
nullptr;
833 const float *bufferNormals =
nullptr;
834 const float *bufferTexCoords =
nullptr;
835 const float* bufferColors =
nullptr;
836 const float *bufferTangents =
nullptr;
837 uint32_t numColorComponents;
838 const uint16_t *bufferJoints =
nullptr;
839 const float *bufferWeights =
nullptr;
842 assert(primitive.attributes.find(
"POSITION") != primitive.attributes.end());
844 const tinygltf::Accessor &posAccessor = model.accessors[primitive.attributes.find(
"POSITION")->second];
845 const tinygltf::BufferView &posView = model.bufferViews[posAccessor.bufferView];
846 bufferPos =
reinterpret_cast<const float *
>(&(model.buffers[posView.buffer].data[posAccessor.byteOffset + posView.byteOffset]));
847 posMin = glm::vec3(posAccessor.minValues[0], posAccessor.minValues[1], posAccessor.minValues[2]);
848 posMax = glm::vec3(posAccessor.maxValues[0], posAccessor.maxValues[1], posAccessor.maxValues[2]);
850 if (primitive.attributes.find(
"NORMAL") != primitive.attributes.end()) {
851 const tinygltf::Accessor &normAccessor = model.accessors[primitive.attributes.find(
"NORMAL")->second];
852 const tinygltf::BufferView &normView = model.bufferViews[normAccessor.bufferView];
853 bufferNormals =
reinterpret_cast<const float *
>(&(model.buffers[normView.buffer].data[normAccessor.byteOffset + normView.byteOffset]));
856 if (primitive.attributes.find(
"TEXCOORD_0") != primitive.attributes.end()) {
857 const tinygltf::Accessor &uvAccessor = model.accessors[primitive.attributes.find(
"TEXCOORD_0")->second];
858 const tinygltf::BufferView &uvView = model.bufferViews[uvAccessor.bufferView];
859 bufferTexCoords =
reinterpret_cast<const float *
>(&(model.buffers[uvView.buffer].data[uvAccessor.byteOffset + uvView.byteOffset]));
862 if (primitive.attributes.find(
"COLOR_0") != primitive.attributes.end())
864 const tinygltf::Accessor& colorAccessor = model.accessors[primitive.attributes.find(
"COLOR_0")->second];
865 const tinygltf::BufferView& colorView = model.bufferViews[colorAccessor.bufferView];
867 numColorComponents = colorAccessor.type == TINYGLTF_PARAMETER_TYPE_FLOAT_VEC3 ? 3 : 4;
868 bufferColors =
reinterpret_cast<const float*
>(&(model.buffers[colorView.buffer].data[colorAccessor.byteOffset + colorView.byteOffset]));
871 if (primitive.attributes.find(
"TANGENT") != primitive.attributes.end())
873 const tinygltf::Accessor &tangentAccessor = model.accessors[primitive.attributes.find(
"TANGENT")->second];
874 const tinygltf::BufferView &tangentView = model.bufferViews[tangentAccessor.bufferView];
875 bufferTangents =
reinterpret_cast<const float *
>(&(model.buffers[tangentView.buffer].data[tangentAccessor.byteOffset + tangentView.byteOffset]));
880 if (primitive.attributes.find(
"JOINTS_0") != primitive.attributes.end()) {
881 const tinygltf::Accessor &jointAccessor = model.accessors[primitive.attributes.find(
"JOINTS_0")->second];
882 const tinygltf::BufferView &jointView = model.bufferViews[jointAccessor.bufferView];
883 bufferJoints =
reinterpret_cast<const uint16_t *
>(&(model.buffers[jointView.buffer].data[jointAccessor.byteOffset + jointView.byteOffset]));
886 if (primitive.attributes.find(
"WEIGHTS_0") != primitive.attributes.end()) {
887 const tinygltf::Accessor &uvAccessor = model.accessors[primitive.attributes.find(
"WEIGHTS_0")->second];
888 const tinygltf::BufferView &uvView = model.bufferViews[uvAccessor.bufferView];
889 bufferWeights =
reinterpret_cast<const float *
>(&(model.buffers[uvView.buffer].data[uvAccessor.byteOffset + uvView.byteOffset]));
892 hasSkin = (bufferJoints && bufferWeights);
894 vertexCount =
static_cast<uint32_t
>(posAccessor.count);
896 for (
size_t v = 0; v < posAccessor.count; v++) {
898 vert.
pos = glm::make_vec3(&bufferPos[v * 3]);
899 vert.normal = glm::normalize(glm::vec3(bufferNormals ? glm::make_vec3(&bufferNormals[v * 3]) : glm::vec3(0.0f)));
900 vert.uv = bufferTexCoords ? glm::make_vec2(&bufferTexCoords[v * 2]) : glm::vec2(0.0f);
902 switch (numColorComponents) {
904 vert.color = glm::vec4(glm::make_vec3(&bufferColors[v * 3]), 1.0f);
906 vert.color = glm::make_vec4(&bufferColors[v * 4]);
910 vert.color = glm::vec4(1.0f);
912 vert.tangent = bufferTangents ? glm::vec4(glm::make_vec4(&bufferTangents[v * 4])) : glm::vec4(0.0f);
913 vert.joint0 = hasSkin ? glm::vec4(glm::make_vec4(&bufferJoints[v * 4])) : glm::vec4(0.0f);
914 vert.weight0 = hasSkin ? glm::make_vec4(&bufferWeights[v * 4]) : glm::vec4(0.0f);
915 vertexBuffer.push_back(vert);
920 const tinygltf::Accessor &accessor = model.accessors[primitive.indices];
921 const tinygltf::BufferView &bufferView = model.bufferViews[accessor.bufferView];
922 const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
924 indexCount =
static_cast<uint32_t
>(accessor.count);
926 switch (accessor.componentType) {
927 case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
928 uint32_t *buf =
new uint32_t[accessor.count];
929 memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count *
sizeof(uint32_t));
930 for (
size_t index = 0; index < accessor.count; index++) {
931 indexBuffer.push_back(buf[index] + vertexStart);
935 case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
936 uint16_t *buf =
new uint16_t[accessor.count];
937 memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count *
sizeof(uint16_t));
938 for (
size_t index = 0; index < accessor.count; index++) {
939 indexBuffer.push_back(buf[index] + vertexStart);
943 case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
944 uint8_t *buf =
new uint8_t[accessor.count];
945 memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count *
sizeof(uint8_t));
946 for (
size_t index = 0; index < accessor.count; index++) {
947 indexBuffer.push_back(buf[index] + vertexStart);
952 std::cerr <<
"Index component type " << accessor.componentType <<
" not supported!" << std::endl;
962 newNode->
mesh = newMesh;
965 parent->
children.push_back(newNode);
967 nodes.push_back(newNode);
1179 tinygltf::Model gltfModel;
1180 tinygltf::TinyGLTF gltfContext;
1186#if defined(__ANDROID__)
1189 tinygltf::asset_manager = androidApp->activity->assetManager;
1191 size_t pos = filename.find_last_of(
'/');
1192 path = filename.substr(0, pos);
1194 std::string error, warning;
1196#if defined(__ANDROID__)
1199 tinygltf::asset_manager = androidApp->activity->assetManager;
1201 bool fileLoaded = gltfContext.LoadASCIIFromFile(&gltfModel, &error, &warning, filename);
1203 std::vector<uint32_t> indexBuffer;
1204 std::vector<Vertex> vertexBuffer;
1211 const tinygltf::Scene &scene = gltfModel.scenes[gltfModel.defaultScene > -1 ? gltfModel.defaultScene : 0];
1212 for (
size_t i = 0; i < scene.nodes.size(); i++) {
1213 const tinygltf::Node node = gltfModel.nodes[scene.nodes[i]];
1214 loadNode(
nullptr, node, scene.nodes[i], gltfModel, indexBuffer, vertexBuffer, scale);
1216 if (gltfModel.animations.size() > 0) {
1223 if (node->skinIndex > -1) {
1224 node->skin =
skins[node->skinIndex];
1245 const glm::mat4 localMatrix = node->getMatrix();
1246 for (
Primitive* primitive : node->mesh->primitives) {
1247 for (uint32_t i = 0; i < primitive->
vertexCount; i++) {
1251 vertex.
pos = glm::vec3(localMatrix * glm::vec4(vertex.
pos, 1.0f));
1252 vertex.
normal = glm::normalize(glm::mat3(localMatrix) * vertex.
normal);
1256 vertex.
pos.y *= -1.0f;
1257 vertex.
normal.y *= -1.0f;
1260 if (preMultiplyColor) {
1269 for (
auto extension : gltfModel.extensionsUsed) {
1270 if (extension ==
"KHR_materials_pbrSpecularGlossiness") {
1271 std::cout <<
"Required extension: " << extension;
1276 size_t vertexBufferSize = vertexBuffer.size() *
sizeof(
Vertex);
1277 size_t indexBufferSize = indexBuffer.size() *
sizeof(uint32_t);
1278 indices.count =
static_cast<uint32_t
>(indexBuffer.size());
1279 vertices.count =
static_cast<uint32_t
>(vertexBuffer.size());
1281 assert((vertexBufferSize > 0) && (indexBufferSize > 0));
1283 struct StagingBuffer {
1285 VkDeviceMemory memory;
1286 } vertexStaging, indexStaging;
1291 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1292 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
1294 &vertexStaging.buffer,
1295 &vertexStaging.memory,
1296 vertexBuffer.data()));
1299 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1300 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
1302 &indexStaging.buffer,
1303 &indexStaging.memory,
1304 indexBuffer.data()));
1309 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
memoryPropertyFlags,
1310 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1316 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
memoryPropertyFlags,
1317 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1323 VkCommandBuffer copyCmd =
ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY,
true);
1325 VkBufferCopy copyRegion = {};
1327 copyRegion.size = vertexBufferSize;
1328 vkCmdCopyBuffer(copyCmd, vertexStaging.buffer,
vertices.buffer, 1, ©Region);
1330 copyRegion.size = indexBufferSize;
1331 vkCmdCopyBuffer(copyCmd, indexStaging.buffer,
indices.buffer, 1, ©Region);
1333 ctx->flushCommandBuffer(copyCmd,
ctx->graphicsQueueHandle(),
true);
1335 vkDestroyBuffer(
ctx->deviceHandle(), vertexStaging.buffer,
nullptr);
1336 vkFreeMemory(
ctx->deviceHandle(), vertexStaging.memory,
nullptr);
1337 vkDestroyBuffer(
ctx->deviceHandle(), indexStaging.buffer,
nullptr);
1338 vkFreeMemory(
ctx->deviceHandle(), indexStaging.memory,
nullptr);
1343 uint32_t uboCount{ 0 };
1344 uint32_t imageCount{ 0 };
1351 if (material.baseColorTexture !=
nullptr) {
1355 std::vector<VkDescriptorPoolSize> poolSizes = {
1356 { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uboCount },
1358 if (imageCount > 0) {
1360 poolSizes.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageCount });
1363 poolSizes.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageCount });
1366 VkDescriptorPoolCreateInfo descriptorPoolCI{};
1367 descriptorPoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1368 descriptorPoolCI.poolSizeCount =
static_cast<uint32_t
>(poolSizes.size());
1369 descriptorPoolCI.pPoolSizes = poolSizes.data();
1370 descriptorPoolCI.maxSets = uboCount + imageCount;
1377 std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
1380 VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{};
1381 descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1382 descriptorLayoutCI.bindingCount =
static_cast<uint32_t
>(setLayoutBindings.size());
1383 descriptorLayoutCI.pBindings = setLayoutBindings.data();
1386 for (
auto node :
nodes) {
1395 std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings{};
1402 VkDescriptorSetLayoutCreateInfo descriptorLayoutCI{};
1403 descriptorLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1404 descriptorLayoutCI.bindingCount =
static_cast<uint32_t
>(setLayoutBindings.size());
1405 descriptorLayoutCI.pBindings = setLayoutBindings.data();
1409 if (material.baseColorTexture !=
nullptr) {