0
\$\begingroup\$

I'm following this tutorial, where they show how to setup a simple dx11 demo with a green triangle in the middle. I'd like to be able to modify it so that it shows 2 triangles instead, i modified the code of the Graphicsclass.cpp in the tutorial by adding some lines to the Render() function, just after the first triangle is drawn, it's the //ADDITIONAL CODE section:

[...]
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(m_Direct3D->GetDeviceContext());

// Render the model using the color shader.
result = m_ColorShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);
if (!result)
{
    return false;
}

//ADDITIONAL CODE
// Reset the world matrix.
worldMatrix = XMMatrixIdentity();

// Translate to the location of the second triangle.
translateMatrix = XMMatrixTranslation(1.0f, 1.0f, 0.0f);
worldMatrix = XMMatrixMultiply(worldMatrix, translateMatrix);

// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(m_Direct3D->GetDeviceContext());

// Render the model using the color shader.
result = m_ColorShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);
if (!result)
{
    return false;
}
//END OF ADDITIONAL CODE
// Present the rendered scene to the screen.
m_Direct3D->EndScene();

But the second triangle doesn't show up, i also put the complete example on github in case you want to try it yourself. I'm sure i'm missing something pretty basic but i can't figure it out

\$\endgroup\$
1
\$\begingroup\$

Ok, i was able to solve it, even if i can't really explain why. In the tutorial, inside the function ColorShaderClass::SetShaderParameters(), i had this:

bool ColorShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX& worldMatrix, XMMATRIX& viewMatrix,
                                       XMMATRIX& projectionMatrix)

[..]
// Transpose the matrices to prepare them for the shader.
worldMatrix = XMMatrixTranspose(worldMatrix);
viewMatrix = XMMatrixTranspose(viewMatrix);
projectionMatrix = XMMatrixTranspose(projectionMatrix);

// Lock the constant buffer so it can be written to.
result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if(FAILED(result))
{
    return false;
}

// Get a pointer to the data in the constant buffer.
dataPtr = (MatrixBufferType*)mappedResource.pData;

// Copy the matrices into the constant buffer.
dataPtr->world = worldMatrix;
dataPtr->view = viewMatrix;
dataPtr->projection = projectionMatrix;

As you can see, the worldMatrix, viewMatrix and projectionMatrix are passed to the function and used directly. I noticed that sometimes (under which circumstances? i dont know) this and other demos crashed with an ACCESS VIOLATION error, that happened exactly at this line:

viewMatrix = XMMatrixTranspose(viewMatrix);

Out of ideas, i decided to modify the function so that the 3 matrices are first passed to some local variables, so that the function operates on the copies, like this:

// Copy the 3 matrices to local variables

XMMATRIX worldMatrixLocal = worldMatrix;
XMMATRIX viewMatrixLocal = viewMatrix;
XMMATRIX projectionMatrixLocal = projectionMatrix;

// Transpose the matrices to prepare them for the shader.
worldMatrixLocal = XMMatrixTranspose(worldMatrixLocal);
viewMatrixLocal = XMMatrixTranspose(viewMatrixLocal);
projectionMatrixLocal = XMMatrixTranspose(projectionMatrixLocal);

// Copy the matrices into the constant buffer.
dataPtr->world = worldMatrixLocal;
dataPtr->view = viewMatrixLocal;
dataPtr->projection = projectionMatrixLocal;

This solved my problem, the 2 triangles are now shown correctly, unfortunately i can't explain why exactly this fix works.

\$\endgroup\$
3
  • \$\begingroup\$ You may be subject to misalignment, ensure that your objects of XMMATRIX type are at 16 byte overalignment. \$\endgroup\$ May 27 '16 at 18:18
  • \$\begingroup\$ correct me if i'm wrong, but i believed that, by following stackoverflow.com/questions/25300116/…, the problem could be avoided \$\endgroup\$
    – rekotc
    May 28 '16 at 13:48
  • \$\begingroup\$ Yes, you'll find there's no guarantee that function parameters are aligned to 16 byte boundaries. I'm fairly sure that you won't get any guarantees with local variables either, it just so happens that the stack frame is aligned to 16 byte boundaries and you only declare three 16-byte aligned variables. You could test if this is the case by declaring an int variable above the matrices in your function. If that breaks it, you know it's alignment that's causing your problem. __declspec(align('16')) is helpful, or dynamically allocate the matrix using an aligned allocator. \$\endgroup\$
    – MrCranky
    Jun 30 '18 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.