Commit 809d0113 by Alexis Hetu Committed by Alexis Hétu

Implement image blitting

First simple implementation of image blitting. Note that layers are not yet taken into account. Passes almost all tests in (There are only 2 failures, which both have an off by 1 error on a single pixel): dEQP-VK.api.copy_and_blit.core.blit_image.simple_tests.* Bug b/118619338 b/119620767 Change-Id: I1e0ac88089d6159924569099ea6345804a219d2c Reviewed-on: https://swiftshader-review.googlesource.com/c/23268Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent bb0a7f09
......@@ -220,6 +220,25 @@ private:
const VkBufferImageCopy region;
};
struct BlitImage : public CommandBuffer::Command
{
BlitImage(VkImage srcImage, VkImage dstImage, const VkImageBlit& region, VkFilter filter) :
srcImage(srcImage), dstImage(dstImage), region(region), filter(filter)
{
}
void play(CommandBuffer::ExecutionState& executionState)
{
Cast(srcImage)->blit(dstImage, region, filter);
}
private:
VkImage srcImage;
VkImage dstImage;
const VkImageBlit& region;
VkFilter filter;
};
struct PipelineBarrier : public CommandBuffer::Command
{
PipelineBarrier()
......@@ -530,7 +549,16 @@ void CommandBuffer::copyImage(VkImage srcImage, VkImageLayout srcImageLayout, Vk
void CommandBuffer::blitImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter)
{
UNIMPLEMENTED();
ASSERT(state == RECORDING);
ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
for(uint32_t i = 0; i < regionCount; i++)
{
commands->push_back(std::make_unique<BlitImage>(srcImage, dstImage, pRegions[i], filter));
}
}
void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout,
......
......@@ -368,6 +368,54 @@ VkDeviceSize Image::getStorageSize(const VkImageAspectFlags& flags) const
return arrayLayers * extent.depth * slicePitchB;
}
sw::Surface* Image::asSurface(const VkImageAspectFlags& flags) const
{
return sw::Surface::create(extent.width, extent.height, extent.depth, getFormat(flags),
deviceMemory->getOffsetPointer(memoryOffset),
rowPitchBytes(flags), slicePitchBytes(flags));
}
void Image::blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter)
{
VkImageAspectFlags srcFlags = region.srcSubresource.aspectMask;
VkImageAspectFlags dstFlags = region.dstSubresource.aspectMask;
if((region.srcSubresource.baseArrayLayer != 0) ||
(region.dstSubresource.baseArrayLayer != 0) ||
(region.srcSubresource.layerCount != 1) ||
(region.dstSubresource.layerCount != 1) ||
(region.srcSubresource.mipLevel != 0) ||
(region.dstSubresource.mipLevel != 0) ||
(srcFlags != dstFlags))
{
UNIMPLEMENTED();
}
int32_t numSlices = (region.srcOffsets[1].z - region.srcOffsets[0].z);
ASSERT(numSlices == (region.dstOffsets[1].z - region.dstOffsets[0].z));
sw::Surface* srcSurface = asSurface(srcFlags);
sw::Surface* dstSurface = Cast(dstImage)->asSurface(dstFlags);
sw::SliceRectF sRect(static_cast<float>(region.srcOffsets[0].x), static_cast<float>(region.srcOffsets[0].y),
static_cast<float>(region.srcOffsets[1].x), static_cast<float>(region.srcOffsets[1].y),
region.srcOffsets[0].z);
sw::SliceRect dRect(region.dstOffsets[0].x, region.dstOffsets[0].y,
region.dstOffsets[1].x, region.dstOffsets[1].y, region.dstOffsets[0].z);
sw::Blitter blitter;
for(int i = 0; i < numSlices; i++)
{
blitter.blit(srcSurface, sRect, dstSurface, dRect,
{filter != VK_FILTER_NEAREST, srcFlags == VK_IMAGE_ASPECT_STENCIL_BIT, false});
sRect.slice++;
dRect.slice++;
}
delete srcSurface;
delete dstSurface;
}
void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
{
if(!((subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
......@@ -398,9 +446,7 @@ void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, co
renderArea.offset.y + renderArea.extent.height);
const sw::SliceRect dRect(rect);
sw::Surface* surface = sw::Surface::create(extent.width, extent.height, extent.depth,
getFormat(subresourceRange.aspectMask), deviceMemory->getOffsetPointer(memoryOffset),
rowPitchBytes(subresourceRange.aspectMask), slicePitchBytes(subresourceRange.aspectMask));
sw::Surface* surface = asSurface(subresourceRange.aspectMask);
sw::Blitter blitter;
blitter.clear((void*)clearValue.color.float32, clearFormat, surface, dRect, 0xF);
delete surface;
......
......@@ -42,6 +42,7 @@ public:
void copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& region);
void copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& region);
void blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter);
void clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
VkImageType getImageType() const { return imageType; }
......@@ -58,6 +59,7 @@ private:
int bytesPerTexel(const VkImageAspectFlags& flags) const;
VkFormat getFormat(const VkImageAspectFlags& flags) const;
int getBorder() const;
sw::Surface* asSurface(const VkImageAspectFlags& flags) const;
DeviceMemory* deviceMemory = nullptr;
VkDeviceSize memoryOffset = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment