diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2024-01-02 14:01:44 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2024-01-02 14:01:44 -0500 |
| commit | be543940e3c561ee2ab8eb315211112b97065476 (patch) | |
| tree | abbf4968dab73b7d242d3052904e5b2e2c854d82 /src/entities.cpp | |
| parent | 0b9c784570fe3660b238b537fa7ba7e5de8783aa (diff) | |
factor out loading entity textures for reuse
Diffstat (limited to 'src/entities.cpp')
| -rw-r--r-- | src/entities.cpp | 1427 |
1 files changed, 715 insertions, 712 deletions
diff --git a/src/entities.cpp b/src/entities.cpp index ab4f731..ad72b04 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -71,480 +71,712 @@ void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memRe } } +void EntityType_LoadTexture(EntityType &et, CompGrBinds &grBinds, AssetHandle textureAssetHandle) { + int32_t pixelWidth, pixelHeight, pixelChannels; + stbi_uc *pixels = nullptr; + if (textureAssetHandle != AssetHandle_MAX) { + const Asset *textureAsset = AM_Get(textureAssetHandle); + pixels = stbi_load_from_memory(static_cast<stbi_uc *>(textureAsset->ptr), textureAsset->size, &pixelWidth, &pixelHeight, &pixelChannels, STBI_rgb_alpha); + assert(pixels != nullptr && "sbti_load failed to load image."); + } else { + pixelWidth = 2; + pixelHeight = 2; + pixelChannels = 4; + pixels = const_cast<unsigned char *>(&PKE_MISSING_TEXTURE_DATA[0]); + } + + uint32_t imageSizeBytes = pixelWidth * pixelHeight * pixelChannels; + + VkFormat imageFormat = VK_FORMAT_R8G8B8A8_SRGB; + if (pixelChannels == 3) { + imageFormat = VK_FORMAT_R8G8B8_SRGB; + } else if (pixelChannels == 2) { + imageFormat = VK_FORMAT_R8G8_SRGB; + } else if (pixelChannels == 1) { + imageFormat = VK_FORMAT_R8_SRGB; + } else { + assert(pixelChannels != 0 && pixelChannels < 5); + } + + VkImageCreateInfo vkImageCreateInfo; + vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + vkImageCreateInfo.pNext = nullptr; + vkImageCreateInfo.flags = 0; + vkImageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + vkImageCreateInfo.format = imageFormat; + vkImageCreateInfo.extent = VkExtent3D { + .width = static_cast<uint32_t>(pixelWidth), + .height = static_cast<uint32_t>(pixelHeight), + .depth = 1 + }; + vkImageCreateInfo.mipLevels = 1; + vkImageCreateInfo.arrayLayers = 1; + vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + vkImageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + vkImageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + vkImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vkImageCreateInfo.queueFamilyIndexCount = 0; + vkImageCreateInfo.pQueueFamilyIndices = nullptr; + vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + vkCreateImage(vkDevice, &vkImageCreateInfo, vkAllocator, &et.textureImage); + + VkMemoryRequirements imageMemReqs; + vkGetImageMemoryRequirements(vkDevice, et.textureImage, &imageMemReqs); + VkMemoryAllocateInfo imageAllocInfo; + imageAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + imageAllocInfo.pNext = nullptr; + imageAllocInfo.allocationSize = imageMemReqs.size; + imageAllocInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemReqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (imageAllocInfo.memoryTypeIndex == 0) { + imageAllocInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemReqs.memoryTypeBits, 0); + } + vkAllocateMemory(vkDevice, &imageAllocInfo, vkAllocator, &et.deviceMemoryTexture); + vkBindImageMemory(vkDevice, et.textureImage, et.deviceMemoryTexture, 0); + + VkImageViewCreateInfo vkImageViewCreateInfo; + vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + vkImageViewCreateInfo.pNext = nullptr; + vkImageViewCreateInfo.flags = 0; + vkImageViewCreateInfo.image = et.textureImage; + // TODO animated textures + vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + vkImageViewCreateInfo.format = imageFormat; + vkImageViewCreateInfo.components = VkComponentMapping { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }; + vkImageViewCreateInfo.subresourceRange = VkImageSubresourceRange { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + // TODO MapMap + .levelCount = 1, + .baseArrayLayer = 0, + // TODO animated textures + .layerCount = 1, + }; + + vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &et.textureImageView); + + // transition image layout and copy to buffer + VkBuffer transferImageBuffer; + VkDeviceMemory transferImageMemory; + void *deviceData; + BeginTransferBuffer(imageSizeBytes, transferImageBuffer, transferImageMemory, deviceData); + memcpy(deviceData, pixels, imageSizeBytes); + { + VkImageMemoryBarrier vkImageMemoryBarrier; + vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + vkImageMemoryBarrier.pNext = nullptr; + vkImageMemoryBarrier.srcAccessMask = {}; + vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.image = et.textureImage; + vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + // TODO MipMap + .levelCount = 1, + .baseArrayLayer = 0, + // TODO animated textures + .layerCount = 1, + }; + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + + vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo); + + vkCmdPipelineBarrier(transferCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); + + // TODO animated textures / texture array - make this an array + VkBufferImageCopy vkBufferImageCopy; + vkBufferImageCopy.bufferOffset = 0; + vkBufferImageCopy.bufferRowLength = pixelWidth; + vkBufferImageCopy.bufferImageHeight = pixelHeight; + vkBufferImageCopy.imageSubresource = VkImageSubresourceLayers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + // TODO animated textures + .baseArrayLayer = 0, + .layerCount = 1, + }; + vkBufferImageCopy.imageOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }; + vkBufferImageCopy.imageExtent = VkExtent3D { + .width = static_cast<uint32_t>(pixelWidth), + .height = static_cast<uint32_t>(pixelHeight), + .depth = 1, + }; + vkCmdCopyBufferToImage(transferCommandBuffer, transferImageBuffer, et.textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vkBufferImageCopy); + + vkEndCommandBuffer(transferCommandBuffer); + + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &transferCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(transferQueue); + vkResetCommandBuffer(transferCommandBuffer, 0); + } + EndTransferBuffer(transferImageBuffer, transferImageMemory); + { + VkImageMemoryBarrier vkImageMemoryBarrier; + vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + vkImageMemoryBarrier.pNext = nullptr; + vkImageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.image = et.textureImage; + vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + // TODO MipMap + .levelCount = 1, + .baseArrayLayer = 0, + // TODO animated textures + .layerCount = 1, + }; + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + + vkBeginCommandBuffer(graphicsCommandBuffer, &vkCommandBufferBeginInfo); + + vkCmdPipelineBarrier(graphicsCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); + + vkEndCommandBuffer(graphicsCommandBuffer); + + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &graphicsCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(graphicsQueue); + } + + // TODO double-check this? + // stbi_image_free(pixels); + if (textureAssetHandle != AssetHandle_MAX) { + AM_Release(textureAssetHandle); + } + + // descriptor pool & sets + + VkDescriptorPoolSize descriptorPoolSizes[2]; + descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorPoolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT; + descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorPoolSizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT; + + VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo; + vkDescriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + vkDescriptorPoolCreateInfo.pNext = nullptr; + vkDescriptorPoolCreateInfo.flags = 0; + vkDescriptorPoolCreateInfo.maxSets = MAX_FRAMES_IN_FLIGHT; + vkDescriptorPoolCreateInfo.poolSizeCount = (uint32_t)2; + vkDescriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes; + + // consider making me a global pool + auto vkResult = vkCreateDescriptorPool(vkDevice, &vkDescriptorPoolCreateInfo, vkAllocator, &et.vkDescriptorPool); + assert(vkResult == VK_SUCCESS); + + VkDescriptorSetLayout descriptorSets[MAX_FRAMES_IN_FLIGHT]; + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + descriptorSets[i] = pkePipelines.vkDescriptorSetLayout_Texture; + } + VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo; + vkDescriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + vkDescriptorSetAllocateInfo.pNext = nullptr; + vkDescriptorSetAllocateInfo.descriptorPool = et.vkDescriptorPool; + vkDescriptorSetAllocateInfo.descriptorSetCount = MAX_FRAMES_IN_FLIGHT; + vkDescriptorSetAllocateInfo.pSetLayouts = descriptorSets; + + grBinds.vkDescriptorSets = Pke_New<VkDescriptorSet>(MAX_FRAMES_IN_FLIGHT); + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + grBinds.vkDescriptorSets[i] = VkDescriptorSet{}; + } + vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, grBinds.vkDescriptorSets); + assert(vkResult == VK_SUCCESS); + + VkWriteDescriptorSet writeDescriptorSets[2 * MAX_FRAMES_IN_FLIGHT]; + for (long i = 0; i < 2 * MAX_FRAMES_IN_FLIGHT; ++i) { + writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSets[i].pNext = nullptr; + writeDescriptorSets[i].dstSet = nullptr; + writeDescriptorSets[i].dstBinding = i % 2; + writeDescriptorSets[i].dstArrayElement = 0; + writeDescriptorSets[i].descriptorCount = 1; + writeDescriptorSets[i].descriptorType = (i % 2) == 0 + ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writeDescriptorSets[i].pImageInfo = nullptr; + writeDescriptorSets[i].pBufferInfo = nullptr; + writeDescriptorSets[i].pTexelBufferView = nullptr; + } + + VkDescriptorImageInfo textureDescriptorInfo; + textureDescriptorInfo.sampler = pkePipelines.vkSampler_Texture; + textureDescriptorInfo.imageView = et.textureImageView; + textureDescriptorInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDescriptorBufferInfo vkDescriptorBufferInfo[MAX_FRAMES_IN_FLIGHT]; + + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + vkDescriptorBufferInfo[i].buffer = UniformBuffers[i]; + vkDescriptorBufferInfo[i].offset = 0; + vkDescriptorBufferInfo[i].range = sizeof(UniformBufferObject); + + long uboIndex = i * 2; + long samplerIndex = uboIndex + 1; + + writeDescriptorSets[uboIndex].pBufferInfo = &vkDescriptorBufferInfo[i]; + writeDescriptorSets[uboIndex].dstSet = grBinds.vkDescriptorSets[i]; + + writeDescriptorSets[samplerIndex].pImageInfo = &textureDescriptorInfo; + writeDescriptorSets[samplerIndex].dstSet = grBinds.vkDescriptorSets[i]; + } + + vkUpdateDescriptorSets(vkDevice, 2 * MAX_FRAMES_IN_FLIGHT, writeDescriptorSets, 0, nullptr); +} + void EntityType_Load(EntityType &et) { assert(et.startingInstanceCount > 0); AssetHandle assetHandle{AM_GetHandle(et.modelAssetKey)}; + assert(assetHandle != AssetHandle_MAX); + + CompGrBinds &grBinds = ECS_CreateGrBinds(et.entityHandle); + /* + * 2023-09-13 - JCB + * I don't like that we're just copying this. + * This should be moved to window.cpp. + */ + grBinds.vkPipelineLayout = pkePipelines.vkPipelineLayout_Texture; + grBinds.graphicsPipeline = pkePipelines.pipelines.Texture; + et.grBindsHandle = grBinds.grBindsHandle; + + // handle texture AssetHandle textureAssetHandle{AM_GetHandle(et.textureAssetKey)}; - if (assetHandle != AssetHandle_MAX) { - const Asset *asset = AM_Get(assetHandle); - - CompGrBinds &grBinds = ECS_CreateGrBinds(et.entityHandle); - /* - * 2023-09-13 - JCB - * I don't like that we're just copying this. - * This should be moved to window.cpp. - */ - grBinds.vkPipelineLayout = pkePipelines.vkPipelineLayout_Texture; - grBinds.graphicsPipeline = pkePipelines.pipelines.Texture; - et.grBindsHandle = grBinds.grBindsHandle; - - cgltf_options options{}; - // TODO allocator - cgltf_data *gltfData = nullptr; - cgltf_result result = cgltf_parse(&options, asset->ptr, asset->size, &gltfData); - assert(result == cgltf_result_success); - // result = cgltf_load_buffers(&options, gltfData, modelPath); - // assert(result == cgltf_result_success); - result = cgltf_validate(gltfData); - assert(result == cgltf_result_success); - assert(gltfData->buffers_count == 1); - - std::filesystem::path gltfPath{asset->basePath}; - gltfPath.replace_filename(gltfData->buffers[0].uri); - AssetHandle modelBinHandle = AM_Register(gltfPath.c_str(), PKE_ASSET_TYPE_UNSET); - - int pixelWidth, pixelHeight, pixelChannels; - stbi_uc *pixels = nullptr; - if (textureAssetHandle != AssetHandle_MAX) { - const Asset *textureAsset = AM_Get(textureAssetHandle); - pixels = stbi_load_from_memory(static_cast<stbi_uc *>(textureAsset->ptr), textureAsset->size, &pixelWidth, &pixelHeight, &pixelChannels, STBI_rgb_alpha); - assert(pixels != nullptr && "sbti_load failed to load image."); - } else { - pixelWidth = 2; - pixelHeight = 2; - pixelChannels = 4; - pixels = const_cast<unsigned char *>(&PKE_MISSING_TEXTURE_DATA[0]); - } + EntityType_LoadTexture(et, grBinds, textureAssetHandle); + + //handle gltf + const Asset *asset = AM_Get(assetHandle); + cgltf_options options{}; + // TODO allocator + cgltf_data *gltfData = nullptr; + cgltf_result result = cgltf_parse(&options, asset->ptr, asset->size, &gltfData); + assert(result == cgltf_result_success); + // result = cgltf_load_buffers(&options, gltfData, modelPath); + // assert(result == cgltf_result_success); + result = cgltf_validate(gltfData); + assert(result == cgltf_result_success); + assert(gltfData->buffers_count == 1); + + std::filesystem::path gltfPath{asset->basePath}; + gltfPath.replace_filename(gltfData->buffers[0].uri); + AssetHandle modelBinHandle = AM_Register(gltfPath.c_str(), PKE_ASSET_TYPE_UNSET); + + // make sure cgltf can interpret our model + for (long i = 0; i < gltfData->accessors_count; ++i) { + assert(gltfData->accessors[i].type != cgltf_type_invalid); + } + for (long i = 0; i < gltfData->buffers_count; ++i) { + assert(gltfData->buffer_views[i].type != cgltf_buffer_view_type_invalid); + } + assert(et.Importer_GLTF.AccessorIndexVertex > -1); + assert(et.Importer_GLTF.AccessorIndexNormal > -1); + assert(et.Importer_GLTF.AccessorIndexUV > -1); + assert(et.Importer_GLTF.AccessorIndexIndex > -1); + + VkBufferCreateInfo bufferCI; + bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCI.pNext = nullptr; + bufferCI.flags = {}; + bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + bufferCI.queueFamilyIndexCount = 1; + bufferCI.pQueueFamilyIndices = &graphicsFamilyIndex; + + const long expectedBufferCount = 4; + VkMemoryRequirements vkMemoryRequirements[expectedBufferCount]; + long index = 0; + + // vertex + assert(et.Importer_GLTF.AccessorIndexVertex > -1); + const auto &accVert = gltfData->accessors[et.Importer_GLTF.AccessorIndexVertex]; + grBinds.vertexFirstBinding = index; + grBinds.vertexBindingCount = 1; + bufferCI.size = accVert.buffer_view->size; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.vertexBuffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.vertexBuffer, &vkMemoryRequirements[index]); + index += 1; + + // normals + assert(et.Importer_GLTF.AccessorIndexNormal > -1); + const auto &accNorm = gltfData->accessors[et.Importer_GLTF.AccessorIndexNormal]; + grBinds.normalsFirstBinding = index; + grBinds.normalsBindingCount = 1; + bufferCI.size = accNorm.buffer_view->size; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.normalsBuffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.normalsBuffer, &vkMemoryRequirements[index]); + index += 1; + + // uv + assert(et.Importer_GLTF.AccessorIndexUV > -1); + const auto &accUV = gltfData->accessors[et.Importer_GLTF.AccessorIndexUV]; + grBinds.uvFirstBinding = index; + grBinds.uvBindingCount = 1; + bufferCI.size = accUV.buffer_view->size; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.uvBuffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.uvBuffer, &vkMemoryRequirements[index]); + index += 1; + + // 2023-09-27 - JCB + // I don't know where else to put this + grBinds.instanceFirstBinding = index; + grBinds.instanceBindingCount = 1; + // no index += 1 because index just happens to be the right value here for + // the binding index, whereas binding the IndexBuffer doesn't need a binding index. + + // index + assert(et.Importer_GLTF.AccessorIndexIndex > -1); + const auto &accIndex = gltfData->accessors[et.Importer_GLTF.AccessorIndexIndex]; + grBinds.indexBindingCount = 1; + grBinds.indexCount = accIndex.count; + bufferCI.size = accIndex.buffer_view->size; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.indexBuffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.indexBuffer, &vkMemoryRequirements[index]); + // index += 1; + + vkDestroyBuffer(vkDevice, grBinds.indexBuffer, vkAllocator); + vkDestroyBuffer(vkDevice, grBinds.uvBuffer, vkAllocator); + vkDestroyBuffer(vkDevice, grBinds.normalsBuffer, vkAllocator); + vkDestroyBuffer(vkDevice, grBinds.vertexBuffer, vkAllocator); + + VkMemoryRequirements combinedMemReqs{}; + combinedMemReqs.alignment = vkMemoryRequirements[0].alignment; + combinedMemReqs.memoryTypeBits = 0; + combinedMemReqs.size = 0; + CalculateCombinedMemReqs(expectedBufferCount, vkMemoryRequirements, combinedMemReqs); + + // create VkDeviceMemory + VkMemoryAllocateInfo vkMemoryAllocateInfo; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = nullptr; + vkMemoryAllocateInfo.allocationSize = combinedMemReqs.size; + vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combinedMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryVert); + + // bind buffers + uint32_t runningOffset = 0; + uint32_t alignmentPadding; + + // vertex + uint32_t offsetVert = runningOffset; + uint32_t sizeVert = accVert.buffer_view->size; + alignmentPadding = sizeVert % combinedMemReqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; + sizeVert += alignmentPadding; + bufferCI.size = sizeVert; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.vertexBuffer); + vkBindBufferMemory(vkDevice, grBinds.vertexBuffer, et.deviceMemoryVert, offsetVert); + runningOffset += sizeVert; + + // norm + uint32_t offsetNorm = runningOffset; + uint32_t sizeNorm = accNorm.buffer_view->size; + alignmentPadding = sizeNorm % combinedMemReqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; + sizeNorm += alignmentPadding; + bufferCI.size = sizeNorm; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.normalsBuffer); + vkBindBufferMemory(vkDevice, grBinds.normalsBuffer, et.deviceMemoryVert, offsetNorm); + runningOffset += sizeNorm; + + // uv + uint32_t offsetUV = runningOffset; + uint32_t sizeUV = accUV.buffer_view->size; + alignmentPadding = sizeUV % combinedMemReqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; + sizeUV += alignmentPadding; + bufferCI.size = sizeUV; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.uvBuffer); + vkBindBufferMemory(vkDevice, grBinds.uvBuffer , et.deviceMemoryVert, offsetUV); + runningOffset += sizeUV; + + // index + uint32_t offsetIndex = runningOffset; + uint32_t sizeIndex = accIndex.buffer_view->size; + alignmentPadding = sizeIndex % combinedMemReqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; + sizeIndex += alignmentPadding; + bufferCI.size = sizeIndex; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.indexBuffer); + vkBindBufferMemory(vkDevice, grBinds.indexBuffer, et.deviceMemoryVert, offsetIndex); + runningOffset += sizeIndex; + + assert(runningOffset == combinedMemReqs.size); + const Asset *modelBinAsset = AM_Get(modelBinHandle); + + // create transfer items && transfer + { + VkDeviceMemory transferDeviceMemory; + VkBuffer transferBuffer; + void *data; + BeginTransferBuffer(combinedMemReqs.size, transferBuffer, transferDeviceMemory, data); + memset(data, '\0', combinedMemReqs.size); - { - uint32_t imageSizeBytes = pixelWidth * pixelHeight * pixelChannels; - - VkFormat imageFormat = VK_FORMAT_R8G8B8A8_SRGB; - if (pixelChannels == 3) { - imageFormat = VK_FORMAT_R8G8B8_SRGB; - } else if (pixelChannels == 2) { - imageFormat = VK_FORMAT_R8G8_SRGB; - } else if (pixelChannels == 1) { - imageFormat = VK_FORMAT_R8_SRGB; - } else { - assert(pixelChannels != 0 && pixelChannels < 5); - } + char *dstPtr = nullptr; + char *srcPtr = nullptr; - VkImageCreateInfo vkImageCreateInfo; - vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - vkImageCreateInfo.pNext = nullptr; - vkImageCreateInfo.flags = 0; - vkImageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - vkImageCreateInfo.format = imageFormat; - vkImageCreateInfo.extent = VkExtent3D { - .width = static_cast<uint32_t>(pixelWidth), - .height = static_cast<uint32_t>(pixelHeight), - .depth = 1 - }; - vkImageCreateInfo.mipLevels = 1; - vkImageCreateInfo.arrayLayers = 1; - vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - vkImageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - vkImageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - vkImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - vkImageCreateInfo.queueFamilyIndexCount = 0; - vkImageCreateInfo.pQueueFamilyIndices = nullptr; - vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - vkCreateImage(vkDevice, &vkImageCreateInfo, vkAllocator, &et.textureImage); - - VkMemoryRequirements imageMemReqs; - vkGetImageMemoryRequirements(vkDevice, et.textureImage, &imageMemReqs); - VkMemoryAllocateInfo imageAllocInfo; - imageAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - imageAllocInfo.pNext = nullptr; - imageAllocInfo.allocationSize = imageMemReqs.size; - imageAllocInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemReqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - if (imageAllocInfo.memoryTypeIndex == 0) { - imageAllocInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemReqs.memoryTypeBits, 0); - } - vkAllocateMemory(vkDevice, &imageAllocInfo, vkAllocator, &et.deviceMemoryTexture); - vkBindImageMemory(vkDevice, et.textureImage, et.deviceMemoryTexture, 0); - - VkImageViewCreateInfo vkImageViewCreateInfo; - vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - vkImageViewCreateInfo.pNext = nullptr; - vkImageViewCreateInfo.flags = 0; - vkImageViewCreateInfo.image = et.textureImage; - // TODO animated textures - vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - vkImageViewCreateInfo.format = imageFormat; - vkImageViewCreateInfo.components = VkComponentMapping { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }; - vkImageViewCreateInfo.subresourceRange = VkImageSubresourceRange { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - // TODO MapMap - .levelCount = 1, - .baseArrayLayer = 0, - // TODO animated textures - .layerCount = 1, - }; - - vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &et.textureImageView); - - // transition image layout and copy to buffer - VkBuffer transferImageBuffer; - VkDeviceMemory transferImageMemory; - void *deviceData; - BeginTransferBuffer(imageSizeBytes, transferImageBuffer, transferImageMemory, deviceData); - memcpy(deviceData, pixels, imageSizeBytes); - { - VkImageMemoryBarrier vkImageMemoryBarrier; - vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - vkImageMemoryBarrier.pNext = nullptr; - vkImageMemoryBarrier.srcAccessMask = {}; - vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkImageMemoryBarrier.image = et.textureImage; - vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - // TODO MipMap - .levelCount = 1, - .baseArrayLayer = 0, - // TODO animated textures - .layerCount = 1, - }; - - VkCommandBufferBeginInfo vkCommandBufferBeginInfo; - vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkCommandBufferBeginInfo.pNext = nullptr; - vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; - - vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo); - - vkCmdPipelineBarrier(transferCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); - - // TODO animated textures / texture array - make this an array - VkBufferImageCopy vkBufferImageCopy; - vkBufferImageCopy.bufferOffset = 0; - vkBufferImageCopy.bufferRowLength = pixelWidth; - vkBufferImageCopy.bufferImageHeight = pixelHeight; - vkBufferImageCopy.imageSubresource = VkImageSubresourceLayers { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - // TODO animated textures - .baseArrayLayer = 0, - .layerCount = 1, - }; - vkBufferImageCopy.imageOffset = VkOffset3D { - .x = 0, - .y = 0, - .z = 0, - }; - vkBufferImageCopy.imageExtent = VkExtent3D { - .width = static_cast<uint32_t>(pixelWidth), - .height = static_cast<uint32_t>(pixelHeight), - .depth = 1, - }; - vkCmdCopyBufferToImage(transferCommandBuffer, transferImageBuffer, et.textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vkBufferImageCopy); - - vkEndCommandBuffer(transferCommandBuffer); - - VkSubmitInfo submitInfo; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.waitSemaphoreCount = 0; - submitInfo.pWaitSemaphores = nullptr; - submitInfo.pWaitDstStageMask = nullptr; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &transferCommandBuffer; - submitInfo.signalSemaphoreCount = 0; - submitInfo.pSignalSemaphores = nullptr; - vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); - vkQueueWaitIdle(transferQueue); - vkResetCommandBuffer(transferCommandBuffer, 0); - } - EndTransferBuffer(transferImageBuffer, transferImageMemory); - { - VkImageMemoryBarrier vkImageMemoryBarrier; - vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - vkImageMemoryBarrier.pNext = nullptr; - vkImageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vkImageMemoryBarrier.image = et.textureImage; - vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - // TODO MipMap - .levelCount = 1, - .baseArrayLayer = 0, - // TODO animated textures - .layerCount = 1, - }; - - VkCommandBufferBeginInfo vkCommandBufferBeginInfo; - vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkCommandBufferBeginInfo.pNext = nullptr; - vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; - - vkBeginCommandBuffer(graphicsCommandBuffer, &vkCommandBufferBeginInfo); - - vkCmdPipelineBarrier(graphicsCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); - - vkEndCommandBuffer(graphicsCommandBuffer); - - VkSubmitInfo submitInfo; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.waitSemaphoreCount = 0; - submitInfo.pWaitSemaphores = nullptr; - submitInfo.pWaitDstStageMask = nullptr; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &graphicsCommandBuffer; - submitInfo.signalSemaphoreCount = 0; - submitInfo.pSignalSemaphores = nullptr; - vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr); - vkQueueWaitIdle(graphicsQueue); - } + dstPtr = static_cast<char *>(data) + offsetVert; + srcPtr = static_cast<char *>(modelBinAsset->ptr) + accVert.buffer_view->offset; + memcpy(dstPtr, srcPtr, accVert.buffer_view->size); - // TODO double-check this? - // stbi_image_free(pixels); - if (textureAssetHandle != AssetHandle_MAX) { - AM_Release(textureAssetHandle); - } + dstPtr = static_cast<char *>(data) + offsetNorm; + srcPtr = static_cast<char *>(modelBinAsset->ptr) + accNorm.buffer_view->offset; + memcpy(dstPtr, srcPtr, accNorm.buffer_view->size); - // descriptor pool & sets - - VkDescriptorPoolSize descriptorPoolSizes[2]; - descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorPoolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT; - descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorPoolSizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT; - - VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo; - vkDescriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - vkDescriptorPoolCreateInfo.pNext = nullptr; - vkDescriptorPoolCreateInfo.flags = 0; - vkDescriptorPoolCreateInfo.maxSets = MAX_FRAMES_IN_FLIGHT; - vkDescriptorPoolCreateInfo.poolSizeCount = (uint32_t)2; - vkDescriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes; - - // consider making me a global pool - auto vkResult = vkCreateDescriptorPool(vkDevice, &vkDescriptorPoolCreateInfo, vkAllocator, &et.vkDescriptorPool); - assert(vkResult == VK_SUCCESS); - - VkDescriptorSetLayout descriptorSets[MAX_FRAMES_IN_FLIGHT]; - for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - descriptorSets[i] = pkePipelines.vkDescriptorSetLayout_Texture; - } - VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo; - vkDescriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - vkDescriptorSetAllocateInfo.pNext = nullptr; - vkDescriptorSetAllocateInfo.descriptorPool = et.vkDescriptorPool; - vkDescriptorSetAllocateInfo.descriptorSetCount = MAX_FRAMES_IN_FLIGHT; - vkDescriptorSetAllocateInfo.pSetLayouts = descriptorSets; - - grBinds.vkDescriptorSets = Pke_New<VkDescriptorSet>(MAX_FRAMES_IN_FLIGHT); - for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - grBinds.vkDescriptorSets[i] = VkDescriptorSet{}; - } - vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, grBinds.vkDescriptorSets); - assert(vkResult == VK_SUCCESS); - - VkWriteDescriptorSet writeDescriptorSets[2 * MAX_FRAMES_IN_FLIGHT]; - for (long i = 0; i < 2 * MAX_FRAMES_IN_FLIGHT; ++i) { - writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSets[i].pNext = nullptr; - writeDescriptorSets[i].dstSet = nullptr; - writeDescriptorSets[i].dstBinding = i % 2; - writeDescriptorSets[i].dstArrayElement = 0; - writeDescriptorSets[i].descriptorCount = 1; - writeDescriptorSets[i].descriptorType = (i % 2) == 0 - ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSets[i].pImageInfo = nullptr; - writeDescriptorSets[i].pBufferInfo = nullptr; - writeDescriptorSets[i].pTexelBufferView = nullptr; - } + dstPtr = static_cast<char *>(data) + offsetUV; + srcPtr = static_cast<char *>(modelBinAsset->ptr) + accUV.buffer_view->offset; + memcpy(dstPtr, srcPtr, accUV.buffer_view->size); + + dstPtr = static_cast<char *>(data) + offsetIndex; + srcPtr = static_cast<char *>(modelBinAsset->ptr) + accIndex.buffer_view->offset; + memcpy(dstPtr, srcPtr, accIndex.buffer_view->size); + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + // TODO consider single-use? + vkCommandBufferBeginInfo.flags = 0; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo); + VkBufferCopy bufferCopys[expectedBufferCount]; + for (long i = 0; i < expectedBufferCount; ++i) { + bufferCopys[i].dstOffset = 0; + } + index = 0; + bufferCopys[index].srcOffset = offsetVert; + bufferCopys[index].size = sizeVert; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.vertexBuffer, 1, &bufferCopys[index]); + index+=1; - VkDescriptorImageInfo textureDescriptorInfo; - textureDescriptorInfo.sampler = pkePipelines.vkSampler_Texture; - textureDescriptorInfo.imageView = et.textureImageView; - textureDescriptorInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + bufferCopys[index].srcOffset = offsetNorm; + bufferCopys[index].size = sizeNorm; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.normalsBuffer, 1, &bufferCopys[index]); + index+=1; - VkDescriptorBufferInfo vkDescriptorBufferInfo[MAX_FRAMES_IN_FLIGHT]; + bufferCopys[index].srcOffset = offsetUV; + bufferCopys[index].size = sizeUV; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.uvBuffer, 1, &bufferCopys[index]); + index+=1; - for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - vkDescriptorBufferInfo[i].buffer = UniformBuffers[i]; - vkDescriptorBufferInfo[i].offset = 0; - vkDescriptorBufferInfo[i].range = sizeof(UniformBufferObject); + bufferCopys[index].srcOffset = offsetIndex; + bufferCopys[index].size = sizeIndex; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.indexBuffer, 1, &bufferCopys[index]); + // index+=1; - long uboIndex = i * 2; - long samplerIndex = uboIndex + 1; + vkEndCommandBuffer(transferCommandBuffer); - writeDescriptorSets[uboIndex].pBufferInfo = &vkDescriptorBufferInfo[i]; - writeDescriptorSets[uboIndex].dstSet = grBinds.vkDescriptorSets[i]; + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &transferCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(transferQueue); - writeDescriptorSets[samplerIndex].pImageInfo = &textureDescriptorInfo; - writeDescriptorSets[samplerIndex].dstSet = grBinds.vkDescriptorSets[i]; - } + EndTransferBuffer(transferBuffer, transferDeviceMemory); + } - vkUpdateDescriptorSets(vkDevice, 2 * MAX_FRAMES_IN_FLIGHT, writeDescriptorSets, 0, nullptr); - } + // set up instance buffer + grBinds.instanceBufferMaxCount = et.startingInstanceCount; + grBinds.instanceBufferMaxCount = grBinds.instanceBufferMaxCount < 1 ? 1 : grBinds.instanceBufferMaxCount; + bufferCI.size = sizeof(glm::mat4) * grBinds.instanceBufferMaxCount; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.instanceBuffer); + VkMemoryRequirements vkMemoryRequirementsInst; + vkGetBufferMemoryRequirements(vkDevice, grBinds.instanceBuffer, &vkMemoryRequirementsInst); + vkMemoryAllocateInfo.allocationSize = vkMemoryRequirementsInst.size; + vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemoryRequirementsInst.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryInst); + vkBindBufferMemory(vkDevice, grBinds.instanceBuffer, et.deviceMemoryInst, 0); + + // bullet + btConvexHullShape *shape; + { + shape = Pke_New<btConvexHullShape>(MemBkt_Bullet); + btScalar *vertDataPointer = reinterpret_cast<btScalar *>(modelBinAsset->ptr); + vertDataPointer += accVert.buffer_view->offset; + new (shape) btConvexHullShape(vertDataPointer, accVert.count, accVert.stride); + shape->optimizeConvexHull(); + shape->initializePolyhedralFeatures(); + et.bt.shape = shape; + } + assert(shape != nullptr); + + modelBinAsset = CAFE_BABE(Asset); + AM_Release(modelBinHandle); - // make sure cgltf can interpret our model - for (long i = 0; i < gltfData->accessors_count; ++i) { - assert(gltfData->accessors[i].type != cgltf_type_invalid); + // set up convex hull debug + { + const btConvexPolyhedron *pol = shape->getConvexPolyhedron(); + DynArray<glm::vec3> vertexes{pol->m_vertices.size(), MemBkt_Bullet}; + DynArray<glm::vec3> normals{pol->m_vertices.size(), MemBkt_Bullet}; + DynArray<glm::vec2> uv{pol->m_vertices.size(), MemBkt_Bullet}; + DynArray<uint16_t> indexes{pol->m_faces.size() * 6, MemBkt_Bullet}; + for (long i = 0; i < pol->m_vertices.size(); ++i) { + btVector3 norm = pol->m_vertices[i]; + auto &glmVert = vertexes.Push(); + BulletToGlm(norm, glmVert); + norm.safeNormalize(); + auto &glmNorm = normals.Push(); + BulletToGlm(norm, glmNorm); + uv.Push({norm.x(), norm.y()}); } - for (long i = 0; i < gltfData->buffers_count; ++i) { - assert(gltfData->buffer_views[i].type != cgltf_buffer_view_type_invalid); + for (long i = 0; i < pol->m_faces.size(); ++i) { + for (long k = 2; k < pol->m_faces[i].m_indices.size(); ++k) { + indexes.Push(pol->m_faces[i].m_indices[0]); + indexes.Push(pol->m_faces[i].m_indices[k - 1]); + indexes.Push(pol->m_faces[i].m_indices[k]); + } } - assert(et.Importer_GLTF.AccessorIndexVertex > -1); - assert(et.Importer_GLTF.AccessorIndexNormal > -1); - assert(et.Importer_GLTF.AccessorIndexUV > -1); - assert(et.Importer_GLTF.AccessorIndexIndex > -1); - - VkBufferCreateInfo bufferCI; - bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferCI.pNext = nullptr; - bufferCI.flags = {}; - bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - bufferCI.queueFamilyIndexCount = 1; - bufferCI.pQueueFamilyIndices = &graphicsFamilyIndex; - - const long expectedBufferCount = 4; - VkMemoryRequirements vkMemoryRequirements[expectedBufferCount]; - long index = 0; - // vertex - assert(et.Importer_GLTF.AccessorIndexVertex > -1); - const auto &accVert = gltfData->accessors[et.Importer_GLTF.AccessorIndexVertex]; - grBinds.vertexFirstBinding = index; - grBinds.vertexBindingCount = 1; - bufferCI.size = accVert.buffer_view->size; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.vertexBuffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.vertexBuffer, &vkMemoryRequirements[index]); - index += 1; - - // normals - assert(et.Importer_GLTF.AccessorIndexNormal > -1); - const auto &accNorm = gltfData->accessors[et.Importer_GLTF.AccessorIndexNormal]; - grBinds.normalsFirstBinding = index; - grBinds.normalsBindingCount = 1; - bufferCI.size = accNorm.buffer_view->size; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.normalsBuffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.normalsBuffer, &vkMemoryRequirements[index]); - index += 1; - - // uv - assert(et.Importer_GLTF.AccessorIndexUV > -1); - const auto &accUV = gltfData->accessors[et.Importer_GLTF.AccessorIndexUV]; - grBinds.uvFirstBinding = index; - grBinds.uvBindingCount = 1; - bufferCI.size = accUV.buffer_view->size; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.uvBuffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.uvBuffer, &vkMemoryRequirements[index]); - index += 1; - - // 2023-09-27 - JCB - // I don't know where else to put this - grBinds.instanceFirstBinding = index; - grBinds.instanceBindingCount = 1; - // no index += 1 because index just happens to be the right value here for - // the binding index, whereas binding the IndexBuffer doesn't need a binding index. + VkBufferCreateInfo physBufferCI[4]; + for (long i = 0; i < 4; ++i) { + physBufferCI[i].sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + physBufferCI[i].pNext = nullptr; + physBufferCI[i].flags = {}; + physBufferCI[i].sharingMode = VK_SHARING_MODE_EXCLUSIVE; + physBufferCI[i].queueFamilyIndexCount = 1; + physBufferCI[i].pQueueFamilyIndices = &graphicsFamilyIndex; + } - // index - assert(et.Importer_GLTF.AccessorIndexIndex > -1); - const auto &accIndex = gltfData->accessors[et.Importer_GLTF.AccessorIndexIndex]; - grBinds.indexBindingCount = 1; - grBinds.indexCount = accIndex.count; - bufferCI.size = accIndex.buffer_view->size; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.indexBuffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.indexBuffer, &vkMemoryRequirements[index]); - // index += 1; - - vkDestroyBuffer(vkDevice, grBinds.indexBuffer, vkAllocator); - vkDestroyBuffer(vkDevice, grBinds.uvBuffer, vkAllocator); - vkDestroyBuffer(vkDevice, grBinds.normalsBuffer, vkAllocator); - vkDestroyBuffer(vkDevice, grBinds.vertexBuffer, vkAllocator); - - VkMemoryRequirements combinedMemReqs{}; - combinedMemReqs.alignment = vkMemoryRequirements[0].alignment; - combinedMemReqs.memoryTypeBits = 0; - combinedMemReqs.size = 0; - CalculateCombinedMemReqs(expectedBufferCount, vkMemoryRequirements, combinedMemReqs); - - // create VkDeviceMemory - VkMemoryAllocateInfo vkMemoryAllocateInfo; - vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - vkMemoryAllocateInfo.pNext = nullptr; - vkMemoryAllocateInfo.allocationSize = combinedMemReqs.size; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combinedMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryVert); - - // bind buffers - uint32_t runningOffset = 0; - uint32_t alignmentPadding; + VkMemoryRequirements memReqs[4]; // vertex - uint32_t offsetVert = runningOffset; - uint32_t sizeVert = accVert.buffer_view->size; - alignmentPadding = sizeVert % combinedMemReqs.alignment; - alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; - sizeVert += alignmentPadding; - bufferCI.size = sizeVert; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.vertexBuffer); - vkBindBufferMemory(vkDevice, grBinds.vertexBuffer, et.deviceMemoryVert, offsetVert); - runningOffset += sizeVert; + index = 0; + physBufferCI[index].size = sizeof(glm::vec3) * vertexes.Count(); + physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physVertBD.buffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.physVertBD.buffer, &memReqs[index]); + grBinds.physVertBD.bindingCount = vertexes.Count(); + grBinds.physVertBD.firstBinding = index; // norm - uint32_t offsetNorm = runningOffset; - uint32_t sizeNorm = accNorm.buffer_view->size; - alignmentPadding = sizeNorm % combinedMemReqs.alignment; - alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; - sizeNorm += alignmentPadding; - bufferCI.size = sizeNorm; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.normalsBuffer); - vkBindBufferMemory(vkDevice, grBinds.normalsBuffer, et.deviceMemoryVert, offsetNorm); - runningOffset += sizeNorm; + index = 1; + physBufferCI[index].size = sizeof(glm::vec3) * normals.Count(); + physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physNormBD.buffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.physNormBD.buffer, &memReqs[index]); + grBinds.physNormBD.bindingCount = normals.Count(); + grBinds.physNormBD.firstBinding = index; // uv - uint32_t offsetUV = runningOffset; - uint32_t sizeUV = accUV.buffer_view->size; - alignmentPadding = sizeUV % combinedMemReqs.alignment; - alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; - sizeUV += alignmentPadding; - bufferCI.size = sizeUV; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.uvBuffer); - vkBindBufferMemory(vkDevice, grBinds.uvBuffer , et.deviceMemoryVert, offsetUV); - runningOffset += sizeUV; + index = 2; + physBufferCI[index].size = sizeof(glm::vec2) * uv.Count(); + physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physUvBD.buffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.physUvBD.buffer, &memReqs[index]); + grBinds.physUvBD.bindingCount = uv.Count(); + grBinds.physUvBD.firstBinding = index; // index - uint32_t offsetIndex = runningOffset; - uint32_t sizeIndex = accIndex.buffer_view->size; - alignmentPadding = sizeIndex % combinedMemReqs.alignment; - alignmentPadding = alignmentPadding == 0 ? 0 : combinedMemReqs.alignment - alignmentPadding; - sizeIndex += alignmentPadding; - bufferCI.size = sizeIndex; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.indexBuffer); - vkBindBufferMemory(vkDevice, grBinds.indexBuffer, et.deviceMemoryVert, offsetIndex); - runningOffset += sizeIndex; - - assert(runningOffset == combinedMemReqs.size); - const Asset *modelBinAsset = AM_Get(modelBinHandle); + index = 3; + physBufferCI[index].size = sizeof(uint16_t) * indexes.Count(); + physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physIndxBD.buffer); + vkGetBufferMemoryRequirements(vkDevice, grBinds.physIndxBD.buffer, &memReqs[index]); + grBinds.physIndxBD.bindingCount = indexes.Count(); + // grBinds.physIndxBD.firstBinding = index; + + CalculateCombinedMemReqs(4, memReqs, combinedMemReqs); + + // vert + index = 0; + if (memReqs[index].size != physBufferCI[index].size) { + vkDestroyBuffer(vkDevice, grBinds.physVertBD.buffer, vkAllocator); + physBufferCI[index].size = memReqs[index].size; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physVertBD.buffer); + } + // norm + index = 1; + if (memReqs[index].size != physBufferCI[index].size) { + vkDestroyBuffer(vkDevice, grBinds.physNormBD.buffer, vkAllocator); + physBufferCI[index].size = memReqs[index].size; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physNormBD.buffer); + } + // uv + index = 2; + if (memReqs[index].size != physBufferCI[index].size) { + vkDestroyBuffer(vkDevice, grBinds.physUvBD.buffer, vkAllocator); + physBufferCI[index].size = memReqs[index].size; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physUvBD.buffer); + } + // index + index = 3; + if (memReqs[index].size != physBufferCI[index].size) { + vkDestroyBuffer(vkDevice, grBinds.physIndxBD.buffer, vkAllocator); + physBufferCI[index].size = memReqs[index].size; + vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physIndxBD.buffer); + } + + // allocate memory + VkMemoryAllocateInfo physVertMemAI; + physVertMemAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + physVertMemAI.pNext = nullptr; + physVertMemAI.allocationSize = combinedMemReqs.size; + physVertMemAI.memoryTypeIndex = combinedMemReqs.memoryTypeBits; + physVertMemAI.memoryTypeIndex = FindMemoryTypeIndex(combinedMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vkAllocateMemory(vkDevice, &physVertMemAI, vkAllocator, &et.deviceMemoryPhysVert); + + runningOffset = 0; + vkBindBufferMemory(vkDevice, grBinds.physVertBD.buffer, et.deviceMemoryPhysVert, runningOffset); + runningOffset += memReqs[0].size; + vkBindBufferMemory(vkDevice, grBinds.physNormBD.buffer, et.deviceMemoryPhysVert, runningOffset); + runningOffset += memReqs[1].size; + vkBindBufferMemory(vkDevice, grBinds.physUvBD.buffer, et.deviceMemoryPhysVert, runningOffset); + runningOffset += memReqs[2].size; + vkBindBufferMemory(vkDevice, grBinds.physIndxBD.buffer, et.deviceMemoryPhysVert, runningOffset); // create transfer items && transfer { @@ -553,25 +785,29 @@ void EntityType_Load(EntityType &et) { void *data; BeginTransferBuffer(combinedMemReqs.size, transferBuffer, transferDeviceMemory, data); memset(data, '\0', combinedMemReqs.size); + runningOffset = 0; char *dstPtr = nullptr; char *srcPtr = nullptr; - dstPtr = static_cast<char *>(data) + offsetVert; - srcPtr = static_cast<char *>(modelBinAsset->ptr) + accVert.buffer_view->offset; - memcpy(dstPtr, srcPtr, accVert.buffer_view->size); + dstPtr = static_cast<char *>(data) + runningOffset; + srcPtr = reinterpret_cast<char *>(vertexes.GetPtr()); + memcpy(dstPtr, srcPtr, sizeof(glm::vec3) * vertexes.Count()); + runningOffset += memReqs[0].size; - dstPtr = static_cast<char *>(data) + offsetNorm; - srcPtr = static_cast<char *>(modelBinAsset->ptr) + accNorm.buffer_view->offset; - memcpy(dstPtr, srcPtr, accNorm.buffer_view->size); + dstPtr = static_cast<char *>(data) + runningOffset; + srcPtr = reinterpret_cast<char *>(normals.GetPtr()); + memcpy(dstPtr, srcPtr, sizeof(glm::vec3) * normals.Count()); + runningOffset += memReqs[1].size; - dstPtr = static_cast<char *>(data) + offsetUV; - srcPtr = static_cast<char *>(modelBinAsset->ptr) + accUV.buffer_view->offset; - memcpy(dstPtr, srcPtr, accUV.buffer_view->size); + dstPtr = static_cast<char *>(data) + runningOffset; + srcPtr = reinterpret_cast<char *>(uv.GetPtr()); + memcpy(dstPtr, srcPtr, sizeof(glm::vec2) * uv.Count()); + runningOffset += memReqs[2].size; - dstPtr = static_cast<char *>(data) + offsetIndex; - srcPtr = static_cast<char *>(modelBinAsset->ptr) + accIndex.buffer_view->offset; - memcpy(dstPtr, srcPtr, accIndex.buffer_view->size); + dstPtr = static_cast<char *>(data) + runningOffset; + srcPtr = reinterpret_cast<char *>(indexes.GetPtr()); + memcpy(dstPtr, srcPtr, sizeof(uint16_t) * indexes.Count()); VkCommandBufferBeginInfo vkCommandBufferBeginInfo; vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -585,24 +821,29 @@ void EntityType_Load(EntityType &et) { bufferCopys[i].dstOffset = 0; } index = 0; - bufferCopys[index].srcOffset = offsetVert; - bufferCopys[index].size = sizeVert; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.vertexBuffer, 1, &bufferCopys[index]); + runningOffset = 0; + bufferCopys[index].srcOffset = runningOffset; + bufferCopys[index].size = memReqs[index].size; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physVertBD.buffer, 1, &bufferCopys[index]); + runningOffset += memReqs[index].size; index+=1; - bufferCopys[index].srcOffset = offsetNorm; - bufferCopys[index].size = sizeNorm; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.normalsBuffer, 1, &bufferCopys[index]); + bufferCopys[index].srcOffset = runningOffset; + bufferCopys[index].size = memReqs[index].size; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physNormBD.buffer, 1, &bufferCopys[index]); + runningOffset += memReqs[index].size; index+=1; - bufferCopys[index].srcOffset = offsetUV; - bufferCopys[index].size = sizeUV; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.uvBuffer, 1, &bufferCopys[index]); + bufferCopys[index].srcOffset = runningOffset; + bufferCopys[index].size = memReqs[index].size; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physUvBD.buffer, 1, &bufferCopys[index]); + runningOffset += memReqs[index].size; index+=1; - bufferCopys[index].srcOffset = offsetIndex; - bufferCopys[index].size = sizeIndex; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.indexBuffer, 1, &bufferCopys[index]); + bufferCopys[index].srcOffset = runningOffset; + bufferCopys[index].size = memReqs[index].size; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physIndxBD.buffer, 1, &bufferCopys[index]); + // runningOffset += memReqs[index].size; // index+=1; vkEndCommandBuffer(transferCommandBuffer); @@ -622,249 +863,11 @@ void EntityType_Load(EntityType &et) { EndTransferBuffer(transferBuffer, transferDeviceMemory); } - - // set up instance buffer - grBinds.instanceBufferMaxCount = et.startingInstanceCount; - grBinds.instanceBufferMaxCount = grBinds.instanceBufferMaxCount < 1 ? 1 : grBinds.instanceBufferMaxCount; - bufferCI.size = sizeof(glm::mat4) * grBinds.instanceBufferMaxCount; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.instanceBuffer); - VkMemoryRequirements vkMemoryRequirementsInst; - vkGetBufferMemoryRequirements(vkDevice, grBinds.instanceBuffer, &vkMemoryRequirementsInst); - vkMemoryAllocateInfo.allocationSize = vkMemoryRequirementsInst.size; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemoryRequirementsInst.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryInst); - vkBindBufferMemory(vkDevice, grBinds.instanceBuffer, et.deviceMemoryInst, 0); - - // bullet - btConvexHullShape *shape; - { - shape = Pke_New<btConvexHullShape>(MemBkt_Bullet); - btScalar *vertDataPointer = reinterpret_cast<btScalar *>(modelBinAsset->ptr); - vertDataPointer += accVert.buffer_view->offset; - new (shape) btConvexHullShape(vertDataPointer, accVert.count, accVert.stride); - shape->optimizeConvexHull(); - shape->initializePolyhedralFeatures(); - et.bt.shape = shape; - } - assert(shape != nullptr); - - modelBinAsset = CAFE_BABE(Asset); - AM_Release(modelBinHandle); - - // set up convex hull debug - { - const btConvexPolyhedron *pol = shape->getConvexPolyhedron(); - DynArray<glm::vec3> vertexes{pol->m_vertices.size(), MemBkt_Bullet}; - DynArray<glm::vec3> normals{pol->m_vertices.size(), MemBkt_Bullet}; - DynArray<glm::vec2> uv{pol->m_vertices.size(), MemBkt_Bullet}; - DynArray<uint16_t> indexes{pol->m_faces.size() * 6, MemBkt_Bullet}; - for (long i = 0; i < pol->m_vertices.size(); ++i) { - btVector3 norm = pol->m_vertices[i]; - auto &glmVert = vertexes.Push(); - BulletToGlm(norm, glmVert); - norm.safeNormalize(); - auto &glmNorm = normals.Push(); - BulletToGlm(norm, glmNorm); - uv.Push({norm.x(), norm.y()}); - } - for (long i = 0; i < pol->m_faces.size(); ++i) { - for (long k = 2; k < pol->m_faces[i].m_indices.size(); ++k) { - indexes.Push(pol->m_faces[i].m_indices[0]); - indexes.Push(pol->m_faces[i].m_indices[k - 1]); - indexes.Push(pol->m_faces[i].m_indices[k]); - } - } - - VkBufferCreateInfo physBufferCI[4]; - for (long i = 0; i < 4; ++i) { - physBufferCI[i].sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - physBufferCI[i].pNext = nullptr; - physBufferCI[i].flags = {}; - physBufferCI[i].sharingMode = VK_SHARING_MODE_EXCLUSIVE; - physBufferCI[i].queueFamilyIndexCount = 1; - physBufferCI[i].pQueueFamilyIndices = &graphicsFamilyIndex; - } - - VkMemoryRequirements memReqs[4]; - - // vertex - index = 0; - physBufferCI[index].size = sizeof(glm::vec3) * vertexes.Count(); - physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physVertBD.buffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.physVertBD.buffer, &memReqs[index]); - grBinds.physVertBD.bindingCount = vertexes.Count(); - grBinds.physVertBD.firstBinding = index; - - // norm - index = 1; - physBufferCI[index].size = sizeof(glm::vec3) * normals.Count(); - physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physNormBD.buffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.physNormBD.buffer, &memReqs[index]); - grBinds.physNormBD.bindingCount = normals.Count(); - grBinds.physNormBD.firstBinding = index; - - // uv - index = 2; - physBufferCI[index].size = sizeof(glm::vec2) * uv.Count(); - physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physUvBD.buffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.physUvBD.buffer, &memReqs[index]); - grBinds.physUvBD.bindingCount = uv.Count(); - grBinds.physUvBD.firstBinding = index; - - // index - index = 3; - physBufferCI[index].size = sizeof(uint16_t) * indexes.Count(); - physBufferCI[index].usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physIndxBD.buffer); - vkGetBufferMemoryRequirements(vkDevice, grBinds.physIndxBD.buffer, &memReqs[index]); - grBinds.physIndxBD.bindingCount = indexes.Count(); - // grBinds.physIndxBD.firstBinding = index; - - CalculateCombinedMemReqs(4, memReqs, combinedMemReqs); - - // vert - index = 0; - if (memReqs[index].size != physBufferCI[index].size) { - vkDestroyBuffer(vkDevice, grBinds.physVertBD.buffer, vkAllocator); - physBufferCI[index].size = memReqs[index].size; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physVertBD.buffer); - } - // norm - index = 1; - if (memReqs[index].size != physBufferCI[index].size) { - vkDestroyBuffer(vkDevice, grBinds.physNormBD.buffer, vkAllocator); - physBufferCI[index].size = memReqs[index].size; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physNormBD.buffer); - } - // uv - index = 2; - if (memReqs[index].size != physBufferCI[index].size) { - vkDestroyBuffer(vkDevice, grBinds.physUvBD.buffer, vkAllocator); - physBufferCI[index].size = memReqs[index].size; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physUvBD.buffer); - } - // index - index = 3; - if (memReqs[index].size != physBufferCI[index].size) { - vkDestroyBuffer(vkDevice, grBinds.physIndxBD.buffer, vkAllocator); - physBufferCI[index].size = memReqs[index].size; - vkCreateBuffer(vkDevice, &physBufferCI[index], vkAllocator, &grBinds.physIndxBD.buffer); - } - - // allocate memory - VkMemoryAllocateInfo physVertMemAI; - physVertMemAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - physVertMemAI.pNext = nullptr; - physVertMemAI.allocationSize = combinedMemReqs.size; - physVertMemAI.memoryTypeIndex = combinedMemReqs.memoryTypeBits; - physVertMemAI.memoryTypeIndex = FindMemoryTypeIndex(combinedMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - vkAllocateMemory(vkDevice, &physVertMemAI, vkAllocator, &et.deviceMemoryPhysVert); - - runningOffset = 0; - vkBindBufferMemory(vkDevice, grBinds.physVertBD.buffer, et.deviceMemoryPhysVert, runningOffset); - runningOffset += memReqs[0].size; - vkBindBufferMemory(vkDevice, grBinds.physNormBD.buffer, et.deviceMemoryPhysVert, runningOffset); - runningOffset += memReqs[1].size; - vkBindBufferMemory(vkDevice, grBinds.physUvBD.buffer, et.deviceMemoryPhysVert, runningOffset); - runningOffset += memReqs[2].size; - vkBindBufferMemory(vkDevice, grBinds.physIndxBD.buffer, et.deviceMemoryPhysVert, runningOffset); - - // create transfer items && transfer - { - VkDeviceMemory transferDeviceMemory; - VkBuffer transferBuffer; - void *data; - BeginTransferBuffer(combinedMemReqs.size, transferBuffer, transferDeviceMemory, data); - memset(data, '\0', combinedMemReqs.size); - runningOffset = 0; - - char *dstPtr = nullptr; - char *srcPtr = nullptr; - - dstPtr = static_cast<char *>(data) + runningOffset; - srcPtr = reinterpret_cast<char *>(vertexes.GetPtr()); - memcpy(dstPtr, srcPtr, sizeof(glm::vec3) * vertexes.Count()); - runningOffset += memReqs[0].size; - - dstPtr = static_cast<char *>(data) + runningOffset; - srcPtr = reinterpret_cast<char *>(normals.GetPtr()); - memcpy(dstPtr, srcPtr, sizeof(glm::vec3) * normals.Count()); - runningOffset += memReqs[1].size; - - dstPtr = static_cast<char *>(data) + runningOffset; - srcPtr = reinterpret_cast<char *>(uv.GetPtr()); - memcpy(dstPtr, srcPtr, sizeof(glm::vec2) * uv.Count()); - runningOffset += memReqs[2].size; - - dstPtr = static_cast<char *>(data) + runningOffset; - srcPtr = reinterpret_cast<char *>(indexes.GetPtr()); - memcpy(dstPtr, srcPtr, sizeof(uint16_t) * indexes.Count()); - - VkCommandBufferBeginInfo vkCommandBufferBeginInfo; - vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkCommandBufferBeginInfo.pNext = nullptr; - // TODO consider single-use? - vkCommandBufferBeginInfo.flags = 0; - vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; - vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo); - VkBufferCopy bufferCopys[expectedBufferCount]; - for (long i = 0; i < expectedBufferCount; ++i) { - bufferCopys[i].dstOffset = 0; - } - index = 0; - runningOffset = 0; - bufferCopys[index].srcOffset = runningOffset; - bufferCopys[index].size = memReqs[index].size; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physVertBD.buffer, 1, &bufferCopys[index]); - runningOffset += memReqs[index].size; - index+=1; - - bufferCopys[index].srcOffset = runningOffset; - bufferCopys[index].size = memReqs[index].size; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physNormBD.buffer, 1, &bufferCopys[index]); - runningOffset += memReqs[index].size; - index+=1; - - bufferCopys[index].srcOffset = runningOffset; - bufferCopys[index].size = memReqs[index].size; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physUvBD.buffer, 1, &bufferCopys[index]); - runningOffset += memReqs[index].size; - index+=1; - - bufferCopys[index].srcOffset = runningOffset; - bufferCopys[index].size = memReqs[index].size; - vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.physIndxBD.buffer, 1, &bufferCopys[index]); - // runningOffset += memReqs[index].size; - // index+=1; - - vkEndCommandBuffer(transferCommandBuffer); - - VkSubmitInfo submitInfo; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.waitSemaphoreCount = 0; - submitInfo.pWaitSemaphores = nullptr; - submitInfo.pWaitDstStageMask = nullptr; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &transferCommandBuffer; - submitInfo.signalSemaphoreCount = 0; - submitInfo.pSignalSemaphores = nullptr; - vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); - vkQueueWaitIdle(transferQueue); - - EndTransferBuffer(transferBuffer, transferDeviceMemory); - } - } - - // cleanup - // cgltf_free(gltfData); - AM_Release(assetHandle); } + + // cleanup + // cgltf_free(gltfData); + AM_Release(assetHandle); } void EntityType_Tick_Late(double delta) { |
