|
@@ -24,6 +24,7 @@
|
|
|
#include "Buffer.h"
|
|
|
|
|
|
#include <limits>
|
|
|
+#include <array>
|
|
|
|
|
|
namespace love
|
|
|
{
|
|
@@ -132,7 +133,7 @@ bool Texture::loadVolatile()
|
|
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
imageInfo.usage = usageFlags;
|
|
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
- imageInfo.samples = msaaSamples;
|
|
|
+ imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
VkImageFormatListCreateInfo viewFormatsInfo{};
|
|
|
viewFormatsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO;
|
|
@@ -153,26 +154,54 @@ bool Texture::loadVolatile()
|
|
|
|
|
|
imageAllocationCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
|
|
|
|
|
- if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS)
|
|
|
- throw love::Exception("failed to create image");
|
|
|
+ if ((msaaSamples & VK_SAMPLE_COUNT_1_BIT) != 0 || readable)
|
|
|
+ {
|
|
|
+ if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &imageData.image, &imageData.allocation, nullptr) != VK_SUCCESS)
|
|
|
+ throw love::Exception("failed to create image");
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((msaaSamples & VK_SAMPLE_COUNT_1_BIT) == 0)
|
|
|
+ {
|
|
|
+ imageInfo.samples = msaaSamples;
|
|
|
+ if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &msaaImageData.image, &msaaImageData.allocation, nullptr) != VK_SUCCESS)
|
|
|
+ throw love::Exception("failed to create MSAA image");
|
|
|
+ }
|
|
|
|
|
|
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
|
|
|
|
|
if (computeWrite)
|
|
|
- imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
+ imageData.layout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
else if (readable)
|
|
|
- imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
+ imageData.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
else if (renderTarget && isPixelFormatDepthStencil(format))
|
|
|
- imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
+ imageData.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
else if (renderTarget)
|
|
|
- imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
+ imageData.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
else // TODO: is there a better layout for this situation?
|
|
|
- imageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
|
+ imageData.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
|
+
|
|
|
+ if (imageData.image != VK_NULL_HANDLE)
|
|
|
+ {
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget,
|
|
|
+ VK_IMAGE_LAYOUT_UNDEFINED, imageData.layout,
|
|
|
+ 0, VK_REMAINING_MIP_LEVELS,
|
|
|
+ 0, VK_REMAINING_ARRAY_LAYERS);
|
|
|
+ }
|
|
|
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- VK_IMAGE_LAYOUT_UNDEFINED, imageLayout,
|
|
|
- 0, VK_REMAINING_MIP_LEVELS,
|
|
|
- 0, VK_REMAINING_ARRAY_LAYERS);
|
|
|
+ if (msaaImageData.image != VK_NULL_HANDLE)
|
|
|
+ {
|
|
|
+ if (renderTarget && isPixelFormatDepthStencil(format))
|
|
|
+ msaaImageData.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
+ else if (renderTarget)
|
|
|
+ msaaImageData.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
+ else // TODO: is there a better layout for this situation?
|
|
|
+ msaaImageData.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
|
+
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, msaaImageData.image, format, renderTarget,
|
|
|
+ VK_IMAGE_LAYOUT_UNDEFINED, msaaImageData.layout,
|
|
|
+ 0, VK_REMAINING_MIP_LEVELS,
|
|
|
+ 0, VK_REMAINING_ARRAY_LAYERS);
|
|
|
+ }
|
|
|
|
|
|
bool hasdata = slices.get(0, 0) != nullptr;
|
|
|
|
|
@@ -195,14 +224,20 @@ bool Texture::loadVolatile()
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
- clear();
|
|
|
+ {
|
|
|
+ if (imageData.image != VK_NULL_HANDLE)
|
|
|
+ clear(imageData);
|
|
|
+ if (msaaImageData.image != VK_NULL_HANDLE)
|
|
|
+ clear(msaaImageData);
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Texture *roottex = (Texture *) rootView.texture;
|
|
|
- textureImage = roottex->textureImage;
|
|
|
- textureImageAllocation = VK_NULL_HANDLE;
|
|
|
- imageLayout = roottex->imageLayout;
|
|
|
+ imageData = roottex->imageData;
|
|
|
+ msaaImageData = roottex->msaaImageData;
|
|
|
+ imageData.allocation = VK_NULL_HANDLE;
|
|
|
+ msaaImageData.allocation = VK_NULL_HANDLE;
|
|
|
msaaSamples = roottex->msaaSamples;
|
|
|
}
|
|
|
|
|
@@ -214,34 +249,8 @@ bool Texture::loadVolatile()
|
|
|
|
|
|
if (renderTarget)
|
|
|
{
|
|
|
- renderTargetImageViews.resize(getMipmapCount());
|
|
|
- for (int mip = 0; mip < getMipmapCount(); mip++)
|
|
|
- {
|
|
|
- renderTargetImageViews.at(mip).resize(layerCount);
|
|
|
-
|
|
|
- for (int slice = 0; slice < layerCount; slice++)
|
|
|
- {
|
|
|
- VkImageViewCreateInfo viewInfo{};
|
|
|
- viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
- viewInfo.image = textureImage;
|
|
|
- viewInfo.viewType = Vulkan::getImageViewType(getTextureType());
|
|
|
- if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_CUBE)
|
|
|
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
- viewInfo.format = vulkanFormat.internalFormat;
|
|
|
- viewInfo.subresourceRange.aspectMask = imageAspect;
|
|
|
- viewInfo.subresourceRange.baseMipLevel = mip + rootView.startMipmap;
|
|
|
- viewInfo.subresourceRange.levelCount = 1;
|
|
|
- viewInfo.subresourceRange.baseArrayLayer = slice + rootView.startLayer;
|
|
|
- viewInfo.subresourceRange.layerCount = 1;
|
|
|
- viewInfo.components.r = vulkanFormat.swizzleR;
|
|
|
- viewInfo.components.g = vulkanFormat.swizzleG;
|
|
|
- viewInfo.components.b = vulkanFormat.swizzleB;
|
|
|
- viewInfo.components.a = vulkanFormat.swizzleA;
|
|
|
-
|
|
|
- if (vkCreateImageView(device, &viewInfo, nullptr, &renderTargetImageViews.at(mip).at(slice)) != VK_SUCCESS)
|
|
|
- throw love::Exception("could not create render target image view");
|
|
|
- }
|
|
|
- }
|
|
|
+ createRenderTargetImageViews(imageData);
|
|
|
+ createRenderTargetImageViews(msaaImageData);
|
|
|
}
|
|
|
|
|
|
if (!debugName.empty())
|
|
@@ -253,15 +262,25 @@ bool Texture::loadVolatile()
|
|
|
if (root)
|
|
|
{
|
|
|
nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
|
|
|
- nameInfo.objectHandle = (uint64_t)textureImage;
|
|
|
+ nameInfo.objectHandle = (uint64_t)imageData.image;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nameInfo.objectType = VK_OBJECT_TYPE_IMAGE_VIEW;
|
|
|
- nameInfo.objectHandle = (uint64_t)textureImageView;
|
|
|
+ nameInfo.objectHandle = (uint64_t)imageData.imageView;
|
|
|
}
|
|
|
nameInfo.pObjectName = debugName.c_str();
|
|
|
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
|
|
|
+
|
|
|
+ if (msaaImageData.image != VK_NULL_HANDLE && root)
|
|
|
+ {
|
|
|
+ nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
|
|
|
+ nameInfo.objectHandle = (uint64_t)msaaImageData.image;
|
|
|
+
|
|
|
+ std::string msaaName = debugName + " (MSAA buffer)";
|
|
|
+ nameInfo.pObjectName = msaaName.c_str();
|
|
|
+ vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -272,26 +291,29 @@ bool Texture::loadVolatile()
|
|
|
|
|
|
void Texture::unloadVolatile()
|
|
|
{
|
|
|
- if (textureImage == VK_NULL_HANDLE)
|
|
|
- return;
|
|
|
+ std::array<VulkanImageData *, 2> datas = {&imageData, &msaaImageData};
|
|
|
|
|
|
- vgfx->queueCleanUp([
|
|
|
- device = device,
|
|
|
- textureImageView = textureImageView,
|
|
|
- allocator = allocator,
|
|
|
- textureImage = textureImage,
|
|
|
- textureImageAllocation = textureImageAllocation,
|
|
|
- textureImageViews = std::move(renderTargetImageViews)] () {
|
|
|
- vkDestroyImageView(device, textureImageView, nullptr);
|
|
|
- if (textureImageAllocation)
|
|
|
- vmaDestroyImage(allocator, textureImage, textureImageAllocation);
|
|
|
- for (const auto &views : textureImageViews)
|
|
|
- for (const auto &view : views)
|
|
|
- vkDestroyImageView(device, view, nullptr);
|
|
|
- });
|
|
|
+ for (const VulkanImageData *data : datas)
|
|
|
+ {
|
|
|
+ if (data->image == VK_NULL_HANDLE)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ vgfx->queueCleanUp([
|
|
|
+ device = device,
|
|
|
+ allocator = allocator,
|
|
|
+ imageData = std::move(*data)] () {
|
|
|
+ if (imageData.imageView != VK_NULL_HANDLE)
|
|
|
+ vkDestroyImageView(device, imageData.imageView, nullptr);
|
|
|
+ if (imageData.allocation != VK_NULL_HANDLE)
|
|
|
+ vmaDestroyImage(allocator, imageData.image, imageData.allocation);
|
|
|
+ for (const auto &views : imageData.renderTargetImageViews)
|
|
|
+ for (const auto &view : views)
|
|
|
+ vkDestroyImageView(device, view, nullptr);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- textureImage = VK_NULL_HANDLE;
|
|
|
- textureImageAllocation = VK_NULL_HANDLE;
|
|
|
+ imageData = {};
|
|
|
+ msaaImageData = {};
|
|
|
|
|
|
updateGraphicsMemorySize(false);
|
|
|
}
|
|
@@ -303,7 +325,7 @@ Texture::~Texture()
|
|
|
|
|
|
ptrdiff_t Texture::getRenderTargetHandle() const
|
|
|
{
|
|
|
- return (ptrdiff_t)textureImageView;
|
|
|
+ return (ptrdiff_t)imageData.image;
|
|
|
}
|
|
|
|
|
|
ptrdiff_t Texture::getSamplerHandle() const
|
|
@@ -313,7 +335,16 @@ ptrdiff_t Texture::getSamplerHandle() const
|
|
|
|
|
|
VkImageView Texture::getRenderTargetView(int mip, int layer)
|
|
|
{
|
|
|
- return renderTargetImageViews.at(mip).at(layer);
|
|
|
+ if (imageData.renderTargetImageViews.empty())
|
|
|
+ return imageData.imageView;
|
|
|
+ return imageData.renderTargetImageViews.at(mip).at(layer);
|
|
|
+}
|
|
|
+
|
|
|
+VkImageView Texture::getMSAARenderTargetView(int mip, int layer)
|
|
|
+{
|
|
|
+ if (msaaImageData.renderTargetImageViews.empty())
|
|
|
+ return msaaImageData.imageView;
|
|
|
+ return msaaImageData.renderTargetImageViews.at(mip).at(layer);
|
|
|
}
|
|
|
|
|
|
VkSampleCountFlagBits Texture::getMsaaSamples() const
|
|
@@ -328,7 +359,7 @@ int Texture::getMSAA() const
|
|
|
|
|
|
ptrdiff_t Texture::getHandle() const
|
|
|
{
|
|
|
- return (ptrdiff_t)textureImage;
|
|
|
+ return (ptrdiff_t)imageData.imageView;
|
|
|
}
|
|
|
|
|
|
void Texture::setSamplerState(const SamplerState &s)
|
|
@@ -339,7 +370,12 @@ void Texture::setSamplerState(const SamplerState &s)
|
|
|
|
|
|
VkImageLayout Texture::getImageLayout() const
|
|
|
{
|
|
|
- return imageLayout;
|
|
|
+ return imageData.layout;
|
|
|
+}
|
|
|
+
|
|
|
+VkImageLayout Texture::getMSAAImageLayout() const
|
|
|
+{
|
|
|
+ return msaaImageData.layout;
|
|
|
}
|
|
|
|
|
|
void Texture::createTextureImageView()
|
|
@@ -347,7 +383,7 @@ void Texture::createTextureImageView()
|
|
|
auto vulkanFormat = Vulkan::getTextureFormat(format);
|
|
|
VkImageViewCreateInfo viewInfo{};
|
|
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
- viewInfo.image = textureImage;
|
|
|
+ viewInfo.image = imageData.image;
|
|
|
viewInfo.viewType = Vulkan::getImageViewType(getTextureType());
|
|
|
viewInfo.format = vulkanFormat.internalFormat;
|
|
|
viewInfo.subresourceRange.aspectMask = imageAspect;
|
|
@@ -364,11 +400,56 @@ void Texture::createTextureImageView()
|
|
|
viewInfo.components.b = vulkanFormat.swizzleB;
|
|
|
viewInfo.components.a = vulkanFormat.swizzleA;
|
|
|
|
|
|
- if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS)
|
|
|
- throw love::Exception("could not create texture image view");
|
|
|
+ imageData.imageView = VK_NULL_HANDLE;
|
|
|
+ if (imageData.image != VK_NULL_HANDLE && readable)
|
|
|
+ {
|
|
|
+ if (vkCreateImageView(device, &viewInfo, nullptr, &imageData.imageView) != VK_SUCCESS)
|
|
|
+ throw love::Exception("could not create texture image view");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Texture::createRenderTargetImageViews(VulkanImageData &data)
|
|
|
+{
|
|
|
+ if (data.image == VK_NULL_HANDLE || (getMipmapCount() == 1 && layerCount == 1 && data.imageView != VK_NULL_HANDLE))
|
|
|
+ {
|
|
|
+ // Reuse the main image view in this situation, if it exists.
|
|
|
+ data.renderTargetImageViews.clear();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto vulkanFormat = Vulkan::getTextureFormat(format);
|
|
|
+
|
|
|
+ data.renderTargetImageViews.resize(getMipmapCount());
|
|
|
+ for (int mip = 0; mip < getMipmapCount(); mip++)
|
|
|
+ {
|
|
|
+ data.renderTargetImageViews.at(mip).resize(layerCount);
|
|
|
+
|
|
|
+ for (int slice = 0; slice < layerCount; slice++)
|
|
|
+ {
|
|
|
+ VkImageViewCreateInfo viewInfo{};
|
|
|
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
+ viewInfo.image = data.image;
|
|
|
+ viewInfo.viewType = Vulkan::getImageViewType(getTextureType());
|
|
|
+ if (viewInfo.viewType == VK_IMAGE_VIEW_TYPE_CUBE)
|
|
|
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
+ viewInfo.format = vulkanFormat.internalFormat;
|
|
|
+ viewInfo.subresourceRange.aspectMask = imageAspect;
|
|
|
+ viewInfo.subresourceRange.baseMipLevel = mip + rootView.startMipmap;
|
|
|
+ viewInfo.subresourceRange.levelCount = 1;
|
|
|
+ viewInfo.subresourceRange.baseArrayLayer = slice + rootView.startLayer;
|
|
|
+ viewInfo.subresourceRange.layerCount = 1;
|
|
|
+ viewInfo.components.r = vulkanFormat.swizzleR;
|
|
|
+ viewInfo.components.g = vulkanFormat.swizzleG;
|
|
|
+ viewInfo.components.b = vulkanFormat.swizzleB;
|
|
|
+ viewInfo.components.a = vulkanFormat.swizzleA;
|
|
|
+
|
|
|
+ if (vkCreateImageView(device, &viewInfo, nullptr, &data.renderTargetImageViews.at(mip).at(slice)) != VK_SUCCESS)
|
|
|
+ throw love::Exception("could not create render target image view");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void Texture::clear()
|
|
|
+void Texture::clear(const VulkanImageData &data)
|
|
|
{
|
|
|
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
|
|
|
|
@@ -379,12 +460,12 @@ void Texture::clear()
|
|
|
range.baseArrayLayer = 0;
|
|
|
range.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
|
|
- VkImageLayout clearLayout = imageLayout == VK_IMAGE_LAYOUT_GENERAL ? imageLayout : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
|
+ VkImageLayout clearLayout = data.layout == VK_IMAGE_LAYOUT_GENERAL ? data.layout : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
|
|
|
|
- if (clearLayout != imageLayout)
|
|
|
+ if (clearLayout != data.layout)
|
|
|
{
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- imageLayout, clearLayout,
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, data.image, format, renderTarget,
|
|
|
+ data.layout, clearLayout,
|
|
|
0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS);
|
|
|
}
|
|
|
|
|
@@ -393,18 +474,18 @@ void Texture::clear()
|
|
|
VkClearDepthStencilValue depthStencilColor{};
|
|
|
depthStencilColor.depth = 0.0f;
|
|
|
depthStencilColor.stencil = 0;
|
|
|
- vkCmdClearDepthStencilImage(commandBuffer, textureImage, clearLayout, &depthStencilColor, 1, &range);
|
|
|
+ vkCmdClearDepthStencilImage(commandBuffer, data.image, clearLayout, &depthStencilColor, 1, &range);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto clearColor = getClearColor(this, ColorD(0, 0, 0, 0));
|
|
|
- vkCmdClearColorImage(commandBuffer, textureImage, clearLayout, &clearColor, 1, &range);
|
|
|
+ vkCmdClearColorImage(commandBuffer, data.image, clearLayout, &clearColor, 1, &range);
|
|
|
}
|
|
|
|
|
|
- if (clearLayout != imageLayout)
|
|
|
+ if (clearLayout != data.layout)
|
|
|
{
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- clearLayout, imageLayout,
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, data.image, format, renderTarget,
|
|
|
+ clearLayout, data.layout,
|
|
|
0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS);
|
|
|
}
|
|
|
}
|
|
@@ -450,15 +531,15 @@ void Texture::generateMipmapsInternal()
|
|
|
{
|
|
|
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget,
|
|
|
+ imageData.layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
rootView.startMipmap, static_cast<uint32_t>(getMipmapCount()),
|
|
|
rootView.startLayer, static_cast<uint32_t>(layerCount));
|
|
|
|
|
|
VkImageMemoryBarrier barrier{};
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
- barrier.image = textureImage;
|
|
|
+ barrier.image = imageData.image;
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
@@ -477,7 +558,7 @@ void Texture::generateMipmapsInternal()
|
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
|
|
0, nullptr,
|
|
|
0, nullptr,
|
|
@@ -498,29 +579,29 @@ void Texture::generateMipmapsInternal()
|
|
|
blit.dstSubresource.baseArrayLayer = rootView.startLayer;
|
|
|
blit.dstSubresource.layerCount = static_cast<uint32_t>(layerCount);
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
{
|
|
|
vkCmdBlitImage(commandBuffer,
|
|
|
- textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
- textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
+ imageData.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
+ imageData.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
1, &blit,
|
|
|
VK_FILTER_LINEAR);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
vkCmdBlitImage(commandBuffer,
|
|
|
- textureImage, VK_IMAGE_LAYOUT_GENERAL,
|
|
|
- textureImage, VK_IMAGE_LAYOUT_GENERAL,
|
|
|
+ imageData.image, VK_IMAGE_LAYOUT_GENERAL,
|
|
|
+ imageData.image, VK_IMAGE_LAYOUT_GENERAL,
|
|
|
1, &blit,
|
|
|
VK_FILTER_LINEAR);
|
|
|
}
|
|
|
|
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
|
- barrier.newLayout = imageLayout;
|
|
|
+ barrier.newLayout = imageData.layout;
|
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
|
|
0, nullptr,
|
|
|
0, nullptr,
|
|
@@ -529,11 +610,11 @@ void Texture::generateMipmapsInternal()
|
|
|
|
|
|
barrier.subresourceRange.baseMipLevel = rootView.startMipmap + mipLevels - 1;
|
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
|
- barrier.newLayout = imageLayout;
|
|
|
+ barrier.newLayout = imageData.layout;
|
|
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
vkCmdPipelineBarrier(commandBuffer,
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
|
|
0, nullptr,
|
|
@@ -587,31 +668,31 @@ void Texture::uploadByteData(const void *data, size_t size, int level, int slice
|
|
|
|
|
|
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
{
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget,
|
|
|
+ imageData.layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
level, 1, baseLayer, 1);
|
|
|
|
|
|
vkCmdCopyBufferToImage(
|
|
|
commandBuffer,
|
|
|
stagingBuffer,
|
|
|
- textureImage,
|
|
|
+ imageData.image,
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
1,
|
|
|
®ion
|
|
|
);
|
|
|
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget,
|
|
|
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout,
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget,
|
|
|
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageData.layout,
|
|
|
level, 1, baseLayer, 1);
|
|
|
}
|
|
|
else
|
|
|
vkCmdCopyBufferToImage(
|
|
|
commandBuffer,
|
|
|
stagingBuffer,
|
|
|
- textureImage,
|
|
|
- imageLayout,
|
|
|
+ imageData.image,
|
|
|
+ imageData.layout,
|
|
|
1,
|
|
|
®ion
|
|
|
);
|
|
@@ -641,16 +722,16 @@ void Texture::copyFromBuffer(graphics::Buffer *source, size_t sourceoffset, int
|
|
|
region.imageExtent.width = static_cast<uint32_t>(rect.w);
|
|
|
region.imageExtent.height = static_cast<uint32_t>(rect.h);
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
{
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget, imageData.layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
|
|
|
- vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
|
+ vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), imageData.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
|
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageData.layout, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
}
|
|
|
else
|
|
|
- vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
|
|
|
+ vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), imageData.image, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
|
|
|
}
|
|
|
|
|
|
void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size)
|
|
@@ -674,16 +755,16 @@ void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const
|
|
|
region.imageExtent.height = static_cast<uint32_t>(rect.h);
|
|
|
region.imageExtent.depth = 1;
|
|
|
|
|
|
- if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
+ if (imageData.layout != VK_IMAGE_LAYOUT_GENERAL)
|
|
|
{
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget, imageData.layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
|
|
|
- vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, ®ion);
|
|
|
+ vkCmdCopyImageToBuffer(commandBuffer, imageData.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, ®ion);
|
|
|
|
|
|
- Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, renderTarget, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageLayout, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
+ Vulkan::cmdTransitionImageLayout(commandBuffer, imageData.image, format, renderTarget, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageData.layout, layers.mipLevel, 1, layers.baseArrayLayer, 1);
|
|
|
}
|
|
|
else
|
|
|
- vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, (VkBuffer)dest->getHandle(), 1, ®ion);
|
|
|
+ vkCmdCopyImageToBuffer(commandBuffer, imageData.image, VK_IMAGE_LAYOUT_GENERAL, (VkBuffer)dest->getHandle(), 1, ®ion);
|
|
|
|
|
|
// TODO: This could be combined with the cmdTransitionImageLayout barrier.
|
|
|
((Buffer *)dest)->postGPUWriteBarrier(commandBuffer);
|