VkBool32 Example::destroyTexture(vkts::IImageSP& currentImage, vkts::IDeviceMemorySP& currentDeviceMemoryImage) const { if (currentImage.get()) { currentImage->destroy(); currentDeviceMemoryImage->destroy(); } return VK_TRUE; }
VkBool32 Example::createTexture(vkts::IImageSP& currentImage, vkts::IDeviceMemorySP& currentDeviceMemoryImage, const VkImageTiling imageTiling, const VkImageUsageFlags usage, const VkImageLayout initialLayout, const VkMemoryPropertyFlags memoryPropertyFlagBits, const VkAccessFlags accessMask) const { VkResult result; // VkExtent3D extent = {VKTS_IMAGE_LENGTH, VKTS_IMAGE_LENGTH, 1}; currentImage = vkts::imageCreate(device->getDevice(), 0, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, extent, 1, 1, VK_SAMPLE_COUNT_1_BIT, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, initialLayout, accessMask); if (!currentImage.get()) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not create image."); return VK_FALSE; } // VkMemoryRequirements memoryRequirements; currentImage->getImageMemoryRequirements(memoryRequirements); // VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; physicalDevice->getPhysicalDeviceMemoryProperties(physicalDeviceMemoryProperties); currentDeviceMemoryImage = vkts::deviceMemoryCreate(device->getDevice(), memoryRequirements, VK_MAX_MEMORY_TYPES, physicalDeviceMemoryProperties.memoryTypes, memoryPropertyFlagBits); if (!currentDeviceMemoryImage.get()) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not allocate memory."); return VK_FALSE; } // Bind image to memory. result = vkBindImageMemory(device->getDevice(), currentImage->getImage(), currentDeviceMemoryImage->getDeviceMemory(), 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not bind image memory."); return VK_FALSE; } return VK_TRUE; }
VkBool32 Example::createTexture(vkts::IImageSP& currentImage, vkts::IDeviceMemorySP& currentDeviceMemoryImage, const vkts::IImageDataSP& imageData, const VkImageTiling imageTiling, const VkImageUsageFlags usage, const VkImageLayout initialLayout, const VkMemoryPropertyFlags memoryPropertyFlagBits, const VkAccessFlags accessMask) const { VkResult result; // currentImage = vkts::imageCreate(device->getDevice(), 0, imageData->getImageType(), imageData->getFormat(), imageData->getExtent3D(), 1, 1, VK_SAMPLE_COUNT_1_BIT, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, initialLayout, accessMask); if (!currentImage.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create image."); return VK_FALSE; } // VkMemoryRequirements memoryRequirements; currentImage->getImageMemoryRequirements(memoryRequirements); // VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; physicalDevice->getPhysicalDeviceMemoryProperties(physicalDeviceMemoryProperties); currentDeviceMemoryImage = vkts::deviceMemoryCreate(device->getDevice(), memoryRequirements, VK_MAX_MEMORY_TYPES, physicalDeviceMemoryProperties.memoryTypes, memoryPropertyFlagBits); if (!currentDeviceMemoryImage.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not allocate memory."); return VK_FALSE; } // Bind image to memory. result = vkBindImageMemory(device->getDevice(), currentImage->getImage(), currentDeviceMemoryImage->getDeviceMemory(), 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not bind image memory."); return VK_FALSE; } // Upload data if host visible. if (memoryPropertyFlagBits & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { VkImageSubresource imageSubresource; imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageSubresource.mipLevel = 0; imageSubresource.arrayLayer = 0; VkSubresourceLayout subresourceLayout; currentImage->getImageSubresourceLayout(subresourceLayout, imageSubresource); result = currentDeviceMemoryImage->mapMemory(0, memoryRequirements.size, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not map memory."); return VK_FALSE; } imageData->copy(currentDeviceMemoryImage->getMemory(), 0, subresourceLayout); currentDeviceMemoryImage->unmapMemory(); } return VK_TRUE; }
VkBool32 Example::buildTexture(const vkts::ICommandBuffersSP& cmdBuffer, vkts::IImageSP& stageImage, vkts::IDeviceMemorySP& stageDeviceMemoryImage) { auto imageData = vkts::imageDataLoad(VKTS_TEXTURE_NAME); if (!imageData.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not load image data: '%s'", VKTS_TEXTURE_NAME); return VK_FALSE; } // VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(physicalDevice->getPhysicalDevice(), imageData->getFormat(), &formatProperties); VkImageTiling imageTiling = VK_IMAGE_TILING_LINEAR; VkMemoryPropertyFlagBits memoryPropertyFlagBits = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; VkImageLayout initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; VkAccessFlags accessMask = VK_ACCESS_HOST_WRITE_BIT; // Check, how to upload image data. if (!(formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Format not supported."); return VK_FALSE; } imageTiling = VK_IMAGE_TILING_OPTIMAL; memoryPropertyFlagBits = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; initialLayout = VK_IMAGE_LAYOUT_GENERAL; accessMask = 0; } // if (!createTexture(image, deviceMemoryImage, imageData, imageTiling, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, initialLayout, memoryPropertyFlagBits, accessMask)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create image."); return VK_FALSE; } // VkImageMemoryBarrier imageMemoryBarrier; memset(&imageMemoryBarrier, 0, sizeof(VkImageMemoryBarrier)); imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.srcAccessMask = 0; // Defined later. imageMemoryBarrier.dstAccessMask = 0; // Defined later. imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;// Defined later. imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;// Defined later. imageMemoryBarrier.srcQueueFamilyIndex = 0; imageMemoryBarrier.dstQueueFamilyIndex = 0; imageMemoryBarrier.image = VK_NULL_HANDLE; // Defined later. imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; // imageMemoryBarrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageMemoryBarrier.image = image->getImage(); cmdBuffer->cmdPipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); // // If the image is only accessible by the device ... if (memoryPropertyFlagBits == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { // ... create texture with host visibility. This texture contains the pixel data. if (!createTexture(stageImage, stageDeviceMemoryImage, imageData, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_ACCESS_HOST_WRITE_BIT)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create image."); return VK_FALSE; } // Prepare source image layout for copy. imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; imageMemoryBarrier.image = stageImage->getImage(); cmdBuffer->cmdPipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); // Prepare target image layout for copy. imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; imageMemoryBarrier.image = image->getImage(); cmdBuffer->cmdPipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); // Copy image data by command. VkImageCopy imageCopy; imageCopy.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; imageCopy.srcOffset = { 0, 0, 0}; imageCopy.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; imageCopy.dstOffset = { 0, 0, 0}; imageCopy.extent = { imageData->getWidth(), imageData->getHeight(), imageData->getDepth()}; vkCmdCopyImage(cmdBuffer->getCommandBuffer(), stageImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy); // Switch back to original layout. imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; cmdBuffer->cmdPipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); } // sampler = vkts::samplerCreate(device->getDevice(), 0, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, 0.0f, VK_FALSE, 1.0f, VK_FALSE, VK_COMPARE_OP_NEVER, 0.0f, 0.0f, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, VK_FALSE); if (!sampler.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create sampler."); return VK_FALSE; } imageView = vkts::imageViewCreate(device->getDevice(), 0, image->getImage(), VK_IMAGE_VIEW_TYPE_2D, image->getFormat(), { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); if (!imageView.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create image view."); return VK_FALSE; } return VK_TRUE; }