129 if (
imageData.uri.empty())
throw std::runtime_error(
"Cannot create resources for a texture with no contents");
132 std::stringstream tracyZoneName;
133 tracyZoneName << __FUNCTION__ <<
": " <<
imageData.uri;
135 ZoneName(tracyZoneName.str().c_str(), tracyZoneName.str().size());
139 VkImageCreateInfo imageInfo{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
140 imageInfo.imageType = VK_IMAGE_TYPE_2D;
141 imageInfo.extent.width =
imageData.width;
142 imageInfo.extent.height =
imageData.height;
143 imageInfo.extent.depth = 1;
144 imageInfo.mipLevels = 1;
145 imageInfo.arrayLayers = 1;
146 imageInfo.format =
format;
147 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
148 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
149 imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
150 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
151 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
154 VmaAllocationCreateInfo allocCI{};
155 allocCI.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
157 VmaAllocator allocator =
context->getVmaAllocator();
160 throw std::runtime_error(
"Failed to create texture image with VMA: " +
imageData.uri);
164 VkImageViewCreateInfo viewInfo{};
165 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
167 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
169 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
170 viewInfo.subresourceRange.baseMipLevel = 0;
171 viewInfo.subresourceRange.levelCount = 1;
172 viewInfo.subresourceRange.baseArrayLayer = 0;
173 viewInfo.subresourceRange.layerCount = 1;
177 throw std::runtime_error(
"failed to create texture image view!");
181 VkSamplerCreateInfo samplerCreateInfo{};
182 samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
183 samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
184 samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
185 samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
186 samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
187 samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
188 samplerCreateInfo.anisotropyEnable = VK_TRUE;
189 samplerCreateInfo.maxAnisotropy = 16.0f;
190 samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
191 samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
192 samplerCreateInfo.compareEnable = VK_FALSE;
193 samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS;
194 samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
195 samplerCreateInfo.mipLodBias = 0.0f;
196 samplerCreateInfo.minLod = 0.0f;
197 samplerCreateInfo.maxLod = 0.0f;
201 throw std::runtime_error(
"failed to create texture sampler!");
286 assert(imageDataSize ==
imageData.image.size() &&
"Calculated image data size mismatch with tinygltf::Image::image vector size!");
288 if(imageDataSize == 0)
290 PLOGE <<
"Image data size of " <<
imageData.uri <<
" is zero!";
298 stagingBuffer.
create(imageDataSize,
299 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
300 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
301 std::string bufferName =
"Image upload staging buffer for " +
imageData.uri;
305 void* mappedData = stagingBuffer.
map();
308 memcpy(mappedData,
imageData.image.data(),
static_cast<size_t>(
imageData.image.size()));
309 stagingBuffer.
unmap();
312 VkImageMemoryBarrier2 imageMemoryBarrier1{};
313 imageMemoryBarrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
314 imageMemoryBarrier1.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
315 imageMemoryBarrier1.srcAccessMask = VK_ACCESS_2_NONE;
316 imageMemoryBarrier1.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
317 imageMemoryBarrier1.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
318 imageMemoryBarrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
319 imageMemoryBarrier1.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
320 imageMemoryBarrier1.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
321 imageMemoryBarrier1.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
323 imageMemoryBarrier1.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
324 imageMemoryBarrier1.subresourceRange.baseMipLevel = 0;
325 imageMemoryBarrier1.subresourceRange.levelCount = 1;
326 imageMemoryBarrier1.subresourceRange.baseArrayLayer = 0;
327 imageMemoryBarrier1.subresourceRange.layerCount = 1;
329 VkDependencyInfo dependencyInfo1{VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
330 dependencyInfo1.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
331 dependencyInfo1.pImageMemoryBarriers = &imageMemoryBarrier1;
332 dependencyInfo1.imageMemoryBarrierCount = 1;
333 vkCmdPipelineBarrier2(commandBuffer, &dependencyInfo1);
335 VkBufferImageCopy region{};
336 region.bufferOffset = 0;
337 region.bufferRowLength = 0;
338 region.bufferImageHeight = 0;
339 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
340 region.imageSubresource.mipLevel = 0;
341 region.imageSubresource.baseArrayLayer = 0;
342 region.imageSubresource.layerCount = 1;
343 region.imageOffset = {0, 0, 0};
344 region.imageExtent = {
static_cast<uint32_t
>(
imageData.width),
static_cast<uint32_t
>(
imageData.height), 1};
347 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
351 VkImageMemoryBarrier2 imageMemoryBarrier2{};
352 imageMemoryBarrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
353 imageMemoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT;
354 imageMemoryBarrier2.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
355 imageMemoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
356 imageMemoryBarrier2.dstAccessMask = VK_ACCESS_2_NONE;
357 imageMemoryBarrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
358 imageMemoryBarrier2.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
359 imageMemoryBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
360 imageMemoryBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
362 imageMemoryBarrier2.subresourceRange = imageMemoryBarrier1.subresourceRange;
364 VkDependencyInfo dependencyInfo2{VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
365 dependencyInfo2.imageMemoryBarrierCount = 1;
366 dependencyInfo2.pImageMemoryBarriers = &imageMemoryBarrier2;
367 vkCmdPipelineBarrier2(commandBuffer, &dependencyInfo2);
373 PLOGE <<
"Failed to map staging buffer memory for texture " <<
imageData.uri;
The application context is the core class which stores the basic openxr and vulkan objects.
VmaAllocation textureAllocation_
VMA allocation for texture memory.
VkDeviceMemory getVkImageMemory() const
void setupImageFormat(const tinygltf::Image &imageData)
tinygltf::Image imageData
Texture & operator=(const Texture &)=delete
void setDebugName(const std::string &debugName)
VkSampler getVkImageSampler() const
static std::string createTexturePath(const std::filesystem::path &assetPath, const GltfLoader::GltfMeshPrimitiveData &primitiveData)
bool isDescriptorIndexInitialized() const
VkImage getVkImage() const
VkImageView getVkImageView() const
void createDataUploadCommand(VkCommandBuffer commandBuffer, Renderer *renderer) const
uint32_t getDescriptorIndex() const
VkFormat getTextureFormat() const
ApplicationContext * context