void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels) { auto fb = GetVulkanFrameBuffer(); int totalSize = w * h * pixelsize; BufferBuilder bufbuilder; bufbuilder.setSize(totalSize); bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); std::unique_ptr<VulkanBuffer> stagingBuffer = bufbuilder.create(fb->device); stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer"); uint8_t *data = (uint8_t*)stagingBuffer->Map(0, totalSize); memcpy(data, pixels, totalSize); stagingBuffer->Unmap(); ImageBuilder imgbuilder; imgbuilder.setFormat(format); imgbuilder.setSize(w, h, GetMipLevels(w, h)); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); mImage.Image = imgbuilder.create(fb->device); mImage.Image->SetDebugName("VkHardwareTexture.mImage"); ImageViewBuilder viewbuilder; viewbuilder.setImage(mImage.Image.get(), format); mImage.View = viewbuilder.create(fb->device); mImage.View->SetDebugName("VkHardwareTexture.mImageView"); auto cmdbuffer = fb->GetTransferCommands(); VkImageTransition imageTransition; imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); imageTransition.execute(cmdbuffer); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; region.imageExtent.depth = 1; region.imageExtent.width = w; region.imageExtent.height = h; cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer)); mImage.GenerateMipmaps(cmdbuffer); }
VkPPTexture::VkPPTexture(PPTexture *texture) { auto fb = GetVulkanFrameBuffer(); VkFormat format; int pixelsize; switch (texture->Format) { default: case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break; case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break; case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break; case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break; case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break; } ImageBuilder imgbuilder; imgbuilder.setFormat(format); imgbuilder.setSize(texture->Width, texture->Height); if (texture->Data) imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); else imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); if (!imgbuilder.isFormatSupported(fb->device)) I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n"); TexImage.Image = imgbuilder.create(fb->device); TexImage.Image->SetDebugName("VkPPTexture"); Format = format; ImageViewBuilder viewbuilder; viewbuilder.setImage(TexImage.Image.get(), format); TexImage.View = viewbuilder.create(fb->device); TexImage.View->SetDebugName("VkPPTextureView"); if (texture->Data) { size_t totalsize = texture->Width * texture->Height * pixelsize; BufferBuilder stagingbuilder; stagingbuilder.setSize(totalsize); stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); Staging = stagingbuilder.create(fb->device); Staging->SetDebugName("VkPPTextureStaging"); VkImageTransition barrier0; barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); barrier0.execute(fb->GetTransferCommands()); void *data = Staging->Map(0, totalsize); memcpy(data, texture->Data.get(), totalsize); Staging->Unmap(); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; region.imageExtent.depth = 1; region.imageExtent.width = texture->Width; region.imageExtent.height = texture->Height; fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); VkImageTransition barrier1; barrier1.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); barrier1.execute(fb->GetTransferCommands()); } else { VkImageTransition barrier; barrier.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); barrier.execute(fb->GetTransferCommands()); } }