blob: 1bf1c915beff8c006f5961c4baca62b3f984a813 [file] [log] [blame]
/*==============================================================================
Copyright(c) 2017 Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files(the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and / or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
============================================================================*/
#include "GmmResourceULT.h"
/////////////////////////////////////////////////////////////////////////////////////
/// CTestResource Constructor
/////////////////////////////////////////////////////////////////////////////////////
CTestResource::CTestResource()
{
}
/////////////////////////////////////////////////////////////////////////////////////
/// CTestResource Destructor
///
/////////////////////////////////////////////////////////////////////////////////////
CTestResource::~CTestResource()
{
}
/////////////////////////////////////////////////////////////////////////////////////
/// Sets up common environment for Resource fixture tests. this is called once per
/// test case before executing all tests under resource fixture test case.
/// It also calls SetupTestCase from CommonULT to initialize global context and others.
///
/// @see CTestResource::SetUpTestCase()
///
/////////////////////////////////////////////////////////////////////////////////////
void CTestResource::SetUpTestCase()
{
printf("%s\n", __FUNCTION__);
GfxPlatform.eProductFamily = IGFX_BROADWELL;
GfxPlatform.eRenderCoreFamily = IGFX_GEN8_CORE;
CommonULT::SetUpTestCase();
}
/////////////////////////////////////////////////////////////////////////////////////
/// Cleans up once all the tests finish execution. It also calls TearDownTestCase
/// from CommonULT to destroy global context and others.
///
/// @see CTestResource::TearDownTestCase()
/////////////////////////////////////////////////////////////////////////////////////
void CTestResource::TearDownTestCase()
{
printf("%s\n", __FUNCTION__);
CommonULT::TearDownTestCase();
}
/// @brief ULT for 1D Linear Resource
TEST_F(CTestResource, Test1DLinearResource)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_1D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not valid for 1D
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate more than 1 page
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1001;
gmmParams.BaseHeight = 1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<false>(ResourceInfo, 0);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 1D Linear Resource Arrays
TEST_F(CTestResource, Test1DLinearResourceArrays)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_1D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.ArraySize = 4;
// Allocate 1x1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x100;
gmmParams.BaseHeight = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight * gmmParams.ArraySize, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<true>(ResourceInfo, AlignedHeight);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 1D Mipped Linear Resource
TEST_F(CTestResource, Test1DLinearResourceMips)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_1D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.MaxLod = 5;
// Allocate 256x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x100;
gmmParams.BaseHeight = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
// Height of 1D surface will just be VAlign. So height of the whole block will be
// Height of Mip0 + Mip2 + Mip3 + Mip4 + Mip5...
AlignedHeight = gmmParams.MaxLod * AlignedHeight;
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<false>(ResourceInfo, 0); // N/A for non-arrayed surface
// Mip0 should be at offset 0. X/Y/Z Offset should be 0 for linear.
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after Mip0. X/Y/Z Offset should be 0 for linear.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; //Mip 1
ResourceInfo->GetOffset(OffsetInfo);
uint32_t SizeOfMip0 = PitchInBytes * GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
EXPECT_EQ(SizeOfMip0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should to the right of Mip1. X/Y/Z Offset should be 0 for linear.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; //Mip 2
ResourceInfo->GetOffset(OffsetInfo);
uint32_t StartOfMip = SizeOfMip0 + (GMM_ULT_ALIGN(gmmParams.BaseWidth64 >> 1, HAlign) * GetBppValue(bpp));
EXPECT_EQ(StartOfMip, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Rest of the mips should be below mip2, each with height of HAlign. X/Y/Z Offset should be 0 for linear.
for(int mip = 3; mip <= gmmParams.MaxLod; mip++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = mip;
ResourceInfo->GetOffset(OffsetInfo);
StartOfMip += PitchInBytes * VAlign;
EXPECT_EQ(StartOfMip, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
// ********************************************************************************//
/// @brief ULT for 2D Linear Resource Arrays
TEST_F(CTestResource, Test2DLinearResourceArrays)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.ArraySize = 4;
// Allocate 256x256 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x100;
gmmParams.BaseHeight = 0x100;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight * gmmParams.ArraySize, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<true>(ResourceInfo, AlignedHeight);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 2D Mipped Linear Resource
TEST_F(CTestResource, Test2DLinearResourceMips)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.MaxLod = 8;
// Allocate 256x256 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x100;
gmmParams.BaseHeight = 0x100;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t AlignedHeight;
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
uint32_t HeightOfPrevMip = AlignedHeight = gmmParams.BaseHeight;
// Mip0 should be at offset 0. X/Y/Z Offset should be 0 for linear.
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after Mip0. X/Y/Z Offset should be 0 for linear.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; //Mip 1
ResourceInfo->GetOffset(OffsetInfo);
uint32_t SizeOfMip0 = PitchInBytes * GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
EXPECT_EQ(SizeOfMip0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should to the right of Mip1. X/Y/Z Offset should be 0 for linear.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; //Mip 2
ResourceInfo->GetOffset(OffsetInfo);
uint32_t StartOfMip = SizeOfMip0 + (GMM_ULT_ALIGN(gmmParams.BaseWidth64 >> 1, HAlign) * GetBppValue(bpp));
EXPECT_EQ(StartOfMip, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Rest of the mips should be below mip2, each with height of HAlign. X/Y/Z Offset should be 0 for linear.
for(int mip = 3; mip <= 8; mip++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = mip;
ResourceInfo->GetOffset(OffsetInfo);
HeightOfPrevMip = GMM_ULT_ALIGN((gmmParams.BaseHeight >> (mip - 1)), VAlign);
AlignedHeight += HeightOfPrevMip;
StartOfMip += PitchInBytes * HeightOfPrevMip;
EXPECT_EQ(StartOfMip, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
//Mip8 will go till Mip0Height + Mip1Height + VALIGN
AlignedHeight += VAlign;
uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
VerifyResourceQPitch<false>(ResourceInfo, 0); // N/A for non-arrayed surface
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Arrayed 2D TileX Resource
TEST_F(CTestResource, Test2DTileXResourceArrays)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileWidth = 512;
const uint32_t TileHeight = 8;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.ArraySize = 4;
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = TileHeight + 1; // 1 row larger than 1 tile height
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileWidth);
uint32_t AlignedHeight, BlockHeight;
BlockHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
AlignedHeight = GMM_ULT_ALIGN_NP2(BlockHeight * gmmParams.ArraySize, TileHeight);
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes); // As wide as 2 tile
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileWidth); // 2 tile wide
VerifyResourceSize<true>(ResourceInfo, PitchInBytes * AlignedHeight); // 4 tile big x 4 array size
VerifyResourceQPitch<true>(ResourceInfo, BlockHeight);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Mipped 2D TileX Resource
TEST_F(CTestResource, Test2DTileXResourceMips)
{
const uint32_t TileSize[2] = {512, 8};
enum Coords
{
X = 0,
Y = 1
};
// Test normal mip case
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
const uint32_t ResourceWidth = 0x400;
const uint32_t ResourceHeight = 0x400;
const uint32_t MaxLod = 10;
TEST_BPP bpp = static_cast<TEST_BPP>(i);
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.BaseWidth64 = ResourceWidth;
gmmParams.BaseHeight = ResourceHeight;
gmmParams.MaxLod = MaxLod;
gmmParams.Format = SetResourceFormat(bpp);
// Create resource
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
// Mip0 is the widest mip. So it will dictate the pitch of the whole surface
const uint32_t Pitch = ResourceWidth * GetBppValue(bpp);
uint32_t AllocationHeight = 0;
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after whole Mip0. Should still be tile aligned.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; // Mip 1
ResourceInfo->GetOffset(OffsetInfo);
uint32_t SizeOfMip0 = Pitch * ResourceHeight;
uint32_t HeightOfPrevMip = AllocationHeight = ResourceHeight;
EXPECT_EQ(SizeOfMip0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should be on the right of Mip1. Should still be tile aligned.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; // Mip 2
ResourceInfo->GetOffset(OffsetInfo);
// MipOffset = Mip1Offset + Mip1Width in tiles
uint32_t MipOffset = SizeOfMip0 + ((Pitch >> 1) / TileSize[X]) * PAGE_SIZE;
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mips 3-8 should be on tile boundary
for(int i = 3; i < 9; i++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = i;
ResourceInfo->GetOffset(OffsetInfo);
HeightOfPrevMip = (ResourceHeight >> (i - 1));
AllocationHeight += HeightOfPrevMip;
MipOffset += Pitch * HeightOfPrevMip;
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
// No X/Y/Z offset since mip is at tile boundary
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
// Mips 9 will share 1 tile with Mip 8
AllocationHeight += TileSize[Y];
uint32_t HeightOfPrevMipsInTile = 0;
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 9;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64); // Same as previous tile aligned mip offset
// X is 0, but Y offset will change
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
HeightOfPrevMipsInTile += (ResourceHeight >> (9 - 1));
EXPECT_EQ(HeightOfPrevMipsInTile, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
// Mip 10 is back on tile boundary
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 10; // Mip 10
ResourceInfo->GetOffset(OffsetInfo);
MipOffset += Pitch * TileSize[Y];
AllocationHeight += TileSize[Y];
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Verify ResourceSize and Pitch
VerifyResourceSize<true>(ResourceInfo, AllocationHeight * Pitch);
VerifyResourcePitch<true>(ResourceInfo, Pitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, Pitch / TileSize[X]);
// These are verified elsewhere
VerifyResourceHAlign<false>(ResourceInfo, 0);
VerifyResourceVAlign<false>(ResourceInfo, 0);
VerifyResourceQPitch<false>(ResourceInfo, 0);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Test where Mip1 + Mip2 width > Mip0 width, and where everything fits in 1 tile
for(uint32_t i = 0; i < TEST_BPP_64; i++)
{
const uint32_t ResourceWidth = 0x4;
const uint32_t ResourceHeight = 0x2;
const uint32_t MaxLod = 0x2;
TEST_BPP bpp = static_cast<TEST_BPP>(i);
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.BaseWidth64 = ResourceWidth;
gmmParams.BaseHeight = ResourceHeight;
gmmParams.MaxLod = MaxLod;
gmmParams.Format = SetResourceFormat(bpp);
// Create resource
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
// Get Alignment that GmmLib is using
const uint32_t HAlign = ResourceInfo->GetHAlign();
const uint32_t VAlign = ResourceInfo->GetVAlign();
// Mip1 + Mip2 is the widest width. So it will dictate the pitch of the whole surface
uint32_t Pitch = GetBppValue(bpp) *
(GMM_ULT_ALIGN(ResourceWidth >> 1, HAlign) + GMM_ULT_ALIGN(ResourceWidth >> 2, HAlign));
Pitch = GMM_ULT_ALIGN(Pitch, TileSize[X]);
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after whole Mip0. Not tile aligned
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; // Mip 1
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64); // Same tile as Mip0
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(GMM_ULT_ALIGN(ResourceHeight, VAlign), OffsetInfo.Render.YOffset); // After Mip0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should be on the right of Mip1. Not tile aligned
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; // Mip 2
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64); // Same Tile as Mip0
uint32_t Mip1Width = GMM_ULT_ALIGN(ResourceWidth >> 1, HAlign) * GetBppValue(bpp);
EXPECT_EQ(Mip1Width, OffsetInfo.Render.XOffset); // On right of Mip1
EXPECT_EQ(GMM_ULT_ALIGN(ResourceHeight, VAlign), OffsetInfo.Render.YOffset); // After Mip0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Verify ResourceSize and Pitch
VerifyResourceSize<true>(ResourceInfo, PAGE_SIZE); // everything should fit in 1 tile
VerifyResourcePitch<true>(ResourceInfo, Pitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, Pitch / TileSize[X]);
// These are verified elsewhere
VerifyResourceHAlign<false>(ResourceInfo, 0);
VerifyResourceVAlign<false>(ResourceInfo, 0);
VerifyResourceQPitch<false>(ResourceInfo, 0);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 2D Linear Resource
TEST_F(CTestResource, Test2DLinearResource)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
//Allocate 1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
const uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
const uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 256 x 256
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 256;
gmmParams.BaseHeight = 256;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 64;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
const uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
const uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 2D TileX Resource
TEST_F(CTestResource, Test2DTileXResource)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileWidth = 512;
const uint32_t TileHeight = 8;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.Flags.Gpu.Texture = 1;
//Allocate 1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, TileWidth); // As wide as 1 Tile
VerifyResourcePitchInTiles<true>(ResourceInfo, 1); // 1 Tile wide
VerifyResourceSize<true>(ResourceInfo, GMM_KBYTE(4)); // 1 Tile Big
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not Tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate surface that requires multi tiles in two dimension
// Allocate 2 tiles in X dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, TileWidth * 2); // As wide as 2 tile
VerifyResourcePitchInTiles<true>(ResourceInfo, 2); // 2 tile wide
VerifyResourceSize<true>(ResourceInfo, GMM_KBYTE(4) * 2); // 2 tile big
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = TileHeight + 1; // 1 row larger than 1 tile height
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, TileWidth * 2); // As wide as 2 tile
VerifyResourcePitchInTiles<true>(ResourceInfo, 2); // 2 tile wide
VerifyResourceSize<true>(ResourceInfo, GMM_KBYTE(4) * 4); // 4 tile big
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 2D TileY Resource
TEST_F(CTestResource, Test2DTileYResource)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileWidth = 128;
const uint32_t TileHeight = 32;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.Flags.Gpu.Texture = 1;
//Allocate 1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileWidth);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileWidth);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileWidth * GMM_KBYTE(4));
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not Tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate surface that requires multi tiles in two dimension
// Allocate 2 tiles in X dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileWidth);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileWidth);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileWidth * GMM_KBYTE(4));
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = TileHeight + 1; // 1 row larger than 1 tile height
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileWidth);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileWidth);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileWidth * 2 * GMM_KBYTE(4));
VerifyResourceQPitch<false>(ResourceInfo, 0); // Not tested
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Arrayed 2D TileY Resource
TEST_F(CTestResource, Test2DTileYResourceArrays)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileWidth = 128;
const uint32_t TileHeight = 32;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.ArraySize = 4;
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileWidth / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = TileHeight + 1; // 1 row larger than 1 tile height
uint32_t AlignedHeight, BlockHeight;
BlockHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
AlignedHeight = GMM_ULT_ALIGN_NP2(BlockHeight * gmmParams.ArraySize, TileHeight);
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileWidth);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileWidth);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes * AlignedHeight); // 4 tile big x 4 array size
VerifyResourceQPitch<true>(ResourceInfo, BlockHeight);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Mipped 2D TileY Resource
TEST_F(CTestResource, Test2DTileYResourceMips)
{
const uint32_t TileSize[2] = {128, 32};
enum Coords
{
X = 0,
Y = 1
};
// Test normal mip case
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
const uint32_t ResourceWidth = 0x200;
const uint32_t ResourceHeight = 0x200;
const uint32_t MaxLod = 0x9;
TEST_BPP bpp = static_cast<TEST_BPP>(i);
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.BaseWidth64 = ResourceWidth;
gmmParams.BaseHeight = ResourceHeight;
gmmParams.MaxLod = MaxLod;
gmmParams.Format = SetResourceFormat(bpp);
// Create resource
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
// Mip0 is the widest mip. So it will dictate the pitch of the whole surface
const uint32_t Pitch = ResourceWidth * GetBppValue(bpp);
uint32_t AllocationHeight = 0;
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after whole Mip0. Should still be tile aligned.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; // Mip 1
ResourceInfo->GetOffset(OffsetInfo);
uint32_t SizeOfMip0 = Pitch * ResourceHeight;
uint32_t HeightOfPrevMip = AllocationHeight = ResourceHeight;
EXPECT_EQ(SizeOfMip0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should be on the right of Mip1. Should still be tile aligned.
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; // Mip 2
ResourceInfo->GetOffset(OffsetInfo);
// MipOffset = Mip1Offset + Mip1Width in tiles
uint32_t MipOffset = SizeOfMip0 + ((Pitch >> 1) / TileSize[X]) * PAGE_SIZE;
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mips 3-5 should be on tile boundary
for(int i = 3; i < 6; i++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = i;
ResourceInfo->GetOffset(OffsetInfo);
HeightOfPrevMip = (ResourceHeight >> (i - 1));
AllocationHeight += HeightOfPrevMip;
MipOffset += Pitch * HeightOfPrevMip;
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
// No X/Y/Z offset since mip is at tile boundary
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
// Mips 6-8 will share 1 tile
AllocationHeight += TileSize[Y];
uint32_t HeightOfPrevMipsInTile = 0;
for(int i = 6; i < 9; i++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = i;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64); // Same as previous tile aligned mip offset
// X is 0, but Y offset will change
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
HeightOfPrevMipsInTile += (ResourceHeight >> (i - 1));
EXPECT_EQ(HeightOfPrevMipsInTile, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
// Mip 9 is back on tile boundary
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 9; // Mip 9
ResourceInfo->GetOffset(OffsetInfo);
MipOffset += Pitch * TileSize[Y];
AllocationHeight += TileSize[Y];
EXPECT_EQ(MipOffset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Verify ResourceSize and Pitch
VerifyResourceSize<true>(ResourceInfo, AllocationHeight * Pitch);
VerifyResourcePitch<true>(ResourceInfo, Pitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, Pitch / TileSize[X]);
// These are verified elsewhere
VerifyResourceHAlign<false>(ResourceInfo, 0);
VerifyResourceVAlign<false>(ResourceInfo, 0);
VerifyResourceQPitch<false>(ResourceInfo, 0);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Test where Mip1 + Mip2 width > Mip0 width, and where everything fits in 1 tile
for(uint32_t i = 0; i < TEST_BPP_64; i++)
{
const uint32_t ResourceWidth = 0x4;
const uint32_t ResourceHeight = 0x2;
const uint32_t MaxLod = 0x2;
TEST_BPP bpp = static_cast<TEST_BPP>(i);
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_2D;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.BaseWidth64 = ResourceWidth;
gmmParams.BaseHeight = ResourceHeight;
gmmParams.MaxLod = MaxLod;
gmmParams.Format = SetResourceFormat(bpp);
// Create resource
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
// Get Alignment that GmmLib is using
const uint32_t HAlign = ResourceInfo->GetHAlign();
const uint32_t VAlign = ResourceInfo->GetVAlign();
// Mip1 + Mip2 is the widest width. So it will dictate the pitch of the whole surface
uint32_t Pitch = GetBppValue(bpp) *
(GMM_ULT_ALIGN(ResourceWidth >> 1, HAlign) + GMM_ULT_ALIGN(ResourceWidth >> 2, HAlign));
Pitch = GMM_ULT_ALIGN(Pitch, TileSize[X]);
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1 should be after whole Mip0. Not tile aligned
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; // Mip 1
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64); // Same tile as Mip0
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(GMM_ULT_ALIGN(ResourceHeight, VAlign), OffsetInfo.Render.YOffset); // After Mip0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2 should be on the right of Mip1. Not tile aligned
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2; // Mip 2
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64); // Same Tile as Mip0
uint32_t Mip1Width = GMM_ULT_ALIGN(ResourceWidth >> 1, HAlign) * GetBppValue(bpp);
EXPECT_EQ(Mip1Width, OffsetInfo.Render.XOffset); // On right of Mip1
EXPECT_EQ(GMM_ULT_ALIGN(ResourceHeight, VAlign), OffsetInfo.Render.YOffset); // After Mip0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Verify ResourceSize and Pitch
VerifyResourceSize<true>(ResourceInfo, PAGE_SIZE); // everything should fit in 1 tile
VerifyResourcePitch<true>(ResourceInfo, Pitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, Pitch / TileSize[X]);
// These are verified elsewhere
VerifyResourceHAlign<false>(ResourceInfo, 0);
VerifyResourceVAlign<false>(ResourceInfo, 0);
VerifyResourceQPitch<false>(ResourceInfo, 0);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
// ********************************************************************************//
/// @brief ULT for 3D Linear Resource
TEST_F(CTestResource, Test3DLinearResource)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_3D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
const uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
const uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 256 x 256 x 256
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 256;
gmmParams.BaseHeight = 256;
gmmParams.Depth = 256;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
const uint32_t AlignedHeight = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
const uint32_t AlignedSize = GMM_ULT_ALIGN(PitchInBytes * AlignedHeight * gmmParams.Depth, PAGE_SIZE);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourceSize<true>(ResourceInfo, AlignedSize);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 3D TileX Resource
TEST_F(CTestResource, Test3DTileXResource)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[TEST_BPP_MAX][3] = {{512, 8, 1},
{512, 8, 1},
{512, 8, 1},
{512, 8, 1},
{512, 8, 1}};
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_3D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, TileSize[i][0]);
VerifyResourcePitchInTiles<true>(ResourceInfo, 1);
VerifyResourceSize<true>(ResourceInfo, GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, 2 * TileSize[i][0]);
VerifyResourcePitchInTiles<true>(ResourceInfo, 2);
VerifyResourceSize<true>(ResourceInfo, 2 * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = TileSize[i][1] + 1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, 2 * TileSize[i][0]);
VerifyResourcePitchInTiles<true>(ResourceInfo, 2);
VerifyResourceSize<true>(ResourceInfo, 2 * 2 * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y/Z dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = TileSize[i][1] + 1;
gmmParams.Depth = TileSize[i][2] + 1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileSize[i][0]);
const uint32_t AlignedHeight = 24; // See details in GetTotal3DHeight();
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileSize[i][0]);
VerifyResourceSize<true>(ResourceInfo, AlignedHeight / TileSize[i][1] * PitchInBytes / TileSize[i][0] * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for 3D TileY Resource
TEST_F(CTestResource, Test3DTileYResource)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[TEST_BPP_MAX][3] = {{128, 32, 1},
{128, 32, 1},
{128, 32, 1},
{128, 32, 1},
{128, 32, 1}};
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_3D;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1x1 surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileSize[i][0]);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileSize[i][0]);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileSize[i][0] * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileSize[i][0]);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileSize[i][0]);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileSize[i][0] * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = TileSize[i][1] + 1;
gmmParams.Depth = 0x1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileSize[i][0]);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileSize[i][0]);
VerifyResourceSize<true>(ResourceInfo, PitchInBytes / TileSize[i][0] * 2 * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X/Y/Z dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[i][0] / GetBppValue(bpp)) + 1;
gmmParams.BaseHeight = TileSize[i][1] + 1;
gmmParams.Depth = TileSize[i][2] + 1;
const uint32_t MinPitch = 32;
const uint32_t PitchAlignment = 32;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t AlignedWidth = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign);
uint32_t PitchInBytes = AlignedWidth * GetBppValue(bpp);
PitchInBytes = GFX_MAX(PitchInBytes, MinPitch);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, PitchAlignment);
PitchInBytes = GMM_ULT_ALIGN(PitchInBytes, TileSize[i][0]);
const uint32_t AlignedHeight = 96; // See details in GetTotal3DHeight();
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, PitchInBytes);
VerifyResourcePitchInTiles<true>(ResourceInfo, PitchInBytes / TileSize[i][0]);
VerifyResourceSize<true>(ResourceInfo, AlignedHeight / TileSize[i][1] * PitchInBytes / TileSize[i][0] * GMM_KBYTE(4));
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Cube Linear Resource
TEST_F(CTestResource, Test3DTileYMippedResource)
{
// Horizontal/Vertical pixel alignment
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[TEST_BPP_MAX][3] = {{128, 32, 1},
{128, 32, 1},
{128, 32, 1},
{128, 32, 1},
{128, 32, 1}};
const uint32_t ResourceWidth = 0x100;
const uint32_t ResourceHeight = 0x100;
const uint32_t ResourceDepth = 0x100;
const uint32_t MaxLod = 0x9;
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_3D;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.BaseWidth64 = ResourceWidth;
gmmParams.BaseHeight = ResourceHeight;
gmmParams.Depth = ResourceDepth;
gmmParams.MaxLod = MaxLod;
gmmParams.Format = SetResourceFormat(bpp);
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
const uint32_t Pitch = ResourceWidth * GetBppValue(bpp);
const uint32_t Mip0Height = ResourceHeight;
const uint32_t Mip0Depth = ResourceDepth;
// Mip0
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip1
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1;
ResourceInfo->GetOffset(OffsetInfo);
const uint32_t SizeOfMip0 = Pitch * Mip0Height * Mip0Depth;
const uint32_t Mip1Offset = SizeOfMip0;
const uint32_t Mip1Height = Mip0Height >> 1;
const uint32_t Mip1Depth = Mip0Depth >> 1;
EXPECT_EQ(Mip1Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip2
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 2;
ResourceInfo->GetOffset(OffsetInfo);
const uint32_t SizeOfMip1 = (Pitch >> 1) * Mip1Height * Mip1Depth;
const uint32_t Mip2Offset = Mip1Offset + SizeOfMip1;
const uint32_t Mip2Height = Mip1Height >> 1;
const uint32_t Mip2Depth = Mip1Depth >> 1;
EXPECT_EQ(Mip2Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip3
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 3;
ResourceInfo->GetOffset(OffsetInfo);
const uint32_t SizeOfMip2 = (Pitch >> 2) * Mip2Height * Mip2Depth;
const uint32_t Mip3Offset = Mip2Offset + SizeOfMip2;
const uint32_t Mip3Height = Mip2Height >> 1;
const uint32_t Mip3Depth = Mip2Depth >> 1;
EXPECT_EQ(Mip3Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip4 (Packed Mip)
// For those mip width/height smaller than H/VAlign, they are upscaled to align with H/VAlign
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 4;
ResourceInfo->GetOffset(OffsetInfo);
const uint32_t SizeOfMip3 = (Pitch >> 3) * Mip3Height * Mip3Depth;
const uint32_t Mip4Offset = Mip3Offset + SizeOfMip3;
EXPECT_EQ(Mip4Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip 5
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 5;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(Mip4Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(16, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip 6
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 6;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(Mip4Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(24, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip 7
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 7;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(Mip4Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(28, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip8 (Start of another packed Mip)
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 8;
ResourceInfo->GetOffset(OffsetInfo);
const uint32_t Mip8Offset = Mip4Offset + Pitch * TileSize[i][1];
EXPECT_EQ(Mip8Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
// Mip9
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 9;
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(Mip8Offset, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(4, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
// ********************************************************************************//
/// @brief ULT for Cube Linear Resource
TEST_F(CTestResource, TestCubeLinearResource)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_CUBE;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
uint32_t ExpectedPitch = GMM_ULT_MAX(GMM_BYTES(32), HAlign * GetBppValue(bpp)); // Min Pitch = 32 bytes
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch); // As wide as 1 tile
VerifyResourcePitchInTiles<false>(ResourceInfo, 1); // not applicable
uint32_t ExpectedQPitch = VAlign;
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be VAlign rows apart within a tile
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned PAGE_SIZE
GMM_ULT_ALIGN(ExpectedPitch *
__GMM_MAX_CUBE_FACE * ExpectedQPitch,
PAGE_SIZE));
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(CubeFaceIndex * ExpectedQPitch * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Y Offset should be 0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate arbitrary size (X/Y dimension not applicable as linear surface)
// Width and Height must be equal
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x201; // 512 + 1, help ult HAlign/VAlign/Pitch alignment logic as well.
gmmParams.BaseHeight = gmmParams.BaseWidth64; // Heigth must be equal to width.
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
uint32_t ExpectedPitch = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign) * GetBppValue(bpp); // HAligned-width in bytes.
ExpectedPitch = GMM_ULT_ALIGN(ExpectedPitch, GMM_BYTES(32));
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch);
VerifyResourcePitchInTiles<false>(ResourceInfo, 2); // not applicable
uint32_t ExpectedQPitch = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be Valigned-BaseHeight rows apart
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned PAGE_SIZE
GMM_ULT_ALIGN(ExpectedPitch *
__GMM_MAX_CUBE_FACE * ExpectedQPitch,
PAGE_SIZE));
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(CubeFaceIndex * ExpectedQPitch * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Y Offset should be 0
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Cube Linear Mipped Resource
TEST_F(CTestResource, TestCubeLinearMippedResourceArray)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t MaxLod = 9;
const uint32_t ResWidth = 0x201;
const uint32_t MaxArraySize = 0x10;
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_CUBE;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.Linear = 1;
gmmParams.Flags.Gpu.Texture = 1;
gmmParams.MaxLod = MaxLod;
gmmParams.ArraySize = MaxArraySize;
// Allocate arbitrary size (X/Y dimension not applicable as linear surface)
// Width and Height must be equal
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
struct //Cache the value for verifying array elements/Cube face offset/Mip Offset
{
uint64_t Offset; // Note : absolute mip offset
} RenderOffset[GMM_ULT_MAX_MIPMAP] = {};
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = ResWidth; // 1024 + 1, help ult HAlign/VAlign/Pitch alignment logic as well.
gmmParams.BaseHeight = gmmParams.BaseWidth64; // Heigth must be equal to width.
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
//------------------------------|
// |
// LOD0 |
// |
// |
//------------------------------|
// LOD1 | LOD2 |
// |----------|
// | LOD3 |
//-------------| LOD4 .. so on
// Mip 0
// Mip 0 decides the pitch of the entire surface
const uint32_t AlignedWidthMip0 = GMM_ULT_ALIGN(ResWidth, HAlign); // HAlign width in pixel
const uint32_t AlignedHeightMip0 = GMM_ULT_ALIGN(ResWidth, VAlign);
uint32_t ExpectedPitch = GMM_ULT_ALIGN(gmmParams.BaseWidth64, HAlign) * GetBppValue(bpp); // HAligned-width in bytes.
ExpectedPitch = GMM_ULT_ALIGN(ExpectedPitch, GMM_BYTES(32));
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch);
VerifyResourcePitchInTiles<false>(ResourceInfo, 2); // Not applicable
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
//cache Mip 0 offset
RenderOffset[0].Offset = 0;
// Mip 1 should be under mip 0
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; //Mip 1
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(AlignedHeightMip0 * ExpectedPitch, // Render offset is the absolute address at which the mip begins
OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // Not applicable for linear surface
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Not applicable for linear surface
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // n/a
//cache Mip 1 offset
RenderOffset[1].Offset = AlignedHeightMip0 * ExpectedPitch; //Absolute base
const uint32_t AlignedWidthMip1 = GMM_ULT_ALIGN(ResWidth >> 1, HAlign); // Align width in pixel to HAlign
const uint32_t AlignedHeightMip1 = GMM_ULT_ALIGN(ResWidth >> 1, VAlign);
uint32_t HeightOfMip;
uint32_t HeightLinesLevel2 = 0;
// Mips 2-9 should be stacked on the right of Mip1 as shown in figure above.
for(int i = 2; i <= MaxLod; i++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = i;
ResourceInfo->GetOffset(OffsetInfo);
HeightOfMip = GMM_ULT_ALIGN(ResWidth >> i, VAlign);
EXPECT_EQ((AlignedHeightMip0 + HeightLinesLevel2) * ExpectedPitch + // Render offset is tile's base address on which mip begins
(AlignedWidthMip1 * GetBppValue(bpp)),
OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // Not applicable for linear surface
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Not applicable for linear surface
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
//cache Mip i'th offset
RenderOffset[i].Offset = (AlignedHeightMip0 + HeightLinesLevel2) * ExpectedPitch +
(AlignedWidthMip1 * GetBppValue(bpp));
HeightLinesLevel2 += HeightOfMip;
}
uint32_t ExpectedQPitch = AlignedHeightMip0 + AlignedHeightMip1 + 12 * VAlign;
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be Valigned-BaseHeight rows apart
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned to tile boundary
GMM_ULT_ALIGN(ExpectedPitch *
MaxArraySize * __GMM_MAX_CUBE_FACE * ExpectedQPitch,
PAGE_SIZE));
// Verify each array element's Mip offset, Cube face offset etc.
for(uint32_t ArrayIndex = 0; ArrayIndex < __GMM_MAX_CUBE_FACE; ArrayIndex++)
{
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.ArrayIndex = ArrayIndex;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
//Verify cube face offsets
EXPECT_EQ(((6 * ArrayIndex) + CubeFaceIndex) * ExpectedQPitch * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0 as linear surf
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Y Offset should be 0 as linear surf
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
uint32_t CubeFaceBaseOffset = ((6 * ArrayIndex) + CubeFaceIndex) * (ExpectedQPitch * ExpectedPitch);
//Verify mip offsets in each cube face
for(uint32_t Lod = 0; Lod <= MaxLod; Lod++)
{
OffsetInfo.MipLevel = Lod;
ResourceInfo->GetOffset(OffsetInfo);
uint32_t MipOffset = CubeFaceBaseOffset + RenderOffset[Lod].Offset;
uint32_t OffsetX = MipOffset % ExpectedPitch;
uint32_t OffsetY = MipOffset / ExpectedPitch;
uint32_t RenderAlignOffset = OffsetY * ExpectedPitch + OffsetX;
EXPECT_EQ(RenderAlignOffset, OffsetInfo.Render.Offset64); // Render offset absolute address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0 as linear surf
EXPECT_EQ(0, OffsetInfo.Render.YOffset); // Y Offset should be 0 as linear surf
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
}
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Cube TileX Resource
TEST_F(CTestResource, TestCubeTileXResource)
{
// Cube is allocated as an array of 6 2D surface representing each cube face below
//===============================
// q coordinate | face |
// 0 | + x |
// 1 | - x |
// 2 | + y |
// 3 | - y |
// 4 | + z |
// 5 | - z |
//===============================
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[1][2] = {512, 8};
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_CUBE;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledX = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1 surface so that it occupies 1 Tile in X dimension
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
uint32_t ExpectedPitch = TileSize[0][0];
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch); // As wide as 1 tile
VerifyResourcePitchInTiles<true>(ResourceInfo, 1); // 1 tile wide
uint32_t ExpectedQPitch = VAlign;
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be VAlign rows apart within a tile
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned to tile boundary
ExpectedPitch *
GMM_ULT_ALIGN(__GMM_MAX_CUBE_FACE * ExpectedQPitch,
TileSize[0][1]));
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(GMM_ULT_ALIGN_FLOOR(CubeFaceIndex * ExpectedQPitch, TileSize[0][1]) * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ((CubeFaceIndex * ExpectedQPitch) % TileSize[0][1],
OffsetInfo.Render.YOffset); // Y Offset should be (CubeFaceIndex * QPitch) % TileHeight
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X dimension.
// Width and Height must be equal
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[0][0] / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = gmmParams.BaseWidth64; // Heigth must be equal to width.
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
uint32_t ExpectedPitch = TileSize[0][0] * 2; // As wide as 2 tile
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, 2); // 2 tile wide
uint32_t ExpectedQPitch = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be Valigned-BaseHeight rows apart
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned to tile boundary
ExpectedPitch *
GMM_ULT_ALIGN(__GMM_MAX_CUBE_FACE * ExpectedQPitch,
TileSize[0][1]));
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(GMM_ULT_ALIGN_FLOOR(CubeFaceIndex * ExpectedQPitch, TileSize[0][1]) * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ((CubeFaceIndex * ExpectedQPitch) % TileSize[0][1],
OffsetInfo.Render.YOffset); // Y Offset should be (CubeFaceIndex * QPitch) % TileHeight
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Cube TileY Resource
TEST_F(CTestResource, TestCubeTileYResource)
{
// Cube is allocated as an array of 6 2D surface representing each cube face below
//===============================
// q coordinate | face |
// 0 | + x |
// 1 | - x |
// 2 | + y |
// 3 | - y |
// 4 | + z |
// 5 | - z |
//===============================
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[1][2] = {128, 32};
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_CUBE;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate 1x1 surface within a tile.
for(uint32_t i = 0; i < TEST_BPP_128; i++) //TEST_BPP_128 cannot fit in a tile as HAlign = 16
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = 0x1;
gmmParams.BaseHeight = 0x1;
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
VerifyResourcePitch<true>(ResourceInfo, TileSize[0][0]); // As wide as 1 tile
VerifyResourcePitchInTiles<true>(ResourceInfo, 1); // 1 tile wide
VerifyResourceSize<true>(ResourceInfo, GMM_KBYTE(4)); // All 6 faces should be accomated in a tile.
VerifyResourceQPitch<true>(ResourceInfo, VAlign); // Each face should be VAlign rows apart within a tile
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64); // Render offset should be 0 as its on single tile.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ(CubeFaceIndex * VAlign, OffsetInfo.Render.YOffset); // Y Offset should be VALIGN * CubeFace Index
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
// Allocate 2 tiles in X dimension.
// Width and Height of Cube must be equal
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = (TileSize[0][0] / GetBppValue(bpp)) + 1; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = gmmParams.BaseWidth64; // Heigth must be equal to width.
gmmParams.Depth = 0x1;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
uint32_t ExpectedPitch = TileSize[0][0] * 2; // As wide as 2 tile
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, 2); // 2 tile wide
uint32_t ExpectedQPitch = GMM_ULT_ALIGN(gmmParams.BaseHeight, VAlign);
VerifyResourceQPitch<true>(ResourceInfo, ExpectedQPitch); // Each face should be Valigned-BaseHeight rows apart
VerifyResourceSize<true>(ResourceInfo, // PitchInBytes * Rows where Rows = __GMM_MAX_CUBE_FACE x QPitch, then aligned to tile boundary
ExpectedPitch *
GMM_ULT_ALIGN(__GMM_MAX_CUBE_FACE * ExpectedQPitch,
TileSize[0][1]));
for(uint32_t CubeFaceIndex = 0; CubeFaceIndex < __GMM_MAX_CUBE_FACE; CubeFaceIndex++)
{
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.CubeFace = static_cast<GMM_CUBE_FACE_ENUM>(CubeFaceIndex);
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(GMM_ULT_ALIGN_FLOOR(CubeFaceIndex * ExpectedQPitch, TileSize[0][1]) * ExpectedPitch,
OffsetInfo.Render.Offset64); // Render offset is tile's base address on which cube face begins.
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // X Offset should be 0
EXPECT_EQ((CubeFaceIndex * ExpectedQPitch) % TileSize[0][1],
OffsetInfo.Render.YOffset); // Y Offset should be (CubeFaceIndex * QPitch) % TileHeight
EXPECT_EQ(0, OffsetInfo.Render.ZOffset); // Z offset N/A should be 0
}
pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
}
}
/// @brief ULT for Cube TileY Mipped Resource Array
TEST_F(CTestResource, TestCubeTileYMippedResourceArray)
{
const uint32_t HAlign = 16;
const uint32_t VAlign = 4;
const uint32_t TileSize[2] = {128, 32};
enum Coords
{
X = 0,
Y = 1
};
GMM_RESCREATE_PARAMS gmmParams = {};
gmmParams.Type = RESOURCE_CUBE;
gmmParams.NoGfxMemory = 1;
gmmParams.Flags.Info.TiledY = 1;
gmmParams.Flags.Gpu.Texture = 1;
// Allocate CUBE surface
for(uint32_t i = 0; i < TEST_BPP_MAX; i++)
{
const uint32_t ResWidth = 0x201;
const uint32_t MaxLod = 0x9;
const uint32_t MaxArraySize = 0x10;
struct //Cache the value for verifying array elements/Cube face offset/Mip Offset
{
uint64_t Offset; // Note : absolute mip offset
} RenderOffset[GMM_ULT_MAX_MIPMAP];
TEST_BPP bpp = static_cast<TEST_BPP>(i);
gmmParams.Format = SetResourceFormat(bpp);
gmmParams.BaseWidth64 = ResWidth; // 1 pixel larger than 1 tile width
gmmParams.BaseHeight = gmmParams.BaseWidth64; // Heigth must be equal to width.
gmmParams.Depth = 0x1;
gmmParams.MaxLod = MaxLod;
gmmParams.ArraySize = MaxArraySize;
GMM_RESOURCE_INFO *ResourceInfo;
ResourceInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
VerifyResourceHAlign<true>(ResourceInfo, HAlign);
VerifyResourceVAlign<true>(ResourceInfo, VAlign);
//------------------------------|
// |
// LOD0 |
// |
// |
//------------------------------|
// LOD1 | LOD2 |
// |----------|
// | LOD3 |
//-------------| LOD4 .. so on
//Mip 0
//Mip 0 decides the pitch of the entire resource.
const uint32_t AlignedWidthMip0 = GMM_ULT_ALIGN(ResWidth, HAlign); // HAlign width in pixel
const uint32_t AlignedHeightMip0 = GMM_ULT_ALIGN(ResWidth, VAlign);
uint32_t ExpectedPitch = GMM_ULT_ALIGN(AlignedWidthMip0 * GetBppValue(bpp), TileSize[X]); // Align AlignedWidthMip0 to 128 bytes
VerifyResourcePitch<true>(ResourceInfo, ExpectedPitch);
VerifyResourcePitchInTiles<true>(ResourceInfo, ExpectedPitch / TileSize[X]); // Pitch/TileY-Width
// Mip0 should be at offset 0 and tile aligned
GMM_REQ_OFFSET_INFO OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 0; //Mip 0
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(0, OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset);
EXPECT_EQ(0, OffsetInfo.Render.YOffset);
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
//cache Mip 0 offset
RenderOffset[0].Offset = 0;
// Mip 1 should be under mip 0
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = 1; //Mip 1
ResourceInfo->GetOffset(OffsetInfo);
EXPECT_EQ(GMM_ULT_ALIGN_FLOOR(AlignedHeightMip0, TileSize[Y]) * ExpectedPitch, // Render offset is tile's base address on which mip begins
OffsetInfo.Render.Offset64);
EXPECT_EQ(0, OffsetInfo.Render.XOffset); // Aligns with Mip0 at X = 0
EXPECT_EQ((AlignedHeightMip0) % TileSize[Y], OffsetInfo.Render.YOffset); // AlignedHeightMip0 % TileY-Height
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
//cache Mip 1 offset
RenderOffset[1].Offset = AlignedHeightMip0 * ExpectedPitch; //Absolute base
const uint32_t AlignedWidthMip1 = GMM_ULT_ALIGN(ResWidth >> 1, HAlign); // Align width in pixel to HAlign
const uint32_t AlignedHeightMip1 = GMM_ULT_ALIGN(ResWidth >> 1, VAlign);
uint32_t HeightOfMip;
uint32_t HeightLinesLevel2 = 0;
// Mips 2-9 should be stacked on the right of Mip1 as shown in figure above.
for(int i = 2; i <= MaxLod; i++)
{
OffsetInfo = {};
OffsetInfo.ReqRender = 1;
OffsetInfo.MipLevel = i;
ResourceInfo->GetOffset(OffsetInfo);
HeightOfMip = GMM_ULT_ALIGN(ResWidth >> i, VAlign);
EXPECT_EQ(GMM_ULT_ALIGN_FLOOR(AlignedHeightMip0 + HeightLinesLevel2, TileSize[Y]) * ExpectedPitch + // Render offset is tile's base address on which mip begins
(AlignedWidthMip1 * GetBppValue(bpp) / TileSize[X]) * PAGE_SIZE,
OffsetInfo.Render.Offset64);
EXPECT_EQ((AlignedWidthMip1 * GetBppValue(bpp)) % TileSize[X], OffsetInfo.Render.XOffset); // Aligns with Mip0 at X = 0
EXPECT_EQ((AlignedHeightMip0 + HeightLinesLevel2) % TileSize[Y], OffsetInfo.Render.YOffset); // AlignedHeightMip0 % TileY-Height
EXPECT_EQ(0, OffsetInfo.Render.ZOffset);
//cache Mip i'th offset
RenderOffset[i].Offset = (AlignedHeightMip0 + HeightLinesLevel2) * ExpectedPitch +
(AlignedWidthMip1 * GetBppValue(bpp));
HeightLinesLevel2 += HeightOfMip;