Skip to content

Commit 8335f79

Browse files
committed
VRTDerivedRasterBand::IRasterIO(): refine check to decide for splitting or not based on the actual number of contributing sources
1 parent e40137c commit 8335f79

File tree

1 file changed

+110
-50
lines changed

1 file changed

+110
-50
lines changed

frmts/vrt/vrtderivedrasterband.cpp

Lines changed: 110 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,56 @@ CPLErr VRTDerivedRasterBand::GetPixelFunctionArguments(
982982
return CE_None;
983983
}
984984

985+
/************************************************************************/
986+
/* CreateMapBufferIdxToSourceIdx() */
987+
/************************************************************************/
988+
989+
static bool CreateMapBufferIdxToSourceIdx(
990+
const std::vector<std::unique_ptr<VRTSource>> &apoSources,
991+
bool bSkipNonContributingSources, int nXOff, int nYOff, int nXSize,
992+
int nYSize, int nBufXSize, int nBufYSize, GDALRasterIOExtraArg *psExtraArg,
993+
bool &bCreateMapBufferIdxToSourceIdxHasRun,
994+
std::vector<int> &anMapBufferIdxToSourceIdx,
995+
bool &bSkipOutputBufferInitialization)
996+
{
997+
CPLAssert(!bCreateMapBufferIdxToSourceIdxHasRun);
998+
bCreateMapBufferIdxToSourceIdxHasRun = true;
999+
anMapBufferIdxToSourceIdx.reserve(apoSources.size());
1000+
for (int iSource = 0; iSource < static_cast<int>(apoSources.size());
1001+
iSource++)
1002+
{
1003+
if (bSkipNonContributingSources &&
1004+
apoSources[iSource]->IsSimpleSource())
1005+
{
1006+
bool bError = false;
1007+
double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
1008+
int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1009+
int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1010+
auto poSource =
1011+
static_cast<VRTSimpleSource *>(apoSources[iSource].get());
1012+
if (!poSource->GetSrcDstWindow(
1013+
nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1014+
psExtraArg->eResampleAlg, &dfReqXOff, &dfReqYOff,
1015+
&dfReqXSize, &dfReqYSize, &nReqXOff, &nReqYOff, &nReqXSize,
1016+
&nReqYSize, &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize,
1017+
bError))
1018+
{
1019+
if (bError)
1020+
{
1021+
return false;
1022+
}
1023+
1024+
// Skip non contributing source
1025+
bSkipOutputBufferInitialization = false;
1026+
continue;
1027+
}
1028+
}
1029+
1030+
anMapBufferIdxToSourceIdx.push_back(iSource);
1031+
}
1032+
return true;
1033+
}
1034+
9851035
/************************************************************************/
9861036
/* IRasterIO() */
9871037
/************************************************************************/
@@ -1142,6 +1192,10 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
11421192
}
11431193
const int nSrcTypeSize = GDALGetDataTypeSizeBytes(eSrcType);
11441194

1195+
std::vector<int> anMapBufferIdxToSourceIdx;
1196+
bool bSkipOutputBufferInitialization = !m_papoSources.empty();
1197+
bool bCreateMapBufferIdxToSourceIdxHasRun = false;
1198+
11451199
// If acquiring the region of interest in a single time is going
11461200
// to consume too much RAM, split in halves, and that recursively
11471201
// until we get below m_nAllowedRAMUsage.
@@ -1151,11 +1205,34 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
11511205
m_poPrivate->m_nAllowedRAMUsage /
11521206
(static_cast<int>(m_papoSources.size()) * nSrcTypeSize))
11531207
{
1154-
CPLErr eErr = SplitRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
1155-
pData, nBufXSize, nBufYSize, eBufType,
1156-
nPixelSpace, nLineSpace, psExtraArg);
1157-
if (eErr != CE_Warning)
1158-
return eErr;
1208+
bool bSplit = true;
1209+
if (m_poPrivate->m_bSkipNonContributingSources)
1210+
{
1211+
// More accurate check by comparing against the number of
1212+
// actually contributing sources.
1213+
if (!CreateMapBufferIdxToSourceIdx(
1214+
m_papoSources, m_poPrivate->m_bSkipNonContributingSources,
1215+
nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1216+
psExtraArg, bCreateMapBufferIdxToSourceIdxHasRun,
1217+
anMapBufferIdxToSourceIdx, bSkipOutputBufferInitialization))
1218+
{
1219+
return CE_Failure;
1220+
}
1221+
bSplit =
1222+
!anMapBufferIdxToSourceIdx.empty() &&
1223+
static_cast<GIntBig>(nBufXSize) * nBufYSize >
1224+
m_poPrivate->m_nAllowedRAMUsage /
1225+
(static_cast<int>(anMapBufferIdxToSourceIdx.size()) *
1226+
nSrcTypeSize);
1227+
}
1228+
if (bSplit)
1229+
{
1230+
CPLErr eErr = SplitRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
1231+
pData, nBufXSize, nBufYSize, eBufType,
1232+
nPixelSpace, nLineSpace, psExtraArg);
1233+
if (eErr != CE_Warning)
1234+
return eErr;
1235+
}
11591236
}
11601237

11611238
/* ---- Get pixel function for band ---- */
@@ -1196,51 +1273,32 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
11961273
}
11971274
const int nExtBufXSize = nBufXSize + 2 * nBufferRadius;
11981275
const int nExtBufYSize = nBufYSize + 2 * nBufferRadius;
1199-
int nBufferCount = 0;
12001276

