Skip to content

Commit 7ffce76

Browse files
committed
[Misc] Replaced RenderSystem::CopyTextureImageData() with ConvertImageBuffer().
- Deprecated RenderSystem::CopyTextureImageData(): Use global ConvertImageBuffer() function instead. - Deprecated RenderSystem::AssertImageDataSize(): Use LLGL_VERIFY() macro instead. - Fixed global function ConvertImageBuffer(): The depth-stencil case did not return a value. - Allow ConvertImageBuffer() function to also copy the source to destination buffer as is if requested. - Make ConvertImageBuffer() return the number of bytes that have been written to.
1 parent da14b3b commit 7ffce76

File tree

9 files changed

+101
-137
lines changed

9 files changed

+101
-137
lines changed

include/LLGL/ImageFlags.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,28 +201,36 @@ struct LLGL_DEPRECATED("LLGL::DstImageDescriptor is deprecated since 0.04b; Use
201201

202202
/**
203203
\brief Converts the image format and data type of the source image (only uncompressed color formats).
204+
204205
\param[in] srcImageView Specifies the source image view.
205206
\param[out] dstImageView Specifies the destination image view.
206207
\param[in] extent Specifies the extent of the image. This is required
207208
\param[in] threadCount Specifies the number of threads to use for conversion.
208209
If this is less than 2, no multi-threading is used. If this is equal to \c LLGL_MAX_THREAD_COUNT,
209210
the maximal count of threads the system supports will be used (e.g. 4 on a quad-core processor). By default 0.
210-
\return True if any conversion was necessary. Otherwise, no conversion was necessary and the destination buffer is not modified!
211+
\param[in] copyUnchangedImage Specifies whether to copy the source buffer into the destination buffer if no conversion was necessary. By default false.
212+
213+
\return Number of bytes that have been written to the destination buffer.
214+
If this is 0, no conversion was necessary and the destination buffer is not modified.
215+
211216
\note Compressed images and depth-stencil images cannot be converted with this function.
217+
212218
\throw std::invalid_argument If a compressed image format is specified either as source or destination.
213219
\throw std::invalid_argument If a depth-stencil format is specified either as source or destination.
214220
\throw std::invalid_argument If the source buffer size is not a multiple of the source data type size times the image format size.
215221
\throw std::invalid_argument If the source buffer is a null pointer.
216222
\throw std::invalid_argument If the destination buffer size does not match the required output buffer size.
217223
\throw std::invalid_argument If the destination buffer is a null pointer.
224+
218225
\see LLGL_MAX_THREAD_COUNT
219226
\see GetMemoryFootprint
220227
*/
221-
LLGL_EXPORT bool ConvertImageBuffer(
228+
LLGL_EXPORT std::size_t ConvertImageBuffer(
222229
const ImageView& srcImageView,
223230
const MutableImageView& dstImageView,
224231
const Extent3D& extent,
225-
unsigned threadCount = 0
232+
unsigned threadCount = 0,
233+
bool copyUnchangedImage = false
226234
);
227235

228236
/**
@@ -231,28 +239,34 @@ LLGL_EXPORT bool ConvertImageBuffer(
231239
This must only be used for tightly packed image buffer, i.e. with a row stride of zero.
232240
\see ConvertImageBuffer(const ImageView&, const MutableImageView&, const Extent3D&, unsigned)
233241
*/
234-
LLGL_EXPORT bool ConvertImageBuffer(
242+
LLGL_EXPORT std::size_t ConvertImageBuffer(
235243
const ImageView& srcImageView,
236244
const MutableImageView& dstImageView,
237-
unsigned threadCount = 0
245+
unsigned threadCount = 0,
246+
bool copyUnchangedImage = false
238247
);
239248

240249
/**
241250
\brief Converst the image format and data type of the source image (only uncompressed color formats) and returns the new generated image buffer.
251+
242252
\param[in] srcImageView Specifies the source image view.
243253
\param[in] dstFormat Specifies the destination image format.
244254
\param[in] dstDataType Specifies the destination image data type.
245255
\param[in] extent Specifies the extent of the image. This is required
246256
\param[in] threadCount Specifies the number of threads to use for conversion.
247257
If this is less than 2, no multi-threading is used. If this is equal to \c LLGL_MAX_THREAD_COUNT,
248258
the maximal count of threads the system supports will be used (e.g. 4 on a quad-core processor). By default 0.
259+
249260
\return Byte buffer with the converted image data or null if no conversion is necessary.
250261
This can be casted to the respective target data type (e.g. <code>unsigned char</code>, <code>int</code>, <code>float</code> etc.).
262+
251263
\note Compressed images and depth-stencil images cannot be converted.
264+
252265
\throw std::invalid_argument If a compressed image format is specified either as source or destination.
253266
\throw std::invalid_argument If a depth-stencil format is specified either as source or destination.
254267
\throw std::invalid_argument If the source buffer size is not a multiple of the source data type size times the image format size.
255268
\throw std::invalid_argument If the source buffer is a null pointer.
269+
256270
\see LLGL_MAX_THREAD_COUNT
257271
\see GetMemoryFootprint
258272
*/

include/LLGL/RenderSystem.h

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,15 @@ class LLGL_EXPORT RenderSystem : public Interface
191191

192192
/**
193193
\brief Returns basic renderer information.
194-
\remarks This is not a constant member function because the first call will invoke the query,
195-
while subsequent calls with return the cached information.
194+
\remarks This is not a constant member function because the first call invokes the query,
195+
while subsequent calls return the cached information.
196196
*/
197197
const RendererInfo& GetRendererInfo();
198198

199199
/**
200200
\brief Returns the rendering capabilities.
201-
\remarks This is not a constant member function because the first call will invoke the query,
202-
while subsequent calls with return the cached information.
201+
\remarks This is not a constant member function because the first call invokes the query,
202+
while subsequent calls return the cached information.
203203
*/
204204
const RenderingCapabilities& GetRenderingCaps();
205205

@@ -672,11 +672,11 @@ class LLGL_EXPORT RenderSystem : public Interface
672672
void Errorf(const char* format, ...);
673673

674674
//! \deprecated Since 0.04b; Implement QueryRendererDetails() instead!
675-
LLGL_DEPRECATED("RenderSystem::SetRendererInfo is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
675+
LLGL_DEPRECATED("RenderSystem::SetRendererInfo() is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
676676
void SetRendererInfo(const RendererInfo& info);
677677

678678
//! \deprecated Since 0.04b; Implement QueryRendererDetails() instead!
679-
LLGL_DEPRECATED("RenderSystem::SetRendererInfo is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
679+
LLGL_DEPRECATED("RenderSystem::SetRendererInfo() is deprecated since 0.04b; Implement QueryRendererDetails() instead!")
680680
void SetRenderingCaps(const RenderingCapabilities& caps);
681681

682682
protected:
@@ -701,15 +701,10 @@ class LLGL_EXPORT RenderSystem : public Interface
701701
//! Validates the specified shader descriptor.
702702
static void AssertCreateShader(const ShaderDescriptor& shaderDesc);
703703

704-
//! Validates the specified image data size against the required size (in bytes).
704+
LLGL_DEPRECATED("RenderSystem::AssertImageDataSize() is deprecated since 0.04b; Use LLGL_VERIFY() macro instead!")
705705
static void AssertImageDataSize(std::size_t dataSize, std::size_t requiredDataSize, const char* useCase = nullptr);
706706

707-
/**
708-
\brief Copies the specified source image to the destination image.
709-
\remarks This function also performs image conversion if there is a mismatch between source and destination format.
710-
\returns The number of bytes that have been written into the destination image buffer.
711-
\see ConvertImageBuffer
712-
*/
707+
LLGL_DEPRECATED("RenderSystem::CopyTextureImageData() is deprecated since 0.04b; Use ConvertOrCopyImageBuffer() instead!")
713708
static std::size_t CopyTextureImageData(
714709
const MutableImageView& dstImageView,
715710
const ImageView& srcImageView,

include/LLGL/RenderSystemFlags.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ struct RenderSystemFlags
239239
/**
240240
\brief Renderer identification number enumeration.
241241
\remarks There are several IDs for reserved future renderers, which are currently not supported (and maybe never supported).
242-
You can use an ID greater than 'RendererID::Reserved' (which has a value of 0x000000ff) for your own renderer.
242+
You can use an ID greater than \c RendererID::Reserved (which has a value of 0x000000FF) for your own renderer.
243243
Or use one of the pre-defined IDs if you want to implement your own OpenGL/ Direct3D or whatever renderer.
244244
\see RendererInfo::rendererID
245245
*/

sources/Core/ImageFlags.cpp

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ static void ConvertImageBufferDataTypeWorker(
238238
}
239239
}
240240

241-
static void ConvertImageBufferDataType(
241+
static std::size_t ConvertImageBufferDataType(
242242
const ImageView& srcImageView,
243243
const MutableImageView& dstImageView,
244244
const Extent3D& extent,
@@ -270,6 +270,8 @@ static void ConvertImageBufferDataType(
270270
numPixels,
271271
threadCount
272272
);
273+
274+
return requiredDstBufferSize;
273275
}
274276

275277
static void SetVariantMinMax(DataType dataType, Variant& var, bool setMin)
@@ -586,7 +588,7 @@ static void ConvertImageBufferFormatWorker(
586588
}
587589
}
588590

589-
static void ConvertImageBufferFormat(
591+
static std::size_t ConvertImageBufferFormat(
590592
const ImageView& srcImageView,
591593
const MutableImageView& dstImageView,
592594
const Extent3D& extent,
@@ -618,6 +620,8 @@ static void ConvertImageBufferFormat(
618620
numPixels,
619621
threadCount
620622
);
623+
624+
return requiredDstBufferSize;
621625
}
622626

623627
static void ValidateSourceImageView(const ImageView& imageView)
@@ -652,19 +656,13 @@ static void ValidateImageConversionParams(
652656

653657
/* ----- Public functions ----- */
654658

655-
LLGL_EXPORT bool ConvertImageBuffer(
659+
LLGL_EXPORT std::size_t ConvertImageBuffer(
656660
const ImageView& srcImageView,
657661
const MutableImageView& dstImageView,
658662
const Extent3D& extent,
659-
unsigned threadCount)
663+
unsigned threadCount,
664+
bool copyUnchangedImage)
660665
{
661-
if (srcImageView.format == dstImageView.format &&
662-
srcImageView.dataType == dstImageView.dataType &&
663-
srcImageView.rowStride == 0)
664-
{
665-
return false;
666-
}
667-
668666
/* Validate input parameters */
669667
ValidateSourceImageView(srcImageView);
670668
ValidateDestinationImageView(dstImageView);
@@ -676,7 +674,7 @@ LLGL_EXPORT bool ConvertImageBuffer(
676674
if (IsDepthOrStencilFormat(srcImageView.format))
677675
{
678676
/* Convert depth-stencil image format */
679-
ConvertImageBufferFormat(srcImageView, dstImageView, extent, threadCount);
677+
return ConvertImageBufferFormat(srcImageView, dstImageView, extent, threadCount);
680678
}
681679
else if (srcImageView.dataType != dstImageView.dataType && srcImageView.format != dstImageView.format)
682680
{
@@ -705,21 +703,17 @@ LLGL_EXPORT bool ConvertImageBuffer(
705703
};
706704

707705
/* Convert image format */
708-
ConvertImageBufferFormat(intermediateSrcImageView, dstImageView, extent, threadCount);
709-
710-
return true;
706+
return ConvertImageBufferFormat(intermediateSrcImageView, dstImageView, extent, threadCount);
711707
}
712708
else if (srcImageView.dataType != dstImageView.dataType)
713709
{
714710
/* Convert image data type */
715-
ConvertImageBufferDataType(srcImageView, dstImageView, extent, threadCount);
716-
return true;
711+
return ConvertImageBufferDataType(srcImageView, dstImageView, extent, threadCount);
717712
}
718713
else if (srcImageView.format != dstImageView.format)
719714
{
720715
/* Convert image format */
721-
ConvertImageBufferFormat(srcImageView, dstImageView, extent, threadCount);
722-
return true;
716+
return ConvertImageBufferFormat(srcImageView, dstImageView, extent, threadCount);
723717
}
724718
else if (srcImageView.rowStride != 0)
725719
{
@@ -737,11 +731,22 @@ LLGL_EXPORT bool ConvertImageBuffer(
737731
srcImageView.rowStride,
738732
0
739733
);
740-
return true;
734+
const std::size_t numPixels = (extent.width * extent.height * extent.depth);
735+
return (numPixels * bpp);
741736
}
742737
}
743738

744-
return false;
739+
/* Copy data directly into destination buffer if no conversion was necessary */
740+
if (copyUnchangedImage)
741+
{
742+
const std::size_t numPixels = (extent.width * extent.height * extent.depth);
743+
const std::size_t requiredImageSize = GetMemoryFootprint(dstImageView.format, dstImageView.dataType, numPixels);
744+
LLGL_ASSERT(dstImageView.dataSize >= requiredImageSize);
745+
LLGL_ASSERT(srcImageView.dataSize >= requiredImageSize);
746+
::memcpy(dstImageView.data, srcImageView.data, requiredImageSize);
747+
}
748+
749+
return 0;
745750
}
746751

747752
LLGL_EXPORT bool ConvertImageBuffer(
@@ -933,24 +938,30 @@ LLGL_EXPORT void CopyImageBufferRegion(
933938
ValidateSourceImageView(srcImageView);
934939
ValidateDestinationImageView(dstImageView);
935940

936-
if (srcImageView.format != dstImageView.format || srcImageView.dataType != dstImageView.dataType)
937-
LLGL_TRAP("cannot copy image buffer region with source and destination images having different format or data type");
941+
LLGL_ASSERT(
942+
srcImageView.format == dstImageView.format && srcImageView.dataType == dstImageView.dataType,
943+
"LLGL::CopyImageBufferRegion() only supports source and destination buffers of equal format and type"
944+
);
938945

939946
const std::uint32_t bpp = static_cast<std::uint32_t>(GetMemoryFootprint(dstImageView.format, dstImageView.dataType, 1));
940947

941948
/* Validate destination image boundaries */
942949
const std::size_t dstPos = GetFlattenedImageBufferPos(dstOffset.x, dstOffset.y, dstOffset.z, dstRowStride, dstLayerStride, bpp);
943950
const std::size_t dstPosEnd = GetFlattenedImageBufferPosEnd(dstOffset, extent, dstRowStride, dstLayerStride, bpp);
944951

945-
if (dstPosEnd > dstImageView.dataSize)
946-
LLGL_TRAP("destination image buffer region out of range");
952+
LLGL_ASSERT(
953+
dstImageView.dataSize >= dstPosEnd,
954+
"destination image buffer size is too small for copy operation"
955+
);
947956

948957
/* Validate source image boundaries */
949958
const std::size_t srcPos = GetFlattenedImageBufferPos(srcOffset.x, srcOffset.y, srcOffset.z, srcRowStride, srcLayerStride, bpp);
950959
const std::size_t srcPosEnd = GetFlattenedImageBufferPosEnd(srcOffset, extent, srcRowStride, srcLayerStride, bpp);
951960

952-
if (srcPosEnd > srcImageView.dataSize)
953-
LLGL_TRAP("source image buffer region out of range");
961+
LLGL_ASSERT(
962+
srcImageView.dataSize >= srcPosEnd,
963+
"source image buffer size is too small for copy operation"
964+
);
954965

955966
/* Copy image buffer region */
956967
BitBlit(

sources/Core/ImageUtils.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "ImageUtils.h"
9+
#include "Assertion.h"
910
#include <LLGL/Types.h>
1011
#include <LLGL/Utils/ForRange.h>
1112
#include <cstdint>
@@ -34,8 +35,20 @@ LLGL_EXPORT void BitBlit(
3435
dstRowStride = std::max(dstRowStride, rowLength);
3536
srcRowStride = std::max(srcRowStride, rowLength);
3637

37-
dstLayerStride = std::max(dstLayerStride, layerLength);
38-
srcLayerStride = std::max(srcLayerStride, layerLength);
38+
const std::uint32_t dstLayerLength = dstRowStride * extent.height;
39+
const std::uint32_t srcLayerLength = srcRowStride * extent.height;
40+
41+
LLGL_ASSERT(
42+
dstLayerStride == 0 || dstLayerStride >= dstLayerLength,
43+
"'dstLayerStride' must be 0 or at least %u, but %u was specified", dstLayerLength, dstLayerStride
44+
);
45+
LLGL_ASSERT(
46+
srcLayerStride == 0 || srcLayerStride >= srcLayerLength,
47+
"'srcLayerStride' must be 0 or at least %u, but %u was specified", srcLayerLength, srcLayerStride
48+
);
49+
50+
dstLayerStride = std::max(dstLayerLength, std::max(dstLayerStride, layerLength));
51+
srcLayerStride = std::max(srcLayerLength, std::max(srcLayerStride, layerLength));
3952

4053
if (srcRowStride == dstRowStride && rowLength == dstRowStride)
4154
{

sources/Renderer/Direct3D11/D3D11RenderSystem.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ void D3D11RenderSystem::ReadTexture(Texture& texture, const TextureRegion& textu
349349
D3D11ThrowIfFailed(hr, "failed to map D3D11 texture copy resource", textureD3D.GetNative());
350350

351351
/* Copy host visible resource to CPU accessible resource */
352-
const ImageView intermediateSrcView{ formatAttribs.format, formatAttribs.dataType, mappedSubresource.pData, mappedSubresource.DepthPitch };
353-
const std::size_t bytesWritten = RenderSystem::CopyTextureImageData(intermediateDstView, intermediateSrcView, numTexelsPerLayer, extent.width, mappedSubresource.RowPitch);
352+
const ImageView intermediateSrcView{ formatAttribs.format, formatAttribs.dataType, mappedSubresource.pData, mappedSubresource.RowPitch };
353+
const std::size_t bytesWritten = RenderSystem::CopyTextureImageData(intermediateDstView, intermediateSrcView, numTexelsPerLayer, extent.width);
354354

355355
/* Unmap resource */
356356
context_->Unmap(texCopy.Get(), subresource);

sources/Renderer/Direct3D12/D3D12RenderSystem.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,13 @@ void D3D12RenderSystem::ReadTexture(Texture& texture, const TextureRegion& textu
255255
const Format format = textureD3D.GetFormat();
256256
const FormatAttributes& formatAttribs = GetFormatAttribs(format);
257257
const Extent3D extent = CalcTextureExtent(textureD3D.GetType(), textureRegion.extent);
258-
const std::uint32_t numTexelsPerLayer = extent.width * extent.height * extent.depth;
259258

260259
void* mappedData = nullptr;
261260
HRESULT hr = readbackBuffer->Map(0, nullptr, &mappedData);
262261
DXThrowIfFailed(hr, "failed to map D3D12 texture copy resource");
263262

264263
const char* srcData = static_cast<const char*>(mappedData);
265-
ImageView intermediateSrcView{ formatAttribs.format, formatAttribs.dataType, srcData, layerStride };
264+
ImageView intermediateSrcView{ formatAttribs.format, formatAttribs.dataType, srcData, layerStride, rowStride };
266265

267266
if (isStencilOnlyFormat)
268267
{
@@ -278,7 +277,7 @@ void D3D12RenderSystem::ReadTexture(Texture& texture, const TextureRegion& textu
278277
for_range(arrayLayer, textureRegion.subresource.numArrayLayers)
279278
{
280279
/* Copy CPU accessible buffer to output data */
281-
RenderSystem::CopyTextureImageData(intermediateDstView, intermediateSrcView, numTexelsPerLayer, extent.width, rowStride);
280+
ConvertImageBuffer(intermediateSrcView, intermediateDstView, extent, LLGL_MAX_THREAD_COUNT, true);
282281

283282
/* Move destination image pointer to next layer */
284283
intermediateDstView.data = static_cast<char*>(intermediateDstView.data) + layerSize;

0 commit comments

Comments
 (0)