Skip to content

Commit

Permalink
Add support for 'alternative' image view min lod calculation
Browse files Browse the repository at this point in the history
According to ''Image Level(s) Selection" in spec, the image view
minLod value can be used as-is, or floor()-ed.

This change runs verification in affected test twice, once requiring
'preferred' method, falling back to 'alternative' if 'preferred' method fails.

Components: Vulkan

VK-GL-CTS Issue: 3556

Affects: dEQP-VK.texture.*min_lod*

Change-Id: I3af08485dbd99ad8d666c6f19aac3456130c375d
  • Loading branch information
scygan authored and mnetsch committed Mar 10, 2022
1 parent 3b93a38 commit ea32156
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 150 deletions.
243 changes: 140 additions & 103 deletions external/vulkancts/modules/vulkan/texture/vktTextureMipmapTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1053,11 +1053,8 @@ tcu::TestStatus Texture2DLodControlTestInstance::iterate (void)
const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
const bool isTrilinear = m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
tcu::Surface referenceFrame (viewportWidth, viewportHeight);
tcu::Surface errorMask (viewportWidth, viewportHeight);
tcu::LookupPrecision lookupPrec;
tcu::LodPrecision lodPrec;
int numFailedPixels = 0;

lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
Expand All @@ -1066,51 +1063,68 @@ tcu::TestStatus Texture2DLodControlTestInstance::iterate (void)
lodPrec.derivateBits = 10;
lodPrec.lodBits = 8;

for (int gridY = 0; gridY < gridHeight; gridY++)
auto compareAndLogImages = [&] (tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
{
for (int gridX = 0; gridX < gridWidth; gridX++)
{
const int curX = cellWidth*gridX;
const int curY = cellHeight*gridY;
const int curW = gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
const int curH = gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
const int cellNdx = gridY*gridWidth + gridX;

getReferenceParams(refParams,cellNdx);
tcu::Surface referenceFrame (viewportWidth, viewportHeight);
tcu::Surface errorMask (viewportWidth, viewportHeight);

// Compute texcoord.
if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
getBasicTexCoord2DImageViewMinLodIntTexCoord(texCoord);
else
getBasicTexCoord2D(texCoord, cellNdx);

// Render ideal result
sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
refTexture, &texCoord[0], refParams);
int numFailedPixels = 0;

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
for (int gridY = 0; gridY < gridHeight; gridY++)
{
for (int gridX = 0; gridX < gridWidth; gridX++)
{
const int curX = cellWidth*gridX;
const int curY = cellHeight*gridY;
const int curW = gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
const int curH = gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
const int cellNdx = gridY*gridWidth + gridX;

getReferenceParams(refParams,cellNdx);

refParams.imageViewMinLodMode = imageViewLodMode;

// Compute texcoord.
if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
getBasicTexCoord2DImageViewMinLodIntTexCoord(texCoord);
else
getBasicTexCoord2D(texCoord, cellNdx);

// Render ideal result
sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
refTexture, &texCoord[0], refParams);

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
}
}
}

if (numFailedPixels > 0)
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
if (numFailedPixels > 0)
{
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
}
return numFailedPixels;
};

m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

if (numFailedPixels > 0)
int numFailedPixels = compareAndLogImages();

if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
{
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
}

m_context.getTestContext().getLog() << TestLog::EndImageSet;

if (numFailedPixels > 0)
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

{
const bool isOk = numFailedPixels == 0;
return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
Expand Down Expand Up @@ -1315,9 +1329,6 @@ tcu::TestStatus TextureCubeLodControlTestInstance::iterate (void)
{
const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
tcu::Surface referenceFrame (viewportWidth, viewportHeight);
tcu::Surface errorMask (viewportWidth, viewportHeight);
int numFailedPixels = 0;
tcu::LookupPrecision lookupPrec;
tcu::LodPrecision lodPrec;

Expand All @@ -1334,44 +1345,59 @@ tcu::TestStatus TextureCubeLodControlTestInstance::iterate (void)
lodPrec.derivateBits = 10;
lodPrec.lodBits = 6;

for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
{
const int curX = gridLayout[cellNdx].x();
const int curY = gridLayout[cellNdx].y();
const int curW = gridLayout[cellNdx].z();
const int curH = gridLayout[cellNdx].w();
const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
tcu::Surface referenceFrame(viewportWidth, viewportHeight);
tcu::Surface errorMask(viewportWidth, viewportHeight);
int numFailedPixels = 0;

computeQuadTexCoordCube(texCoord, cubeFace);
getReferenceParams(refParams, cellNdx);
for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
{
const int curX = gridLayout[cellNdx].x();
const int curY = gridLayout[cellNdx].y();
const int curW = gridLayout[cellNdx].z();
const int curH = gridLayout[cellNdx].w();
const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);

// Render ideal reference.
computeQuadTexCoordCube(texCoord, cubeFace);
getReferenceParams(refParams, cellNdx);

refParams.imageViewMinLodMode = imageViewLodMode;

// Render ideal reference.
{
tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
}

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
}
if (numFailedPixels > 0)
{
tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
}
return numFailedPixels;
};

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
}

if (numFailedPixels > 0)
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
int numFailedPixels = compareAndLogImages();

if (numFailedPixels > 0)
if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
{
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
}
m_context.getTestContext().getLog() << TestLog::EndImageSet;

m_context.getTestContext().getLog() << TestLog::EndImageSet;
if (numFailedPixels > 0)
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

