Skip to content

Commit fef2d20

Browse files
TextureLoader: fix pitched source data size
Size raw image blobs through the final active row instead of requiring trailing padding, and cover both borrowed and premultiplied texture data paths.
1 parent e637cfc commit fef2d20

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

Tests/DiligentToolsTest/src/TextureLoaderTest.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,59 @@ TEST(Tools_TextureLoader, CopiesTextureDataWithSourcePadding)
116116
EXPECT_TRUE(std::equal(ExpectedPixels.begin(), ExpectedPixels.end(), pCopiedPixels));
117117
}
118118

119+
TEST(Tools_TextureLoader, SupportsPitchedTextureDataWithoutFinalRowPadding)
120+
{
121+
constexpr Uint32 Width = 3;
122+
constexpr Uint32 Height = 2;
123+
constexpr Uint32 RowSize = Width * 4;
124+
constexpr Uint32 RowStride = 16;
125+
constexpr Uint32 SourceDataSize = (Height - 1) * RowStride + RowSize;
126+
127+
// The source ends at the final active pixel; there is no padding after the last row.
128+
const std::array<Uint8, SourceDataSize> Pixels{
129+
1, 2, 3, 255, 4, 5, 6, 255, 7, 8, 9, 255,
130+
0xAA, 0xBB, 0xCC, 0xDD,
131+
10, 11, 12, 255, 13, 14, 15, 255, 16, 17, 18, 255};
132+
133+
TextureDesc Desc = MakeRGBA8TextureDesc();
134+
Desc.Width = Width;
135+
Desc.Height = Height;
136+
137+
TextureSubResData Subres{Pixels.data(), RowStride};
138+
TextureData TexData{&Subres, 1};
139+
140+
TextureLoadInfo LoadInfo{Desc.Name};
141+
LoadInfo.Format = Desc.Format;
142+
LoadInfo.MipLevels = 1;
143+
LoadInfo.GenerateMips = False;
144+
145+
const auto CheckPixels = [&](ITextureLoader* pLoader, bool ExpectCopy) {
146+
ASSERT_NE(pLoader, nullptr);
147+
148+
const TextureSubResData& LoadedSubres = pLoader->GetSubresourceData(0);
149+
ASSERT_NE(LoadedSubres.pData, nullptr);
150+
EXPECT_EQ(LoadedSubres.Stride, RowStride);
151+
EXPECT_EQ(LoadedSubres.pData != Pixels.data(), ExpectCopy);
152+
153+
const Uint8* pLoadedPixels = static_cast<const Uint8*>(LoadedSubres.pData);
154+
for (Uint32 Row = 0; Row < Height; ++Row)
155+
{
156+
EXPECT_TRUE(std::equal(Pixels.data() + Row * RowStride,
157+
Pixels.data() + Row * RowStride + RowSize,
158+
pLoadedPixels + Row * LoadedSubres.Stride));
159+
}
160+
};
161+
162+
RefCntAutoPtr<ITextureLoader> pBorrowedLoader;
163+
CreateTextureLoaderFromTextureData(Desc, TexData, false, &LoadInfo, &pBorrowedLoader);
164+
CheckPixels(pBorrowedLoader, false);
165+
166+
LoadInfo.PermultiplyAlpha = True;
167+
RefCntAutoPtr<ITextureLoader> pPremultipliedLoader;
168+
CreateTextureLoaderFromTextureData(Desc, TexData, false, &LoadInfo, &pPremultipliedLoader);
169+
CheckPixels(pPremultipliedLoader, true);
170+
}
171+
119172
TEST(Tools_TextureLoader, HandlesArrayMipSubresources)
120173
{
121174
TextureDesc Desc;

TextureLoader/src/TextureLoaderImpl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,14 @@ static RefCntAutoPtr<Image> CreateImageFromTextureData(const TextureDesc& Te
224224
ImgDesc.NumComponents = FmtAttribs.NumComponents;
225225
ImgDesc.RowStride = StaticCast<Uint32>(Subres.Stride);
226226

227+
const Uint32 RowCount = GetSubresourceRowCount(TexDesc, MipProps);
228+
VERIFY_EXPR(RowCount > 0);
229+
const Uint64 SourceDataSize = Uint64{RowCount - 1} * Subres.Stride + MipProps.RowSize;
230+
227231
RefCntAutoPtr<IDataBlob> pPixels;
228232
if (TexLoadInfo.PermultiplyAlpha && ImgDesc.NumComponents == 4)
229233
{
230-
pPixels = DataBlobImpl::Create(TexLoadInfo.pAllocator, size_t{ImgDesc.RowStride} * size_t{ImgDesc.Height});
234+
pPixels = DataBlobImpl::Create(TexLoadInfo.pAllocator, StaticCast<size_t>(SourceDataSize));
231235
std::memcpy(pPixels->GetDataPtr(), Subres.pData, pPixels->GetSize());
232236

233237
PremultiplyAlphaAttribs PremultAttribs;
@@ -242,7 +246,7 @@ static RefCntAutoPtr<Image> CreateImageFromTextureData(const TextureDesc& Te
242246
}
243247
else
244248
{
245-
pPixels = ProxyDataBlob::Create(Subres.pData, StaticCast<size_t>(Subres.DepthStride));
249+
pPixels = ProxyDataBlob::Create(Subres.pData, StaticCast<size_t>(SourceDataSize));
246250
}
247251

248252
RefCntAutoPtr<Image> pImage;

0 commit comments

Comments
 (0)