1201-
std::vector<std::unique_ptr<void, VSIFreeReleaser>> apBuffers(
1202-
m_papoSources.size());
1203-
std::vector<int> anMapBufferIdxToSourceIdx(m_papoSources.size());
1204-
bool bSkipOutputBufferInitialization = !m_papoSources.empty();
1205-
for (int iSource = 0; iSource < static_cast<int>(m_papoSources.size());
1206-
iSource++)
1277+
if (!bCreateMapBufferIdxToSourceIdxHasRun)
12071278
{
1208-
if (m_poPrivate->m_bSkipNonContributingSources &&
1209-
m_papoSources[iSource]->IsSimpleSource())
1279+
if (!CreateMapBufferIdxToSourceIdx(
1280+
m_papoSources, m_poPrivate->m_bSkipNonContributingSources,
1281+
nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, psExtraArg,
1282+
bCreateMapBufferIdxToSourceIdxHasRun, anMapBufferIdxToSourceIdx,
1283+
bSkipOutputBufferInitialization))
12101284
{
1211-
bool bError = false;
1212-
double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
1213-
int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1214-
int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1215-
auto poSource =
1216-
static_cast<VRTSimpleSource *>(m_papoSources[iSource].get());
1217-
if (!poSource->GetSrcDstWindow(
1218-
nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1219-
psExtraArg->eResampleAlg, &dfReqXOff, &dfReqYOff,
1220-
&dfReqXSize, &dfReqYSize, &nReqXOff, &nReqYOff, &nReqXSize,
1221-
&nReqYSize, &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize,
1222-
bError))
1223-
{
1224-
if (bError)
1225-
{
1226-
return CE_Failure;
1227-
}
1228-
1229-
// Skip non contributing source
1230-
bSkipOutputBufferInitialization = false;
1231-
continue;
1232-
}
1285+
return CE_Failure;
12331286
}
1234-
1235-
anMapBufferIdxToSourceIdx[nBufferCount] = iSource;
1236-
apBuffers[nBufferCount].reset(
1287+
}
1288+
std::vector<std::unique_ptr<void, VSIFreeReleaser>> apBuffers(
1289+
anMapBufferIdxToSourceIdx.size());
1290+
for (size_t iBuffer = 0; iBuffer < anMapBufferIdxToSourceIdx.size();
1291+
++iBuffer)
1292+
{
1293+
apBuffers[iBuffer].reset(
12371294
VSI_MALLOC3_VERBOSE(nSrcTypeSize, nExtBufXSize, nExtBufYSize));
1238-
if (apBuffers[nBufferCount] == nullptr)
1295+
if (apBuffers[iBuffer] == nullptr)
12391296
{
12401297
return CE_Failure;
12411298
}
12421299

12431300
bool bBufferInit = true;
1301+
const int iSource = anMapBufferIdxToSourceIdx[iBuffer];
12441302
if (m_papoSources[iSource]->IsSimpleSource())
12451303
{
12461304
const auto poSS =
@@ -1279,21 +1337,19 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
12791337
/* ------------------------------------------------------------ */
12801338
if (!m_bNoDataValueSet || m_dfNoDataValue == 0)
12811339
{
1282-
memset(apBuffers[nBufferCount].get(), 0,
1340+
memset(apBuffers[iBuffer].get(), 0,
12831341
static_cast<size_t>(nSrcTypeSize) * nExtBufXSize *
12841342
nExtBufYSize);
12851343
}
12861344
else
12871345
{
1288-
GDALCopyWords64(
1289-
&m_dfNoDataValue, GDT_Float64, 0,
1290-
static_cast<GByte *>(apBuffers[nBufferCount].get()),
1291-
eSrcType, nSrcTypeSize,
1292-
static_cast<GPtrDiff_t>(nExtBufXSize) * nExtBufYSize);
1346+
GDALCopyWords64(&m_dfNoDataValue, GDT_Float64, 0,
1347+
static_cast<GByte *>(apBuffers[iBuffer].get()),
1348+
eSrcType, nSrcTypeSize,
1349+
static_cast<GPtrDiff_t>(nExtBufXSize) *
1350+
nExtBufYSize);
12931351
}
12941352
}
1295-
1296-
++nBufferCount;
12971353
}
12981354

12991355
/* -------------------------------------------------------------------- */
@@ -1309,7 +1365,8 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
13091365
// No contributing sources and SkipNonContributingSources mode ?
13101366
// Do not call the pixel function and just return the 0/nodata initialized
13111367
// output buffer.
1312-
if (nBufferCount == 0 && m_poPrivate->m_bSkipNonContributingSources)
1368+
if (anMapBufferIdxToSourceIdx.empty() &&
1369+
m_poPrivate->m_bSkipNonContributingSources)
13131370
{
13141371
return CE_None;
13151372
}
@@ -1384,7 +1441,9 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
13841441
// Load values for sources into packed buffers.
13851442
CPLErr eErr = CE_None;
13861443
VRTSource::WorkingState oWorkingState;
1387-
for (int iBuffer = 0; iBuffer < nBufferCount && eErr == CE_None; iBuffer++)
1444+
for (size_t iBuffer = 0;
1445+
iBuffer < anMapBufferIdxToSourceIdx.size() && eErr == CE_None;
1446+
iBuffer++)
13881447
{
13891448
const int iSource = anMapBufferIdxToSourceIdx[iBuffer];
13901449
GByte *pabyBuffer = static_cast<GByte *>(apBuffers[iBuffer].get());
@@ -1470,6 +1529,7 @@ CPLErr VRTDerivedRasterBand::IRasterIO(
14701529
}
14711530

14721531
// Apply pixel function.
1532+
const int nBufferCount = static_cast<int>(anMapBufferIdxToSourceIdx.size());
14731533
if (eErr == CE_None && EQUAL(m_poPrivate->m_osLanguage, "Python"))
14741534
{
14751535
// numpy doesn't have native cint16/cint32/cfloat16

0 commit comments

Comments
 (0)