{
const bool isOk = numFailedPixels == 0;
Expand Down Expand Up @@ -1584,11 +1610,8 @@ tcu::TestStatus Texture3DLodControlTestInstance::iterate (void)
const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
const bool isTrilinear = m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
tcu::Surface referenceFrame (viewportWidth, viewportHeight);
tcu::Surface errorMask (viewportWidth, viewportHeight);
tcu::LookupPrecision lookupPrec;
tcu::LodPrecision lodPrec;
int numFailedPixels = 0;

lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
Expand All @@ -1597,53 +1620,67 @@ tcu::TestStatus Texture3DLodControlTestInstance::iterate (void)
lodPrec.derivateBits = 10;
lodPrec.lodBits = 8;

for (int gridY = 0; gridY < gridHeight; gridY++)
auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
{
for (int gridX = 0; gridX < gridWidth; gridX++)
{
const int curX = cellWidth*gridX;
const int curY = cellHeight*gridY;
const int curW = gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
const int curH = gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
const int cellNdx = gridY*gridWidth + gridX;

getReferenceParams(refParams, cellNdx);
tcu::Surface referenceFrame (viewportWidth, viewportHeight);
tcu::Surface errorMask (viewportWidth, viewportHeight);
int numFailedPixels = 0;

// Compute texcoord.
if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
getBasicTexCoord3DImageViewMinlodIntTexCoord(texCoord);
else
getBasicTexCoord3D(texCoord, cellNdx);

// Render ideal result
sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
refTexture, &texCoord[0], refParams);

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
for (int gridY = 0; gridY < gridHeight; gridY++)
{
for (int gridX = 0; gridX < gridWidth; gridX++)
{
const int curX = cellWidth*gridX;
const int curY = cellHeight*gridY;
const int curW = gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
const int curH = gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
const int cellNdx = gridY*gridWidth + gridX;

getReferenceParams(refParams, cellNdx);

refParams.imageViewMinLodMode = imageViewLodMode;

// Compute texcoord.
if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
getBasicTexCoord3DImageViewMinlodIntTexCoord(texCoord);
else
getBasicTexCoord3D(texCoord, cellNdx);

// Render ideal result
sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
refTexture, &texCoord[0], refParams);

// Compare this cell
numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
m_texture->getTexture(), &texCoord[0], refParams,
lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
}
}
if (numFailedPixels > 0)
{
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
}
}

if (numFailedPixels > 0)
{
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
}
return numFailedPixels;
};

m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

if (numFailedPixels > 0)
int numFailedPixels = compareAndLogImages();

if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
{
m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
<< TestLog::Image("ErrorMask", "Error mask", errorMask);
numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
}

m_context.getTestContext().getLog() << TestLog::EndImageSet;

if (numFailedPixels > 0)
m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

{
const bool isOk = numFailedPixels == 0;
return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
Expand Down
11 changes: 8 additions & 3 deletions framework/common/tcuTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ bool isColorOrder (TextureFormat::ChannelOrder order)
}
}

float getImageViewMinLod(ImageViewMinLod& l)
{
return (l.mode == IMAGEVIEWMINLODMODE_PREFERRED) ? l.value : deFloatFloor(l.value);
}

} // anonymous

bool isValid (TextureFormat format)
Expand Down Expand Up @@ -2535,7 +2540,7 @@ Vec4 sampleLevelArray2DOffset (const ConstPixelBufferAccess* levels, int numLeve
bool magnified;
// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
const float minLodRelative = (minLodParams != DE_NULL) ? minLodParams->minLod - (float)minLodParams->baseLevel : 0.0f;
const float minLodRelative = (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;

if (es2 && sampler.magFilter == Sampler::LINEAR &&
(sampler.minFilter == Sampler::NEAREST_MIPMAP_NEAREST || sampler.minFilter == Sampler::NEAREST_MIPMAP_LINEAR))
Expand Down Expand Up @@ -2634,7 +2639,7 @@ Vec4 sampleLevelArray3DOffset (const ConstPixelBufferAccess* levels, int numLeve
{
// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
const float minLodRelative = (minLodParams != DE_NULL) ? minLodParams->minLod - (float)minLodParams->baseLevel : 0.0f;
const float minLodRelative = (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;
bool magnified = lod <= sampler.lodThreshold;
Sampler::FilterMode filterMode = magnified ? sampler.magFilter : sampler.minFilter;

Expand Down Expand Up @@ -3078,7 +3083,7 @@ static Vec4 sampleLevelArrayCubeSeamless (const ConstPixelBufferAccess* const (&
{
// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
const float minLodRelative = (minLodParams != DE_NULL) ? minLodParams->minLod - (float)minLodParams->baseLevel : 0.0f;
const float minLodRelative = (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;
bool magnified = lod <= sampler.lodThreshold;
Sampler::FilterMode filterMode = magnified ? sampler.magFilter : sampler.minFilter;

Expand Down
18 changes: 15 additions & 3 deletions framework/common/tcuTexture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,11 +477,23 @@ class TextureLevel
/*--------------------------------------------------------------------*//*!
* \brief VK_EXT_image_view_min_lod
*//*--------------------------------------------------------------------*/
enum ImageViewMinLodMode
{
IMAGEVIEWMINLODMODE_PREFERRED, //!< use image view min lod as-is
IMAGEVIEWMINLODMODE_ALTERNATIVE, //!< use floor of image view min lod, as in 'Image Level(s) Selection' in VK spec (v 1.3.206)
};

struct ImageViewMinLod
{
float value;
ImageViewMinLodMode mode;
};

struct ImageViewMinLodParams
{
int baseLevel;
float minLod;
bool intTexCoord;
int baseLevel;
ImageViewMinLod minLod;
bool intTexCoord;
};

Vec4 sampleLevelArray1D (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, int level, float lod);
Expand Down
Loading

0 comments on commit ea32156

Please sign in to comment.