Commit a233ceae by Alexis Hetu Committed by Alexis Hétu

Image copy

Image objects now have the ability to copy their content to another image object. They can also copy their content to or from Buffer objects. Bug b\119620767 Change-Id: I047e9ecdcc11e264589de1d9461ef448f22a4d9e Reviewed-on: https://swiftshader-review.googlesource.com/c/23070Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent afb8cd30
......@@ -12,12 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "VkDeviceMemory.hpp"
#include "VkBuffer.hpp"
#include "VkImage.hpp"
#include "Device/Surface.hpp"
#include <cstring>
namespace vk
{
Image::Image(const VkImageCreateInfo* pCreateInfo, void* mem)
Image::Image(const VkImageCreateInfo* pCreateInfo, void* mem) :
flags(pCreateInfo->flags),
imageType(pCreateInfo->imageType),
format(pCreateInfo->format),
extent(pCreateInfo->extent),
mipLevels(pCreateInfo->mipLevels),
arrayLayers(pCreateInfo->arrayLayers),
samples(pCreateInfo->samples),
tiling(pCreateInfo->tiling)
{
}
......@@ -30,4 +42,183 @@ size_t Image::ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo
return 0;
}
const VkMemoryRequirements Image::getMemoryRequirements() const
{
VkMemoryRequirements memoryRequirements;
memoryRequirements.alignment = vk::REQUIRED_MEMORY_ALIGNMENT;
memoryRequirements.memoryTypeBits = vk::MEMORY_TYPE_GENERIC_BIT;
memoryRequirements.size = getStorageSize();
return memoryRequirements;
}
void Image::bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset)
{
deviceMemory = pDeviceMemory;
memoryOffset = pMemoryOffset;
}
void Image::copyTo(VkImage dstImage, const VkImageCopy& pRegion)
{
// Image copy does not perform any conversion, it simply copies memory from
// an image to another image that has the same number of bytes per pixel.
Image* dst = Cast(dstImage);
int srcBytesPerTexel = bytesPerTexel();
ASSERT(srcBytesPerTexel == dst->bytesPerTexel());
if(!((pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.srcSubresource.baseArrayLayer != 0) ||
(pRegion.srcSubresource.layerCount != 1) ||
(pRegion.srcSubresource.mipLevel != 0))
{
UNIMPLEMENTED();
}
if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.dstSubresource.baseArrayLayer != 0) ||
(pRegion.dstSubresource.layerCount != 1) ||
(pRegion.dstSubresource.mipLevel != 0))
{
UNIMPLEMENTED();
}
const char* srcMem = static_cast<const char*>(getTexelPointer(pRegion.srcOffset));
char* dstMem = static_cast<char*>(dst->getTexelPointer(pRegion.dstOffset));
int srcRowPitchBytes = rowPitchBytes();
int srcSlicePitchBytes = slicePitchBytes();
int dstRowPitchBytes = dst->rowPitchBytes();
int dstSlicePitchBytes = dst->slicePitchBytes();
bool isSingleLine = (pRegion.extent.height == 1) && (pRegion.extent.depth == 1);
bool isEntireLine = (pRegion.extent.width == extent.width) && (pRegion.extent.width == dst->extent.width) && (srcRowPitchBytes == dstRowPitchBytes);
bool isSinglePlane = (pRegion.extent.depth == 1);
bool isEntirePlane = isEntireLine && (pRegion.extent.height == extent.height) && (pRegion.extent.height == dst->extent.height) && (srcSlicePitchBytes == dstSlicePitchBytes);
if(isSingleLine)
{
memcpy(dstMem, srcMem, pRegion.extent.width * srcBytesPerTexel); // Copy one line
}
else if(isEntireLine && isSinglePlane)
{
memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes); // Copy one plane
}
else if(isEntireLine && isEntirePlane)
{
memcpy(dstMem, srcMem, pRegion.extent.depth * srcSlicePitchBytes); // Copy multiple planes
}
else if(isEntireLine) // Copy plane by plane
{
for(uint32_t z = 0; z < pRegion.extent.depth; z++, dstMem += dstSlicePitchBytes, srcMem += srcSlicePitchBytes)
{
memcpy(dstMem, srcMem, pRegion.extent.height * srcRowPitchBytes);
}
}
else // Copy line by line
{
for(uint32_t z = 0; z < pRegion.extent.depth; z++)
{
for(uint32_t y = 0; y < pRegion.extent.height; y++, dstMem += dstRowPitchBytes, srcMem += srcRowPitchBytes)
{
memcpy(dstMem, srcMem, pRegion.extent.width * srcBytesPerTexel);
}
}
}
}
void Image::copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion)
{
if((pRegion.imageExtent.width != extent.width) ||
(pRegion.imageExtent.height != extent.height) ||
(pRegion.imageExtent.depth != extent.depth) ||
!((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.imageSubresource.baseArrayLayer != 0) ||
(pRegion.imageSubresource.layerCount != 1) ||
(pRegion.imageSubresource.mipLevel != 0) ||
(pRegion.imageOffset.x != 0) ||
(pRegion.imageOffset.y != 0) ||
(pRegion.imageOffset.z != 0) ||
(pRegion.bufferRowLength != extent.width) ||
(pRegion.bufferImageHeight != extent.height))
{
UNIMPLEMENTED();
}
Cast(dstBuffer)->copyFrom(Cast(deviceMemory)->getOffsetPointer(memoryOffset),
sw::Surface::sliceB(pRegion.imageExtent.width, pRegion.imageExtent.height,
getBorder(), format, false) * pRegion.imageExtent.depth,
pRegion.bufferOffset);
}
void Image::copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion)
{
if((pRegion.imageExtent.width != extent.width) ||
(pRegion.imageExtent.height != extent.height) ||
(pRegion.imageExtent.depth != extent.depth) ||
!((pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
(pRegion.imageSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
(pRegion.imageSubresource.baseArrayLayer != 0) ||
(pRegion.imageSubresource.layerCount != 1) ||
(pRegion.imageSubresource.mipLevel != 0) ||
(pRegion.imageOffset.x != 0) ||
(pRegion.imageOffset.y != 0) ||
(pRegion.imageOffset.z != 0) ||
(pRegion.bufferRowLength != extent.width) ||
(pRegion.bufferImageHeight != extent.height))
{
UNIMPLEMENTED();
}
Cast(srcBuffer)->copyTo(Cast(deviceMemory)->getOffsetPointer(memoryOffset),
sw::Surface::sliceB(pRegion.imageExtent.width, pRegion.imageExtent.height,
getBorder(), format, false) * pRegion.imageExtent.depth,
pRegion.bufferOffset);
}
void* Image::getTexelPointer(const VkOffset3D& offset) const
{
return Cast(deviceMemory)->getOffsetPointer(texelOffsetBytesInStorage(offset) + memoryOffset);
}
VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D& offset) const
{
return offset.z * slicePitchBytes() + offset.y * rowPitchBytes() + offset.x * bytesPerTexel();
}
int Image::rowPitchBytes() const
{
return sw::Surface::pitchB(extent.width, getBorder(), format, false);
}
int Image::slicePitchBytes() const
{
return sw::Surface::sliceB(extent.width, extent.height, getBorder(), format, false);
}
int Image::bytesPerTexel() const
{
return sw::Surface::bytes(format);
}
int Image::getBorder() const
{
return ((flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && (imageType == VK_IMAGE_TYPE_2D)) ? 1 : 0;
}
VkDeviceSize Image::getStorageSize() const
{
if(mipLevels > 1)
{
UNIMPLEMENTED();
}
return extent.depth * slicePitchBytes();
}
} // namespace vk
\ No newline at end of file
......@@ -17,6 +17,11 @@
#include "VkObject.hpp"
namespace sw
{
class Surface;
};
namespace vk
{
......@@ -29,7 +34,31 @@ public:
static size_t ComputeRequiredAllocationSize(const VkImageCreateInfo* pCreateInfo);
VkDeviceSize getStorageSize() const;
const VkMemoryRequirements getMemoryRequirements() const;
void bind(VkDeviceMemory pDeviceMemory, VkDeviceSize pMemoryOffset);
void copyTo(VkImage dstImage, const VkImageCopy& pRegion);
void copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion);
void copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion);
private:
void* getTexelPointer(const VkOffset3D& offset) const;
VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D& offset) const;
int rowPitchBytes() const;
int slicePitchBytes() const;
int bytesPerTexel() const;
int getBorder() const;
VkDeviceMemory deviceMemory = nullptr;
VkDeviceSize memoryOffset = 0;
VkImageCreateFlags flags = 0;
VkImageType imageType = VK_IMAGE_TYPE_2D;
VkFormat format = VK_FORMAT_UNDEFINED;
VkExtent3D extent = {0, 0, 0};
uint32_t mipLevels = 0;
uint32_t arrayLayers = 0;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
};
static inline Image* Cast(VkImage object)
......
......@@ -551,7 +551,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device, VkImage image,
TRACE("(VkDevice device = 0x%X, VkImage image = 0x%X, VkDeviceMemory memory = 0x%X, VkDeviceSize memoryOffset = %d)",
device, image, memory, memoryOffset);
UNIMPLEMENTED();
vk::Cast(image)->bind(memory, memoryOffset);
return VK_SUCCESS;
}
......@@ -569,7 +569,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(VkDevice device, VkImage
TRACE("(VkDevice device = 0x%X, VkImage image = 0x%X, VkMemoryRequirements* pMemoryRequirements = 0x%X)",
device, image, pMemoryRequirements);
UNIMPLEMENTED();
*pMemoryRequirements = vk::Cast(image)->getMemoryRequirements();
}
VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
......
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