|
@@ -55,14 +55,14 @@ namespace bgfx { namespace vk
|
|
|
16,
|
|
16,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// static DXGI_SAMPLE_DESC s_msaa[] =
|
|
|
|
|
-// {
|
|
|
|
|
-// { 1, 0 },
|
|
|
|
|
-// { 2, 0 },
|
|
|
|
|
-// { 4, 0 },
|
|
|
|
|
-// { 8, 0 },
|
|
|
|
|
-// { 16, 0 },
|
|
|
|
|
-// };
|
|
|
|
|
|
|
+ static MsaaSamplerVK s_msaa[] =
|
|
|
|
|
+ {
|
|
|
|
|
+ { 1, VK_SAMPLE_COUNT_1_BIT },
|
|
|
|
|
+ { 2, VK_SAMPLE_COUNT_2_BIT },
|
|
|
|
|
+ { 4, VK_SAMPLE_COUNT_4_BIT },
|
|
|
|
|
+ { 8, VK_SAMPLE_COUNT_8_BIT },
|
|
|
|
|
+ { 16, VK_SAMPLE_COUNT_16_BIT },
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
static const VkBlendFactor s_blendFactor[][2] =
|
|
static const VkBlendFactor s_blendFactor[][2] =
|
|
|
{
|
|
{
|
|
@@ -970,6 +970,7 @@ VK_IMPORT_DEVICE
|
|
|
, m_maxAnisotropy(1)
|
|
, m_maxAnisotropy(1)
|
|
|
, m_depthClamp(false)
|
|
, m_depthClamp(false)
|
|
|
, m_wireframe(false)
|
|
, m_wireframe(false)
|
|
|
|
|
+ , m_rtMsaa(false)
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1580,6 +1581,16 @@ VK_IMPORT_INSTANCE
|
|
|
vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures);
|
|
vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures);
|
|
|
m_deviceFeatures.robustBufferAccess = VK_FALSE;
|
|
m_deviceFeatures.robustBufferAccess = VK_FALSE;
|
|
|
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ for (uint16_t ii = 0, last = 0; ii < BX_COUNTOF(s_msaa); ii++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if ((m_deviceProperties.limits.framebufferColorSampleCounts >= s_msaa[ii].Count) && (m_deviceProperties.limits.framebufferDepthSampleCounts >= s_msaa[ii].Count))
|
|
|
|
|
+ last = ii;
|
|
|
|
|
+ else
|
|
|
|
|
+ s_msaa[ii] = s_msaa[last];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
{
|
|
{
|
|
|
struct ImageTest
|
|
struct ImageTest
|
|
|
{
|
|
{
|
|
@@ -2051,7 +2062,7 @@ VK_IMPORT_DEVICE
|
|
|
m_sci.imageExtent.width = width;
|
|
m_sci.imageExtent.width = width;
|
|
|
m_sci.imageExtent.height = height;
|
|
m_sci.imageExtent.height = height;
|
|
|
m_sci.imageArrayLayers = 1;
|
|
m_sci.imageArrayLayers = 1;
|
|
|
- m_sci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
|
|
|
+ m_sci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
|
m_sci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
m_sci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
m_sci.queueFamilyIndexCount = 0;
|
|
m_sci.queueFamilyIndexCount = 0;
|
|
|
m_sci.pQueueFamilyIndices = NULL;
|
|
m_sci.pQueueFamilyIndices = NULL;
|
|
@@ -2624,8 +2635,198 @@ VK_IMPORT_DEVICE
|
|
|
m_uniforms[_handle.idx] = NULL;
|
|
m_uniforms[_handle.idx] = NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void requestScreenShot(FrameBufferHandle /*_handle*/, const char* /*_filePath*/) override
|
|
|
|
|
|
|
+ void requestScreenShot(FrameBufferHandle _fbh, const char* _filePath) override
|
|
|
{
|
|
{
|
|
|
|
|
+ bool supportsBlit = true;
|
|
|
|
|
+
|
|
|
|
|
+ // Check blit support for source and destination
|
|
|
|
|
+ VkFormatProperties formatProps;
|
|
|
|
|
+
|
|
|
|
|
+ // Check if the device supports blitting from optimal images (the swapchain images are in optimal format)
|
|
|
|
|
+ vkGetPhysicalDeviceFormatProperties(m_physicalDevice, m_sci.imageFormat, &formatProps);
|
|
|
|
|
+ if (!(formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) {
|
|
|
|
|
+ BX_TRACE("Device does not support blitting from optimal tiled images, using copy instead of blit!\n");
|
|
|
|
|
+ supportsBlit = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check if the device supports blitting to linear images
|
|
|
|
|
+ vkGetPhysicalDeviceFormatProperties(m_physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProps);
|
|
|
|
|
+ if (!(formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
|
|
|
|
|
+ BX_TRACE("Device does not support blitting to linear tiled images, using copy instead of blit!\n");
|
|
|
|
|
+ supportsBlit = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Source for the copy is the last rendered swapchain image
|
|
|
|
|
+ VkImage srcImage = m_backBufferColorImage[m_backBufferColorIdx];
|
|
|
|
|
+ uint32_t width = m_sci.imageExtent.width, height = m_sci.imageExtent.height;
|
|
|
|
|
+
|
|
|
|
|
+ if (isValid(_fbh))
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureVK& texture = m_textures[m_frameBuffers[_fbh.idx].m_attachment[0].handle.idx];
|
|
|
|
|
+ srcImage = VK_NULL_HANDLE != texture.m_singleMsaaImage ? texture.m_singleMsaaImage : texture.m_textureImage;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create the linear tiled destination image to copy to and to read the memory from
|
|
|
|
|
+ VkImage dstImage = VK_NULL_HANDLE;
|
|
|
|
|
+ VkImageCreateInfo ici;
|
|
|
|
|
+ ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
|
|
|
+ ici.pNext = NULL;
|
|
|
|
|
+ ici.flags = 0;
|
|
|
|
|
+ // Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differ
|
|
|
|
|
+ ici.imageType = VK_IMAGE_TYPE_2D;
|
|
|
|
|
+ ici.format = VK_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
|
+ ici.extent.width = width;
|
|
|
|
|
+ ici.extent.height = height;
|
|
|
|
|
+ ici.extent.depth = 1;
|
|
|
|
|
+ ici.arrayLayers = 1;
|
|
|
|
|
+ ici.mipLevels = 1;
|
|
|
|
|
+ ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
+ ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
+ ici.tiling = VK_IMAGE_TILING_LINEAR;
|
|
|
|
|
+ ici.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
|
|
|
+ ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
|
+ ici.queueFamilyIndexCount = 0;
|
|
|
|
|
+ ici.pQueueFamilyIndices = NULL;
|
|
|
|
|
+ // Create the image
|
|
|
|
|
+ VK_CHECK(vkCreateImage(m_device, &ici, m_allocatorCb, &dstImage));
|
|
|
|
|
+
|
|
|
|
|
+ // Create memory to back up the image
|
|
|
|
|
+ VkMemoryRequirements memRequirements;
|
|
|
|
|
+ vkGetImageMemoryRequirements(m_device, dstImage, &memRequirements);
|
|
|
|
|
+
|
|
|
|
|
+ VkMemoryAllocateInfo ma;
|
|
|
|
|
+ ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
|
+ ma.pNext = NULL;
|
|
|
|
|
+ ma.allocationSize = memRequirements.size;
|
|
|
|
|
+
|
|
|
|
|
+ VkDeviceMemory dstImageMemory = VK_NULL_HANDLE;
|
|
|
|
|
+ // Memory must be host visible to copy from
|
|
|
|
|
+ VK_CHECK(allocateMemory(&memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &dstImageMemory));
|
|
|
|
|
+ VK_CHECK(vkBindImageMemory(m_device, dstImage, dstImageMemory, 0));
|
|
|
|
|
+
|
|
|
|
|
+ // Do the actual blit from the swapchain image to our host visible destination image
|
|
|
|
|
+ VkCommandBuffer copyCmd = beginNewCommand();
|
|
|
|
|
+
|
|
|
|
|
+ // Transition destination image to transfer destination layout
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(copyCmd
|
|
|
|
|
+ , dstImage
|
|
|
|
|
+ , VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
|
|
|
|
+ , 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // Transition swapchain image from present to transfer source layout
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(copyCmd
|
|
|
|
|
+ , srcImage
|
|
|
|
|
+ , VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
|
|
|
|
+ , 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // If source and destination support blit we'll blit as this also does automatic format conversion (e.g. from BGR to RGB)
|
|
|
|
|
+ if (supportsBlit)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Define the region to blit (we will blit the whole swapchain image)
|
|
|
|
|
+ VkOffset3D blitSize;
|
|
|
|
|
+ blitSize.x = width;
|
|
|
|
|
+ blitSize.y = height;
|
|
|
|
|
+ blitSize.z = 1;
|
|
|
|
|
+ VkImageBlit imageBlitRegion{};
|
|
|
|
|
+ imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ imageBlitRegion.srcSubresource.layerCount = 1;
|
|
|
|
|
+ imageBlitRegion.srcOffsets[1] = blitSize;
|
|
|
|
|
+ imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ imageBlitRegion.dstSubresource.layerCount = 1;
|
|
|
|
|
+ imageBlitRegion.dstOffsets[1] = blitSize;
|
|
|
|
|
+
|
|
|
|
|
+ // Issue the blit command
|
|
|
|
|
+ vkCmdBlitImage(
|
|
|
|
|
+ copyCmd,
|
|
|
|
|
+ srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
|
+ dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ &imageBlitRegion,
|
|
|
|
|
+ VK_FILTER_NEAREST);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Otherwise use image copy (requires us to manually flip components)
|
|
|
|
|
+ VkImageCopy imageCopyRegion{};
|
|
|
|
|
+ imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ imageCopyRegion.srcSubresource.layerCount = 1;
|
|
|
|
|
+ imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ imageCopyRegion.dstSubresource.layerCount = 1;
|
|
|
|
|
+ imageCopyRegion.extent.width = width;
|
|
|
|
|
+ imageCopyRegion.extent.height = height;
|
|
|
|
|
+ imageCopyRegion.extent.depth = 1;
|
|
|
|
|
+
|
|
|
|
|
+ // Issue the copy command
|
|
|
|
|
+ vkCmdCopyImage(
|
|
|
|
|
+ copyCmd,
|
|
|
|
|
+ srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
|
+ dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ &imageCopyRegion);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Transition destination image to general layout, which is the required layout for mapping the image memory later on
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(copyCmd
|
|
|
|
|
+ , dstImage
|
|
|
|
|
+ , VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
|
+ , 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // Transition back the swap chain image after the blit is done
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(copyCmd
|
|
|
|
|
+ , srcImage
|
|
|
|
|
+ , VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
|
|
|
+ , 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ submitCommandAndWait(copyCmd);
|
|
|
|
|
+
|
|
|
|
|
+ // Get layout of the image (including row pitch)
|
|
|
|
|
+ VkImageSubresource subResource{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
|
|
|
|
|
+ VkSubresourceLayout subResourceLayout;
|
|
|
|
|
+ vkGetImageSubresourceLayout(m_device, dstImage, &subResource, &subResourceLayout);
|
|
|
|
|
+
|
|
|
|
|
+ // Map image memory so we can start copying from it
|
|
|
|
|
+ char* data;
|
|
|
|
|
+ vkMapMemory(m_device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
|
|
|
|
|
+ data += subResourceLayout.offset;
|
|
|
|
|
+
|
|
|
|
|
+ bimg::imageSwizzleBgra8(
|
|
|
|
|
+ data
|
|
|
|
|
+ , subResourceLayout.rowPitch
|
|
|
|
|
+ , width
|
|
|
|
|
+ , height
|
|
|
|
|
+ , data
|
|
|
|
|
+ , subResourceLayout.rowPitch
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ g_callback->screenShot(_filePath
|
|
|
|
|
+ , width
|
|
|
|
|
+ , height
|
|
|
|
|
+ , subResourceLayout.rowPitch
|
|
|
|
|
+ , data
|
|
|
|
|
+ , height * subResourceLayout.rowPitch
|
|
|
|
|
+ , false
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // Clean up resources
|
|
|
|
|
+ vkUnmapMemory(m_device, dstImageMemory);
|
|
|
|
|
+ vkFreeMemory(m_device, dstImageMemory, m_allocatorCb);
|
|
|
|
|
+ vkDestroyImage(m_device, dstImage, m_allocatorCb);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void updateViewName(ViewId _id, const char* _name) override
|
|
void updateViewName(ViewId _id, const char* _name) override
|
|
@@ -3089,9 +3290,11 @@ VK_IMPORT_DEVICE
|
|
|
if (isValid(m_fbh)
|
|
if (isValid(m_fbh)
|
|
|
&& m_fbh.idx != _fbh.idx)
|
|
&& m_fbh.idx != _fbh.idx)
|
|
|
{
|
|
{
|
|
|
- const FrameBufferVK& frameBuffer = m_frameBuffers[m_fbh.idx];
|
|
|
|
|
|
|
+ FrameBufferVK& frameBuffer = m_frameBuffers[m_fbh.idx];
|
|
|
BX_UNUSED(frameBuffer);
|
|
BX_UNUSED(frameBuffer);
|
|
|
|
|
|
|
|
|
|
+ if (m_rtMsaa) frameBuffer.resolve();
|
|
|
|
|
+
|
|
|
for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)
|
|
for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)
|
|
|
{
|
|
{
|
|
|
TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx];
|
|
TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx];
|
|
@@ -3169,7 +3372,7 @@ VK_IMPORT_DEVICE
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
m_fbh = _fbh;
|
|
m_fbh = _fbh;
|
|
|
-// m_rtMsaa = _msaa;
|
|
|
|
|
|
|
+ m_rtMsaa = _msaa;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void setBlendState(VkPipelineColorBlendStateCreateInfo& _desc, uint64_t _state, uint32_t _rgba = 0)
|
|
void setBlendState(VkPipelineColorBlendStateCreateInfo& _desc, uint64_t _state, uint32_t _rgba = 0)
|
|
@@ -3410,7 +3613,7 @@ VK_IMPORT_DEVICE
|
|
|
TextureVK& texture = m_textures[_attachments[ii].handle.idx];
|
|
TextureVK& texture = m_textures[_attachments[ii].handle.idx];
|
|
|
ad[ii].flags = 0;
|
|
ad[ii].flags = 0;
|
|
|
ad[ii].format = texture.m_format;
|
|
ad[ii].format = texture.m_format;
|
|
|
- ad[ii].samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
+ ad[ii].samples = texture.m_sampler.Sample;
|
|
|
|
|
|
|
|
if (texture.m_aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
|
if (texture.m_aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
|
|
{
|
|
{
|
|
@@ -3701,11 +3904,13 @@ VK_IMPORT_DEVICE
|
|
|
viewportState.scissorCount = 1;
|
|
viewportState.scissorCount = 1;
|
|
|
viewportState.pScissors = NULL;
|
|
viewportState.pScissors = NULL;
|
|
|
|
|
|
|
|
|
|
+ VkSampleCountFlagBits rasterizerMsaa = (isValid(m_fbh) && !!(BGFX_STATE_MSAA & _state) ? m_textures[m_frameBuffers[m_fbh.idx].m_attachment[0].handle.idx].m_sampler.Sample : VK_SAMPLE_COUNT_1_BIT);
|
|
|
|
|
+
|
|
|
VkPipelineMultisampleStateCreateInfo multisampleState;
|
|
VkPipelineMultisampleStateCreateInfo multisampleState;
|
|
|
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
|
multisampleState.pNext = NULL;
|
|
multisampleState.pNext = NULL;
|
|
|
multisampleState.flags = 0;
|
|
multisampleState.flags = 0;
|
|
|
- multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
+ multisampleState.rasterizationSamples = rasterizerMsaa;
|
|
|
multisampleState.sampleShadingEnable = VK_FALSE;
|
|
multisampleState.sampleShadingEnable = VK_FALSE;
|
|
|
multisampleState.minSampleShading = !!(BGFX_STATE_CONSERVATIVE_RASTER & _state) ? 1.0f : 0.0f;
|
|
multisampleState.minSampleShading = !!(BGFX_STATE_CONSERVATIVE_RASTER & _state) ? 1.0f : 0.0f;
|
|
|
multisampleState.pSampleMask = NULL;
|
|
multisampleState.pSampleMask = NULL;
|
|
@@ -3912,10 +4117,17 @@ VK_IMPORT_DEVICE
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
imageInfo[imageCount].imageLayout = texture.m_currentImageLayout;
|
|
imageInfo[imageCount].imageLayout = texture.m_currentImageLayout;
|
|
|
|
|
+
|
|
|
imageInfo[imageCount].imageView = VK_NULL_HANDLE != texture.m_textureImageDepthView
|
|
imageInfo[imageCount].imageView = VK_NULL_HANDLE != texture.m_textureImageDepthView
|
|
|
? texture.m_textureImageDepthView
|
|
? texture.m_textureImageDepthView
|
|
|
: texture.m_textureImageView
|
|
: texture.m_textureImageView
|
|
|
;
|
|
;
|
|
|
|
|
+
|
|
|
|
|
+ if (VK_NULL_HANDLE != texture.m_singleMsaaImageView)
|
|
|
|
|
+ {
|
|
|
|
|
+ imageInfo[imageCount].imageView = texture.m_singleMsaaImageView;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
imageInfo[imageCount].sampler = sampler;
|
|
imageInfo[imageCount].sampler = sampler;
|
|
|
|
|
|
|
|
wds[wdsCount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
wds[wdsCount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
@@ -4353,6 +4565,7 @@ VK_IMPORT_DEVICE
|
|
|
uint32_t m_maxAnisotropy;
|
|
uint32_t m_maxAnisotropy;
|
|
|
bool m_depthClamp;
|
|
bool m_depthClamp;
|
|
|
bool m_wireframe;
|
|
bool m_wireframe;
|
|
|
|
|
+ bool m_rtMsaa;
|
|
|
|
|
|
|
|
TextVideoMem m_textVideoMem;
|
|
TextVideoMem m_textVideoMem;
|
|
|
|
|
|
|
@@ -5208,6 +5421,8 @@ VK_DESTROY
|
|
|
: VK_IMAGE_ASPECT_COLOR_BIT
|
|
: VK_IMAGE_ASPECT_COLOR_BIT
|
|
|
;
|
|
;
|
|
|
|
|
|
|
|
|
|
+ m_sampler = s_msaa[bx::uint32_satsub((m_flags & BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT, 1)];
|
|
|
|
|
+
|
|
|
if (m_format == VK_FORMAT_S8_UINT
|
|
if (m_format == VK_FORMAT_S8_UINT
|
|
|
|| m_format == VK_FORMAT_D16_UNORM_S8_UINT
|
|
|| m_format == VK_FORMAT_D16_UNORM_S8_UINT
|
|
|
|| m_format == VK_FORMAT_D24_UNORM_S8_UINT
|
|
|| m_format == VK_FORMAT_D24_UNORM_S8_UINT
|
|
@@ -5244,6 +5459,12 @@ VK_DESTROY
|
|
|
const bool renderTarget = 0 != (m_flags & BGFX_TEXTURE_RT_MASK);
|
|
const bool renderTarget = 0 != (m_flags & BGFX_TEXTURE_RT_MASK);
|
|
|
const bool blit = 0 != (m_flags & BGFX_TEXTURE_BLIT_DST);
|
|
const bool blit = 0 != (m_flags & BGFX_TEXTURE_BLIT_DST);
|
|
|
|
|
|
|
|
|
|
+ const bool needResolve = true
|
|
|
|
|
+ && 1 < m_sampler.Count
|
|
|
|
|
+ && 0 == (m_flags & BGFX_TEXTURE_MSAA_SAMPLE)
|
|
|
|
|
+ && !writeOnly
|
|
|
|
|
+ ;
|
|
|
|
|
+
|
|
|
BX_UNUSED(swizzle, writeOnly, computeWrite, renderTarget, blit);
|
|
BX_UNUSED(swizzle, writeOnly, computeWrite, renderTarget, blit);
|
|
|
|
|
|
|
|
BX_TRACE(
|
|
BX_TRACE(
|
|
@@ -5468,7 +5689,7 @@ VK_DESTROY
|
|
|
| (_flags & BGFX_TEXTURE_COMPUTE_WRITE ? VK_IMAGE_USAGE_STORAGE_BIT : 0)
|
|
| (_flags & BGFX_TEXTURE_COMPUTE_WRITE ? VK_IMAGE_USAGE_STORAGE_BIT : 0)
|
|
|
;
|
|
;
|
|
|
ici.format = m_format;
|
|
ici.format = m_format;
|
|
|
- ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
|
|
+ ici.samples = m_sampler.Sample;
|
|
|
ici.mipLevels = m_numMips;
|
|
ici.mipLevels = m_numMips;
|
|
|
ici.arrayLayers = m_numSides;
|
|
ici.arrayLayers = m_numSides;
|
|
|
ici.extent.width = m_width;
|
|
ici.extent.width = m_width;
|
|
@@ -5528,9 +5749,9 @@ VK_DESTROY
|
|
|
viewInfo.components = m_components;
|
|
viewInfo.components = m_components;
|
|
|
viewInfo.subresourceRange.aspectMask = m_aspectMask;
|
|
viewInfo.subresourceRange.aspectMask = m_aspectMask;
|
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
|
- viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips;
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.levelCount = m_numMips;
|
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
- viewInfo.subresourceRange.layerCount = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.layerCount = m_numSides;
|
|
|
VK_CHECK(vkCreateImageView(
|
|
VK_CHECK(vkCreateImageView(
|
|
|
device
|
|
device
|
|
|
, &viewInfo
|
|
, &viewInfo
|
|
@@ -5552,9 +5773,9 @@ VK_DESTROY
|
|
|
viewInfo.components = m_components;
|
|
viewInfo.components = m_components;
|
|
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
|
- viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips;
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.levelCount = m_numMips;
|
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
- viewInfo.subresourceRange.layerCount = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.layerCount = m_numSides;
|
|
|
VK_CHECK(vkCreateImageView(
|
|
VK_CHECK(vkCreateImageView(
|
|
|
device
|
|
device
|
|
|
, &viewInfo
|
|
, &viewInfo
|
|
@@ -5579,9 +5800,9 @@ VK_DESTROY
|
|
|
viewInfo.components = m_components;
|
|
viewInfo.components = m_components;
|
|
|
viewInfo.subresourceRange.aspectMask = m_aspectMask;
|
|
viewInfo.subresourceRange.aspectMask = m_aspectMask;
|
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
|
- viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips;
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.levelCount = m_numMips;
|
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
- viewInfo.subresourceRange.layerCount = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
|
|
|
|
|
|
|
+ viewInfo.subresourceRange.layerCount = m_numSides;
|
|
|
VK_CHECK(vkCreateImageView(
|
|
VK_CHECK(vkCreateImageView(
|
|
|
device
|
|
device
|
|
|
, &viewInfo
|
|
, &viewInfo
|
|
@@ -5589,6 +5810,61 @@ VK_DESTROY
|
|
|
, &m_textureImageStorageView
|
|
, &m_textureImageStorageView
|
|
|
) );
|
|
) );
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (needResolve)
|
|
|
|
|
+ {
|
|
|
|
|
+ {
|
|
|
|
|
+ VkImageCreateInfo ici_resolve = ici;
|
|
|
|
|
+ ici_resolve.samples = s_msaa[0].Sample;
|
|
|
|
|
+ ici_resolve.usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
|
|
|
|
+
|
|
|
|
|
+ VK_CHECK(vkCreateImage(device, &ici_resolve, allocatorCb, &m_singleMsaaImage));
|
|
|
|
|
+
|
|
|
|
|
+ VkMemoryRequirements imageMemReq_resolve;
|
|
|
|
|
+ vkGetImageMemoryRequirements(device, m_singleMsaaImage, &imageMemReq_resolve);
|
|
|
|
|
+
|
|
|
|
|
+ VK_CHECK(s_renderVK->allocateMemory(&imageMemReq_resolve, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &m_singleMsaaDeviceMem));
|
|
|
|
|
+
|
|
|
|
|
+ vkBindImageMemory(device, m_singleMsaaImage, m_singleMsaaDeviceMem, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
|
|
|
|
|
+
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(commandBuffer
|
|
|
|
|
+ , m_singleMsaaImage
|
|
|
|
|
+ , m_aspectMask
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
|
+ , m_numMips
|
|
|
|
|
+ , m_numSides
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ s_renderVK->submitCommandAndWait(commandBuffer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ VkImageViewCreateInfo viewInfo;
|
|
|
|
|
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
|
+ viewInfo.pNext = NULL;
|
|
|
|
|
+ viewInfo.flags = 0;
|
|
|
|
|
+ viewInfo.image = m_singleMsaaImage;
|
|
|
|
|
+ viewInfo.viewType = m_type;
|
|
|
|
|
+ viewInfo.format = m_format;
|
|
|
|
|
+ viewInfo.components = m_components;
|
|
|
|
|
+ viewInfo.subresourceRange.aspectMask = m_aspectMask;
|
|
|
|
|
+ viewInfo.subresourceRange.baseMipLevel = 0;
|
|
|
|
|
+ viewInfo.subresourceRange.levelCount = m_numMips;
|
|
|
|
|
+ viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
|
|
+ viewInfo.subresourceRange.layerCount = m_numSides;
|
|
|
|
|
+ VK_CHECK(vkCreateImageView(
|
|
|
|
|
+ device
|
|
|
|
|
+ , &viewInfo
|
|
|
|
|
+ , allocatorCb
|
|
|
|
|
+ , &m_singleMsaaImageView
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return m_directAccessPtr;
|
|
return m_directAccessPtr;
|
|
@@ -5596,20 +5872,28 @@ VK_DESTROY
|
|
|
|
|
|
|
|
void TextureVK::destroy()
|
|
void TextureVK::destroy()
|
|
|
{
|
|
{
|
|
|
|
|
+ VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
|
|
|
|
|
+ VkDevice device = s_renderVK->m_device;
|
|
|
|
|
+
|
|
|
if (m_textureImage)
|
|
if (m_textureImage)
|
|
|
{
|
|
{
|
|
|
- VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
|
|
|
|
|
- VkDevice device = s_renderVK->m_device;
|
|
|
|
|
-
|
|
|
|
|
vkFreeMemory(device, m_textureDeviceMem, allocatorCb);
|
|
vkFreeMemory(device, m_textureDeviceMem, allocatorCb);
|
|
|
|
|
|
|
|
vkDestroy(m_textureImageStorageView);
|
|
vkDestroy(m_textureImageStorageView);
|
|
|
vkDestroy(m_textureImageDepthView);
|
|
vkDestroy(m_textureImageDepthView);
|
|
|
vkDestroy(m_textureImageView);
|
|
vkDestroy(m_textureImageView);
|
|
|
vkDestroy(m_textureImage);
|
|
vkDestroy(m_textureImage);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- m_currentImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
|
|
+ if (m_singleMsaaImage)
|
|
|
|
|
+ {
|
|
|
|
|
+ vkFreeMemory(device, m_singleMsaaDeviceMem, allocatorCb);
|
|
|
|
|
+
|
|
|
|
|
+ vkDestroy(m_singleMsaaImageView);
|
|
|
|
|
+ vkDestroy(m_singleMsaaImage);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ m_currentImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void TextureVK::update(VkCommandPool _commandPool, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem)
|
|
void TextureVK::update(VkCommandPool _commandPool, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem)
|
|
@@ -5699,6 +5983,108 @@ VK_DESTROY
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ void TextureVK::resolve(uint8_t _resolve)
|
|
|
|
|
+ {
|
|
|
|
|
+ BX_UNUSED(_resolve);
|
|
|
|
|
+
|
|
|
|
|
+ bool needResolve = VK_NULL_HANDLE != m_singleMsaaImage;
|
|
|
|
|
+ if (needResolve)
|
|
|
|
|
+ {
|
|
|
|
|
+ VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
|
|
|
|
|
+
|
|
|
|
|
+ VkImageResolve blitInfo;
|
|
|
|
|
+ blitInfo.srcOffset.x = 0;
|
|
|
|
|
+ blitInfo.srcOffset.y = 0;
|
|
|
|
|
+ blitInfo.srcOffset.z = 0;
|
|
|
|
|
+ blitInfo.dstOffset.x = 0;
|
|
|
|
|
+ blitInfo.dstOffset.y = 0;
|
|
|
|
|
+ blitInfo.dstOffset.z = 0;
|
|
|
|
|
+ blitInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ blitInfo.srcSubresource.mipLevel = 0;
|
|
|
|
|
+ blitInfo.srcSubresource.baseArrayLayer = 0;
|
|
|
|
|
+ blitInfo.srcSubresource.layerCount = 1;
|
|
|
|
|
+ blitInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
+ blitInfo.dstSubresource.mipLevel = 0;
|
|
|
|
|
+ blitInfo.dstSubresource.baseArrayLayer = 0;
|
|
|
|
|
+ blitInfo.dstSubresource.layerCount = 1;
|
|
|
|
|
+ blitInfo.extent.width = m_width;
|
|
|
|
|
+ blitInfo.extent.height = m_height;
|
|
|
|
|
+ blitInfo.extent.depth = 1;
|
|
|
|
|
+
|
|
|
|
|
+ vkCmdResolveImage(commandBuffer,
|
|
|
|
|
+ m_textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
|
+ m_singleMsaaImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
|
+ 1, &blitInfo);
|
|
|
|
|
+
|
|
|
|
|
+ s_renderVK->submitCommandAndWait(commandBuffer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const bool renderTarget = 0 != (m_flags & BGFX_TEXTURE_RT_MASK);
|
|
|
|
|
+ if (renderTarget
|
|
|
|
|
+ && 1 < m_numMips
|
|
|
|
|
+ && 0 != (_resolve & BGFX_RESOLVE_AUTO_GEN_MIPS))
|
|
|
|
|
+ {
|
|
|
|
|
+ VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
|
|
|
|
|
+
|
|
|
|
|
+ int32_t mipWidth = m_width;
|
|
|
|
|
+ int32_t mipHeight = m_height;
|
|
|
|
|
+
|
|
|
|
|
+ for (uint32_t i = 1; i < m_numMips; i++) {
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(commandBuffer
|
|
|
|
|
+ , needResolve ? m_singleMsaaImage : m_textureImage
|
|
|
|
|
+ , m_aspectMask
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
|
|
|
|
+ , i - 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ VkImageBlit blit{};
|
|
|
|
|
+ blit.srcOffsets[0] = { 0, 0, 0 };
|
|
|
|
|
+ blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
|
|
|
|
|
+ blit.srcSubresource.aspectMask = m_aspectMask;
|
|
|
|
|
+ blit.srcSubresource.mipLevel = i - 1;
|
|
|
|
|
+ blit.srcSubresource.baseArrayLayer = 0;
|
|
|
|
|
+ blit.srcSubresource.layerCount = 1;
|
|
|
|
|
+ blit.dstOffsets[0] = { 0, 0, 0 };
|
|
|
|
|
+ blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
|
|
|
|
|
+ blit.dstSubresource.aspectMask = m_aspectMask;
|
|
|
|
|
+ blit.dstSubresource.mipLevel = i;
|
|
|
|
|
+ blit.dstSubresource.baseArrayLayer = 0;
|
|
|
|
|
+ blit.dstSubresource.layerCount = 1;
|
|
|
|
|
+
|
|
|
|
|
+ vkCmdBlitImage(commandBuffer,
|
|
|
|
|
+ needResolve ? m_singleMsaaImage : m_textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
|
+ needResolve ? m_singleMsaaImage : m_textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
|
+ 1, &blit,
|
|
|
|
|
+ VK_FILTER_LINEAR);
|
|
|
|
|
+
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(commandBuffer
|
|
|
|
|
+ , needResolve ? m_singleMsaaImage : m_textureImage
|
|
|
|
|
+ , m_aspectMask
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
|
+ , i - 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (mipWidth > 1) mipWidth /= 2;
|
|
|
|
|
+ if (mipHeight > 1) mipHeight /= 2;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bgfx::vk::setImageMemoryBarrier(commandBuffer
|
|
|
|
|
+ , needResolve ? m_singleMsaaImage : m_textureImage
|
|
|
|
|
+ , m_aspectMask
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
|
|
|
|
+ , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
|
+ , m_numMips - 1
|
|
|
|
|
+ , 1
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ s_renderVK->submitCommandAndWait(commandBuffer);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
void TextureVK::copyBufferToTexture(VkBuffer stagingBuffer, uint32_t bufferImageCopyCount, VkBufferImageCopy* bufferImageCopy)
|
|
void TextureVK::copyBufferToTexture(VkBuffer stagingBuffer, uint32_t bufferImageCopyCount, VkBufferImageCopy* bufferImageCopy)
|
|
|
{
|
|
{
|
|
|
VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
|
|
VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
|
|
@@ -5779,6 +6165,23 @@ VK_DESTROY
|
|
|
m_renderPass = renderPass;
|
|
m_renderPass = renderPass;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ void FrameBufferVK::resolve()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (0 < m_numAttachment)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (uint32_t ii = 0; ii < m_numAttachment; ++ii)
|
|
|
|
|
+ {
|
|
|
|
|
+ const Attachment& at = m_attachment[ii];
|
|
|
|
|
+
|
|
|
|
|
+ if (isValid(at.handle))
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureVK& texture = s_renderVK->m_textures[at.handle.idx];
|
|
|
|
|
+ texture.resolve(at.resolve);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
void FrameBufferVK::destroy()
|
|
void FrameBufferVK::destroy()
|
|
|
{
|
|
{
|
|
|
vkDestroy(m_framebuffer);
|
|
vkDestroy(m_framebuffer);
|
|
@@ -5853,7 +6256,7 @@ VK_DESTROY
|
|
|
VkFilter filter = bimg::isDepth(bimg::TextureFormat::Enum(src.m_textureFormat) ) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
|
|
VkFilter filter = bimg::isDepth(bimg::TextureFormat::Enum(src.m_textureFormat) ) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
|
|
|
vkCmdBlitImage(
|
|
vkCmdBlitImage(
|
|
|
commandBuffer
|
|
commandBuffer
|
|
|
- , src.m_textureImage
|
|
|
|
|
|
|
+ , VK_NULL_HANDLE != src.m_singleMsaaImage ? src.m_singleMsaaImage : src.m_textureImage
|
|
|
, src.m_currentImageLayout
|
|
, src.m_currentImageLayout
|
|
|
, dst.m_textureImage
|
|
, dst.m_textureImage
|
|
|
, dst.m_currentImageLayout
|
|
, dst.m_currentImageLayout
|