📄 driververif.cpp
字号:
//
// Some of the rotation specs (e.g., XY) do not involve a rotation about
// the Z axis; thus, only one iteration of the Z-Axis loop is needed for
// these cases.
//
if (UsesZRot((D3DQA_ROTTYPE)RotType))
{
uiRotZFirst = 0;
uiRotZLast = D3DQA_NUM_SAMPLE_ROT_ANGLES-1; // Adjust for zero-based indexing
}
else
{
uiRotZFirst = uiRotZLast = 0;
}
for(uiRotIndexZ = uiRotZFirst; uiRotIndexZ <= uiRotZLast; uiRotIndexZ++)
{
uiIteration++; // This is used only for logging purposes; and for ease of debugging.
//
// Retrieve the amount (angle) of Z-axis rotation for this iteration
//
float fRotZ = ROTANGLES[uiRotIndexZ];
//
// Determine the rotation matrix that satisfies the specifications for this
// iteration of the nested loop.
//
// The inverse matrix isn't actually used here; but it is generated in case
// it is useful in debugging.
//
if (!(GetRotationInverses((D3DQA_ROTTYPE)RotType, // D3DQA_ROTTYPE rType,
fRotX, // const float fXRot,
fRotY, // const float fYRot,
fRotZ, // const float fZRot,
&TexTransMatrix, // D3DMATRIX* const RotMatrix,
&TexTransMatrixInverse))) // D3DMATRIX* const RotMatrixInverse)
{
DebugOut(_T("GetRotationInverses failed.\n"));
Result = TPR_FAIL;
goto cleanup;
}
//
// For ease of computation, the "expected" texture coordinates will be
// derived by storing the initial coordinates in a vector and then
// transforming it by the same rotation matrix that has been indicated
// to Direct3D.
//
ResultTexCoordsExpected.x = _M(InputVertex.tu);
ResultTexCoordsExpected.y = _M(InputVertex.tv);
ResultTexCoordsExpected.z = _M(InputVertex.tr);
ResultTexCoordsExpected = TransformVector(&ResultTexCoordsExpected, &TexTransMatrix);
//
// Set-up the texture coordinate transform matrix for the desired transformation.
//
if (FAILED(m_pd3dDevice->SetTransform( D3DMTS_TEXTURE0, &TexTransMatrix, D3DMFMT_D3DMVALUE_FLOAT )))
{
DebugOut(_T("IDirect3DMobileDevice::SetTransform failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Process a single vertex from the vertex buffer.
//
if (FAILED(m_pd3dDevice->ProcessVertices(0, // UINT SrcStartIndex: Index of first vertex to be loaded.
0, // UINT DestIndex: Index of first vertex in the destination vertex buffer
1, // UINT VertexCount: Number of vertices to process.
pVBOut, // IDirect3DMobileVertexBuffer* pDestBuffer: Pointer to an IDirect3DMobileVertexBuffer interface, the destination vertex buffer representing the stream of interleaved vertex data
0))) // DWORD Flags: Processing options. Set this parameter to 0 for default processing.
{
DebugOut(_T("IDirect3DMobileDevice::ProcessVertices failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Verify output vertices (lock, examine data, unlock)
//
//
// Lock output vertex buffer; so that resulting coordinate data can be examined
//
if( FAILED( pVBOut->Lock( 0, sizeof(D3DQA_TTRTEST_OUT), (VOID**)&pOutputVert, 0 ) ) )
{
DebugOut(_T("IDirect3DMobileVertexBuffer::Lock failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Test for differences that exceed the tolerance
//
if ((fabs(*(float*)&ResultTexCoordsExpected.x - *(float*)&pOutputVert->tu) > m_fTestTolerance) ||
(fabs(*(float*)&ResultTexCoordsExpected.y - *(float*)&pOutputVert->tv) > m_fTestTolerance) ||
(fabs(*(float*)&ResultTexCoordsExpected.z - *(float*)&pOutputVert->tr) > m_fTestTolerance))
{
//
// Log the current rotation specs. Note that the order of the X, Y, Z angle information will
// not be output in "rotation order". For example, a rotation of XYZ will have the same debug
// output order as a rotation of XZY.
//
DebugOut(_T("Iteration #%u... Rotation Type: %s; X Rot Angle: %f; Y Rot Angle: %f; Z Rot Angle: %f"),
uiIteration, D3DQA_ROTTYPE_NAMES[RotType], fRotX, fRotY, fRotZ);
//
// The comparison demonstrated a difference that exceeded the tolerance
//
DebugOut(_T("Texture coordinate comparison failure. Expected coordinates: (%f,%f,%f); Actual coordinates (%f,%f,%f); Difference (%f,%f,%f); Tolerance (%f)"),
*(float*)&ResultTexCoordsExpected.x, *(float*)&ResultTexCoordsExpected.y, *(float*)&ResultTexCoordsExpected.z,
*(float*)&pOutputVert->tu, *(float*)&pOutputVert->tv, *(float*)&pOutputVert->tr,
fabs(*(float*)&ResultTexCoordsExpected.x - *(float*)&pOutputVert->tu),
fabs(*(float*)&ResultTexCoordsExpected.y - *(float*)&pOutputVert->tv),
fabs(*(float*)&ResultTexCoordsExpected.z - *(float*)&pOutputVert->tr),
m_fTestTolerance);
Result = TPR_FAIL;
uiNumFailures++;
if (uiNumFailures >= uiFailureThreshhold)
{
DebugOut(_T("Failure threshhold exceeded.\n"));
Result = TPR_FAIL; // Should have been set to this previously anyway
goto cleanup;
}
}
//
// Unlock output vertex buffer; analysis of coordinate data therein is complete
//
if( FAILED( pVBOut->Unlock() ) )
{
DebugOut(_T("IDirect3DMobileVertexBuffer::Unlock failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
}
}
}
}
cleanup:
//
// Unlock if not already unlocked (no op if it is already unlocked)
//
if (pVBIn)
pVBIn->Unlock();
if (pVBOut)
pVBOut->Unlock();
//
// Release vertex buffers
//
if (pVBIn)
pVBIn->Release();
if (pVBOut)
pVBOut->Release();
//
// Clear active vertex buffer ref-count
//
if (m_pd3dDevice)
m_pd3dDevice->SetStreamSource( 0, // UINT StreamNumber
NULL, // IDirect3DMobileVertexBuffer* pStreamData
0); // UINT Stride
//
// Return tux test case result
//
return Result;
}
//
// ExecuteMultTest
//
// This test verifies ProcessVertices transformation of vertex positions via the world and view matrices.
// The technique used by this test is to confirm that multiplications between specific matrix components
// is occuring as expected.
//
// This test expects the viewport and projection to be set up to "cancel" each other out (the result of the
// projection matrix mult with the viewport matrix should be the identity matrix).
//
// For simplicity, it is expected that clipping is off.
//
// Arguments:
//
// None
//
// Return Value:
//
// TPR_PASS, TPR_FAIL, or TPR_SKIP, depending on test result
//
INT DriverVerifTest::ExecuteMultTest()
{
DebugOut(_T("Beginning ExecuteMultTest.\n"));
//
// This test iterates over a variety of multiplicands, each
// generated by 2^exp, where exp is:
//
int iExponentOne, iExponentTwo;
//
// Input and output Vertex buffers for ProcessVertices
//
IDirect3DMobileVertexBuffer *pInVB = NULL;
IDirect3DMobileVertexBuffer *pOutVB = NULL;
//
// Positions for multiplicands in world, view matrix data
//
UINT uiWorldRow, uiWorldCol, uiViewRow, uiViewCol;
//
// World and view transformation matrices for D3DM TnL
//
D3DMMATRIX WorldMatrix, ViewMatrix;
//
// FVF sizes for this test
//
CONST UINT uiInVertSize = sizeof(float)*3; // X,Y,Z
CONST UINT uiOutVertSize = sizeof(float)*4; // X,Y,Z,RHW
//
// Difference between expected value and actual value
//
double dDelta;
double dLargestDelta = 0.0f;
//
// The test will return TPR_FAIL if even one result exceeds the tolerance, but to aid in
// debugging the test will continue to execute until reaching the number of failures below.
//
CONST UINT uiFailureThreshhold = 25;
UINT uiNumFailures = 0;
//
// Used for VB locks, to access floating point positional data (X,Y,Z,RHW)
//
float *pFloats = NULL;
//
// Tux Test Case Result; all non-pass blocks set this to another value
//
INT Result = TPR_PASS;
if (!IsReady())
{
DebugOut(_T("Due to failed initialization, the test must be aborted.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Disable clipping
//
if( FAILED( m_pd3dDevice->SetRenderState(D3DMRS_CLIPPING, FALSE)))
{
DebugOut(_T("IDirect3DMobileDevice::SetRenderState failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Disable lighting
//
if( FAILED( m_pd3dDevice->SetRenderState(D3DMRS_LIGHTING, FALSE)))
{
DebugOut(_T("IDirect3DMobileDevice::SetRenderState failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Cause viewport and projection to cancel each other out, for isolated world/view testing
//
if (FAILED(SetDegenerateViewAndProj()))
{
DebugOut(_T("SetDegenerateViewAndProj failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Creates a Vertex Buffer; sets stream source and vertex shader type (FVF)
//
pOutVB = CreateActiveBuffer(m_pd3dDevice, 1, D3DMFVF_XYZRHW_FLOAT, uiOutVertSize, D3DMUSAGE_DONOTCLIP);
if (NULL == pOutVB)
{
DebugOut(_T("CreateActiveBuffer failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Creates a Vertex Buffer; sets stream source and vertex shader type (FVF)
//
pInVB = CreateActiveBuffer(m_pd3dDevice, 1, D3DMFVF_XYZ_FLOAT, uiInVertSize, 0);
if (NULL == pInVB)
{
DebugOut(_T("CreateActiveBuffer failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Iterate over a variety of multiplicands
//
for(iExponentOne = D3DQA_PV_MINEXP; iExponentOne <= 0; iExponentOne++)
{
for(iExponentTwo = 0; iExponentTwo >= (D3DQA_PV_MINEXP-iExponentOne); iExponentTwo--)
{
UINT uiMultOpNum = 1;
float fValOne = (float)pow( 2, iExponentOne );
float fValTwo = (float)pow( 2, iExponentTwo );
int iExpectedResultExp = iExponentOne+iExponentTwo;
float fExpectedResult = fValOne * fValTwo; // Equivalent to: (float)pow( 2, iExpectedResultExp );
for (uiViewCol = 0; uiViewCol < 3; uiViewCol++)
{
for (uiWorldRow = 0; uiWorldRow < 3; uiWorldRow++)
{
for (uiWorldCol = 0; uiWorldCol < 3; uiWorldCol++)
{
uiViewRow = uiWorldCol;
float fResult;
//
// Lock the input vertex buffer
//
if( FAILED( pInVB->Lock(0, // UINT OffsetToLock,
uiInVertSize, // UINT SizeToLock,
(VOID**)(&pFloats), // VOID** ppbData,
0))) // DWORD Flags
{
DebugOut(_T("IDirect3DMobileVertexBuffer::Lock failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Fill the input vertex buffer
//
pFloats[0] = 0.0f;
pFloats[1] = 0.0f;
pFloats[2] = 0.0f;
pFloats[uiWorldRow] = 1.0f;
//
// Unlock the input vertex buffer
//
pInVB->Unlock();
//
// Prepare the view and world matrices
//
ZeroMemory(&WorldMatrix,sizeof(D3DMMATRIX));
ZeroMemory(&ViewMatrix,sizeof(D3DMMATRIX));
//
// Set the view matrix, initially, to identity
//
ViewMatrix.m[0][0] = ViewMatrix.m[1][1] = ViewMatrix.m[2][2] = ViewMatrix.m[3][3] = _M(1.0f);
WorldMatrix.m[3][3] = _M(1.0f);
//
// Set multiplicands
//
WorldMatrix.m[uiWorldRow][uiWorldCol] = _M(fValOne);
ViewMatrix.m[uiViewRow][uiViewCol] = _M(fValTwo);
//
// Indicate world matrix to D3DM
//
if( FAILED( m_pd3dDevice->SetTransform(D3DMTS_WORLD, // D3DTRANSFORMSTATETYPE State,
&WorldMatrix, // CONST D3DMMATRIX* pMatrix
D3DMFMT_D3DMVALUE_FLOAT))) // D3DMFORMAT Format
{
DebugOut(_T("IDirect3DMobileDevice::SetTransform failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Indicate view matrix to D3DM
//
if( FAILED( m_pd3dDevice->SetTransform(D3DMTS_VIEW, // D3DTRANSFORMSTATETYPE State,
&ViewMatrix, // CONST D3DMMATRIX* pMatrix
D3DMFMT_D3DMVALUE_FLOAT))) // D3DMFORMAT Format
{
DebugOut(_T("IDirect3DMobileDevice::SetTransform failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Perform TnL on input VB, store in output VB
//
if( FAILED( m_pd3dDevice->ProcessVertices(0, // UINT SrcStartIndex,
0, // UINT DestIndex,
1, // UINT VertexCount,
pOutVB, // IDirect3DMobileVertexBuffer* pDestBuffer,
0))) // DWORD Flags
{
DebugOut(_T("IDirect3DMobileDevice::ProcessVertices failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// Lock results of ProcessVertices
//
if( FAILED( pOutVB->Lock(0, // UINT OffsetToLock,
uiOutVertSize, // UINT SizeToLock,
(VOID**)(&pFloats), // VOID** ppbData,
0))) // DWORD Flags
{
DebugOut(_T("IDirect3DMobileVertexBuffer::Lock failed.\n"));
Result = TPR_ABORT;
goto cleanup;
}
//
// fResult should be the product of the multiplicands
//
fResult = pFloats[uiViewCol];
//
// Release the lock (the target value has been stored elsewhere)
//
pOutVB->Unlock();
//
// What is the difference between the expected result and the actual result, if
// any?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -