Renderer/Texture: Implement Update of a region + inherit AbstractImage
This commit is contained in:
@@ -73,7 +73,7 @@ namespace Nz
|
||||
return m_params.type;
|
||||
}
|
||||
|
||||
bool OpenGLTexture::Update(const void* ptr)
|
||||
bool OpenGLTexture::Update(const void* ptr, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
{
|
||||
auto format = DescribeTextureFormat(m_params.pixelFormat);
|
||||
assert(format);
|
||||
@@ -90,6 +90,9 @@ namespace Nz
|
||||
else
|
||||
context.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
context.glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth);
|
||||
context.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight);
|
||||
|
||||
switch (m_params.type)
|
||||
{
|
||||
case ImageType::E1D:
|
||||
@@ -99,7 +102,7 @@ namespace Nz
|
||||
break;
|
||||
|
||||
case ImageType::E2D:
|
||||
m_texture.TexSubImage2D(GL::TextureTarget::Target2D, 0, 0, 0, m_params.width, m_params.height, format->format, format->type, ptr);
|
||||
m_texture.TexSubImage2D(GL::TextureTarget::Target2D, level, box.x, box.y, box.width, box.height, format->format, format->type, ptr);
|
||||
break;
|
||||
|
||||
case ImageType::E2D_Array:
|
||||
@@ -115,7 +118,7 @@ namespace Nz
|
||||
|
||||
for (GL::TextureTarget face : { GL::TextureTarget::CubemapPositiveX, GL::TextureTarget::CubemapNegativeX, GL::TextureTarget::CubemapPositiveY, GL::TextureTarget::CubemapNegativeY, GL::TextureTarget::CubemapPositiveZ, GL::TextureTarget::CubemapNegativeZ })
|
||||
{
|
||||
m_texture.TexSubImage2D(face, 0, 0, 0, m_params.width, m_params.height, format->format, format->type, facePtr);
|
||||
m_texture.TexSubImage2D(face, level, box.x, box.y, box.width, box.height, format->format, format->type, facePtr);
|
||||
facePtr += faceSize;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1248,41 +1248,7 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::Update(const UInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (m_sharedImage == &emptyImage)
|
||||
{
|
||||
NazaraError("Image must be valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pixels)
|
||||
{
|
||||
NazaraError("Invalid pixel source");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level >= m_sharedImage->levels.size())
|
||||
{
|
||||
NazaraError("Level out of bounds (" + NumberToString(level) + " >= " + NumberToString(m_sharedImage->levels.size()) + ')');
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
EnsureOwnership();
|
||||
|
||||
Copy(m_sharedImage->levels[level].get(), pixels, m_sharedImage->format,
|
||||
GetLevelSize(m_sharedImage->width, level),
|
||||
GetLevelSize(m_sharedImage->height, level),
|
||||
GetLevelSize(m_sharedImage->depth, level),
|
||||
0, 0,
|
||||
srcWidth, srcHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
bool Image::Update(const void* pixels, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (m_sharedImage == &emptyImage)
|
||||
@@ -1328,7 +1294,7 @@ namespace Nz
|
||||
UInt8 bpp = PixelFormatInfo::GetBytesPerPixel(m_sharedImage->format);
|
||||
UInt8* dstPixels = GetPixelPtr(m_sharedImage->levels[level].get(), bpp, box.x, box.y, box.z, width, height);
|
||||
|
||||
Copy(dstPixels, pixels, m_sharedImage->format,
|
||||
Copy(dstPixels, static_cast<const UInt8*>(pixels), m_sharedImage->format,
|
||||
box.width, box.height, box.depth,
|
||||
width, height,
|
||||
srcWidth, srcHeight);
|
||||
@@ -1336,11 +1302,6 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::Update(const UInt8* pixels, const Rectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
{
|
||||
return Update(pixels, Boxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
||||
}
|
||||
|
||||
Image& Image::operator=(const Image& image)
|
||||
{
|
||||
ReleaseImage();
|
||||
|
||||
@@ -167,9 +167,9 @@ namespace Nz
|
||||
return m_params.type;
|
||||
}
|
||||
|
||||
bool VulkanTexture::Update(const void* ptr)
|
||||
bool VulkanTexture::Update(const void* ptr, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
|
||||
{
|
||||
std::size_t textureSize = m_params.width * m_params.height * m_params.depth * PixelFormatInfo::GetBytesPerPixel(m_params.pixelFormat);
|
||||
std::size_t textureSize = box.width * box.height * box.depth * PixelFormatInfo::GetBytesPerPixel(m_params.pixelFormat);
|
||||
if (m_params.type == ImageType::Cubemap)
|
||||
textureSize *= 6;
|
||||
|
||||
@@ -198,7 +198,44 @@ namespace Nz
|
||||
vmaDestroyBuffer(m_device.GetMemoryAllocator(), stagingBuffer, stagingAllocation);
|
||||
});
|
||||
|
||||
std::memcpy(allocationInfo.pMappedData, ptr, textureSize);
|
||||
if (srcWidth == 0)
|
||||
srcWidth = box.width;
|
||||
|
||||
if (srcHeight == 0)
|
||||
srcHeight = box.height;
|
||||
|
||||
if (srcWidth == box.width && srcHeight == box.height)
|
||||
std::memcpy(allocationInfo.pMappedData, ptr, textureSize);
|
||||
else
|
||||
{
|
||||
unsigned int dstWidth = box.width;
|
||||
unsigned int dstHeight = box.height;
|
||||
|
||||
unsigned int bpp = PixelFormatInfo::GetBytesPerPixel(m_params.pixelFormat);
|
||||
unsigned int lineStride = box.width * bpp;
|
||||
unsigned int dstLineStride = dstWidth * bpp;
|
||||
unsigned int dstFaceStride = dstLineStride * dstHeight;
|
||||
unsigned int srcLineStride = srcWidth * bpp;
|
||||
unsigned int srcFaceStride = srcLineStride * srcHeight;
|
||||
|
||||
const UInt8* source = static_cast<const UInt8*>(ptr);
|
||||
UInt8* destination = static_cast<UInt8*>(allocationInfo.pMappedData);
|
||||
for (unsigned int i = 0; i < box.depth; ++i)
|
||||
{
|
||||
UInt8* dstFacePtr = destination;
|
||||
const UInt8* srcFacePtr = source;
|
||||
for (unsigned int y = 0; y < box.height; ++y)
|
||||
{
|
||||
std::memcpy(dstFacePtr, srcFacePtr, lineStride);
|
||||
|
||||
dstFacePtr += dstLineStride;
|
||||
srcFacePtr += srcLineStride;
|
||||
}
|
||||
|
||||
destination += dstFaceStride;
|
||||
source += srcFaceStride;
|
||||
}
|
||||
}
|
||||
|
||||
Vk::AutoCommandBuffer copyCommandBuffer = m_device.AllocateCommandBuffer(QueueType::Graphics);
|
||||
if (!copyCommandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT))
|
||||
@@ -206,7 +243,7 @@ namespace Nz
|
||||
|
||||
VkImageSubresourceLayers subresourceLayers = { //< FIXME
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
0, //< mipLevel
|
||||
level, //< mipLevel
|
||||
0, //< baseArrayLayer
|
||||
UInt32((m_params.type == ImageType::Cubemap) ? 6 : 1) //< layerCount
|
||||
};
|
||||
@@ -219,9 +256,22 @@ namespace Nz
|
||||
subresourceLayers.layerCount //< layerCount
|
||||
};
|
||||
|
||||
VkBufferImageCopy region = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
subresourceLayers,
|
||||
{ // imageOffset
|
||||
box.x, box.y, box.z
|
||||
},
|
||||
{ // imageExtent
|
||||
box.width, box.height, box.depth
|
||||
}
|
||||
};
|
||||
|
||||
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
|
||||
|
||||
copyCommandBuffer->CopyBufferToImage(stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceLayers, m_params.width, m_params.height, m_params.depth);
|
||||
copyCommandBuffer->CopyBufferToImage(stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceLayers, region);
|
||||
|
||||
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user