Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Texture3D::loadFromBuffer(Device &device, const void *buffer, VkDeviceSize instanceSize, uint32_t width,
- uint32_t height, uint32_t channels, uint32_t depth, VkFormat format,
- VkImageLayout imageLayout) {
- this->width = width;
- this->height = height;
- this->depth = depth;
- this->channels = channels;
- this->layout = imageLayout;
- // Format support check
- // 3D texture support in Vulkan is mandatory so there is no need to check if it is supported
- VkFormatProperties formatProperties;
- vkGetPhysicalDeviceFormatProperties(device.getPhysicalDevice(), format, &formatProperties);
- // Check if format supports transfer
- if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
- Logger::log(LOG_LEVEL_ERROR,
- "Error: Device does not support flag TRANSFER_DST for selected texture format!\n");
- throw std::runtime_error("Error: Device does not support flag TRANSFER_DST for selected!");
- }
- // Check if GPU supports requested 3D texture dimensions
- uint32_t maxImageDimension3D(device.properties.limits.maxImageDimension3D);
- if (width > maxImageDimension3D || height > maxImageDimension3D || depth > maxImageDimension3D) {
- Logger::log(LOG_LEVEL_ERROR,
- "Error: Requested texture dimensions is greater than supported 3D texture dimension!\n");
- throw std::runtime_error("Error: Requested texture dimensions is greater than supported 3D texture dimension!");
- }
- // Calculate aligned dimensions based on device properties
- VkDeviceSize alignedRowPitch = (width * instanceSize +
- device.properties.limits.optimalBufferCopyRowPitchAlignment - 1) &
- ~(device.properties.limits.optimalBufferCopyRowPitchAlignment - 1);
- VkDeviceSize alignedSlicePitch = alignedRowPitch * height;
- VkDeviceSize totalSize = alignedSlicePitch * depth;
- VkImageCreateInfo imageCreateInfo = Init::imageCreateInfo();
- imageCreateInfo.imageType = VK_IMAGE_TYPE_3D;
- imageCreateInfo.format = format;
- imageCreateInfo.mipLevels = this->mipLevels;
- imageCreateInfo.arrayLayers = 1;
- imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageCreateInfo.extent.width = this->width;
- imageCreateInfo.extent.height = this->height;
- imageCreateInfo.extent.depth = this->depth;
- // Set initial layout of the image to undefined
- imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
- checkResult(vkCreateImage(device.device(), &imageCreateInfo, nullptr, &this->image));
- // Device local memory to back up image
- VkMemoryAllocateInfo memAllocInfo = Init::memoryAllocateInfo();
- VkMemoryRequirements memReqs = {};
- vkGetImageMemoryRequirements(device.device(), this->image, &memReqs);
- memAllocInfo.allocationSize = memReqs.size;
- memAllocInfo.memoryTypeIndex = device.findMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- checkResult(vkAllocateMemory(device.device(), &memAllocInfo, nullptr, &this->memory));
- checkResult(vkBindImageMemory(device.device(), this->image, this->memory, 0));
- // Create a host-visible staging buffer that contains the raw image data
- Buffer stagingBuffer{
- device,
- instanceSize, // Size of each element (4 bytes for float)
- totalSize, // Total size including padding
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
- };
- stagingBuffer.map();
- // Copy data slice by slice with proper alignment
- const float* srcData = static_cast<const float*>(buffer);
- float* dstData = static_cast<float*>(stagingBuffer.getMappedMemory());
- // Calculate pitches in bytes
- VkDeviceSize unalignedRowPitch = width * sizeof(float);
- VkDeviceSize unalignedSlicePitch = unalignedRowPitch * height;
- // Debug prints
- Logger::log(LOG_LEVEL_DEBUG, "Width: %d, Height: %d, Depth: %d\n", width, height, depth);
- Logger::log(LOG_LEVEL_DEBUG, "Unaligned row pitch: %zu bytes\n", unalignedRowPitch);
- Logger::log(LOG_LEVEL_DEBUG, "Aligned row pitch: %zu bytes\n", alignedRowPitch);
- Logger::log(LOG_LEVEL_DEBUG, "Aligned slice pitch: %zu bytes\n", alignedSlicePitch);
- Logger::log(LOG_LEVEL_DEBUG, "Unligned slice pitch: %zu bytes\n", alignedSlicePitch);
- for (uint32_t z = 0; z < depth; z++) {
- for (uint32_t y = 0; y < height; y++) {
- const float* srcRow = srcData + (z * height * width) + (y * width);
- float* dstRow = dstData + (z * alignedSlicePitch / sizeof(float)) +
- (y * alignedRowPitch / sizeof(float));
- // Copy one row of floats
- memcpy(dstRow, srcRow, unalignedRowPitch);
- }
- }
- stagingBuffer.unmap();
- // Setup buffer copy regions with proper alignment
- VkBufferImageCopy copyRegion{};
- copyRegion.bufferOffset = 0;
- copyRegion.bufferRowLength = alignedRowPitch / instanceSize; // In texels
- copyRegion.bufferImageHeight = height;
- copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyRegion.imageSubresource.mipLevel = 0;
- copyRegion.imageSubresource.baseArrayLayer = 0;
- copyRegion.imageSubresource.layerCount = 1;
- copyRegion.imageExtent = {width, height, depth};
- // Transition the texture image layout to transfer destination
- device.transitionImageLayout(
- this->image,
- VK_IMAGE_LAYOUT_UNDEFINED,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
- );
- // Copy the data from the staging buffer to the texture image
- VkCommandBuffer cmdBuffer = device.beginSingleTimeCommands();
- vkCmdCopyBufferToImage(
- cmdBuffer,
- stagingBuffer.getBuffer(),
- image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- ©Region
- );
- device.endSingleTimeCommands(cmdBuffer);
- // Transition the texture image layout to shader read after copying the data
- device.transitionImageLayout(
- this->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- imageLayout
- );
- // create image view
- VkImageViewCreateInfo view = Init::imageViewCreateInfo();
- view.image = this->image;
- view.viewType = VK_IMAGE_VIEW_TYPE_3D;
- view.format = format;
- view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- view.subresourceRange.baseMipLevel = 0;
- view.subresourceRange.baseArrayLayer = 0;
- view.subresourceRange.layerCount = 1;
- view.subresourceRange.levelCount = 1;
- checkResult(vkCreateImageView(device.device(), &view, nullptr, &this->view));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement