Asked by:
DrawInstanced/DrawIndexedInstanced Bug on Windows Phone 8.1

Question
-
Hi,
I have a Nokia Lumia 930 with OS version 8.10.14226.359.
Whenever I try to invoke ID3D11DeviceContext::DrawInstanced in a Windows Store App. it responds with device removal:
D3D11: Removing Device.
D3D11 WARNING: ID3D11Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DRIVER_INTERNAL_ERROR: There is strong evidence that the driver has performed an undefined operation; but it may be because the application performed an illegal or undefined operation to begin with.). [ EXECUTION WARNING #379: DEVICE_REMOVAL_PROCESS_POSSIBLY_AT_FAULT]If build the same app to desktop it works as expected.
Then, I investigated further, and modified the DirectX Sample Windows Store App. to use instanced data.
It seems the ID3D11DeviceContext::DrawIndexedInstanced method ignores the StartInstanceLocation parameter on Windows Phone. So I cannot draw more than 256 instances in one frame with multiple DrawIndexedInstanced calls.
When I build it as a desktop app it works as expected.
Anyone experienced similar issues?
Thanks,
Andras
Saturday, February 21, 2015 1:48 PM
All replies
-
You should post the code in here.
Vote if help you
Monday, February 23, 2015 5:39 AM -
I had no better idea, so I modified the example DirectX App in the store apps, and paste it here the modifications:
in Sample3DSceneRenderer::CreateDeviceDependentResources() i replaced the vertexDesc:
static const D3D11_INPUT_ELEMENT_DESC vertexDesc [] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "POSITION", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, };
at the end of createCubeTask, I added:
static DirectX::XMFLOAT3 instanceData[512]; //float x = -4.f, y = -4.f, z = -4.f; for (int i = 0; i < 512; i++) { instanceData[i].x = -4.f + 1.f * (i % 8); instanceData[i].y = -4.f + 1.f * ((i / 8) % 8); instanceData[i].z = -4.f + 1.f * ((i / 8 / 8) % 8); } D3D11_SUBRESOURCE_DATA instanceDataStruct = { 0 }; instanceDataStruct.pSysMem = instanceData; instanceDataStruct.SysMemPitch = 0; instanceDataStruct.SysMemSlicePitch = 0; CD3D11_BUFFER_DESC instanceBufferDesc(sizeof(instanceData), D3D11_BIND_VERTEX_BUFFER); DX::ThrowIfFailed( m_deviceResources->GetD3DDevice()->CreateBuffer( &instanceBufferDesc, &instanceDataStruct, &m_instanceBuffer));
Added this to the Sample3DSceneRenderer declaration:
Microsoft::WRL::ComPtr<ID3D11Buffer> m_instanceBuffer;
Replaced the eye position in Sample3DSceneRenderer::CreateWindowSizeDependentResources():
static const XMVECTORF32 eye = { 0.0f, 0.7f, 10.5f, 0.0f };
then, replaced Sample3DSceneRenderer::Render() with:
void Sample3DSceneRenderer::Render() { // Loading is asynchronous. Only draw geometry after it's loaded. if (!m_loadingComplete) { return; } auto context = m_deviceResources->GetD3DDeviceContext(); // Prepare the constant buffer to send it to the graphics device. context->UpdateSubresource( m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0 ); // Each vertex is one instance of the VertexPositionColor struct. UINT stride[] = { sizeof(VertexPositionColor), sizeof(XMFLOAT3) }; UINT offset[] = { 0, 0 }; ID3D11Buffer* buf[] = { m_vertexBuffer.Get(), m_instanceBuffer.Get() }; context->IASetVertexBuffers( 0, 2, buf, stride, offset); context->IASetIndexBuffer( m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short). 0 ); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->IASetInputLayout(m_inputLayout.Get()); // Attach our vertex shader. context->VSSetShader( m_vertexShader.Get(), nullptr, 0 ); // Send the constant buffer to the graphics device. context->VSSetConstantBuffers( 0, 1, m_constantBuffer.GetAddressOf() ); // Attach our pixel shader. context->PSSetShader( m_pixelShader.Get(), nullptr, 0 ); context->DrawIndexedInstanced(m_indexCount, 256, 0, 0, 0); context->DrawIndexedInstanced(m_indexCount, 256, 0, 0, 256); }
I modified the SimpleVertexShader.hlsl as well:
cbuffer ModelViewProjectionConstantBuffer : register(b0) { matrix model; matrix view; matrix projection; }; // Per-vertex data used as input to the vertex shader. struct VertexShaderInput { float3 pos : POSITION; float3 color : COLOR0; float3 pos2 : POSITION1; }; // Per-pixel color data passed through the pixel shader. struct PixelShaderInput { float4 pos : SV_POSITION; float3 color : COLOR0; }; // Simple shader to do vertex processing on the GPU. PixelShaderInput main(VertexShaderInput input) { PixelShaderInput output; float4 pos = float4(input.pos+input.pos2, 1.0f); // Transform the vertex position into projected space. pos = mul(pos, model); pos = mul(pos, view); pos = mul(pos, projection); output.pos = pos; // Pass the color through without modification. output.color = input.color; return output; }
It draws 512 instances of the cubes when compiled to desktop.
But when I compile and run on windows phone, only the first maximum 256 instance is visible, no matter what I pass to StartInstanceLocation in DrawIndexedInstanced
- Edited by throwthisaway Monday, February 23, 2015 3:46 PM
Monday, February 23, 2015 3:45 PM -
Also, if I replace Sample3DSceneRenderer::Render() with this, in the example above,
the desktop app draws something (some rectangles as expected), the windows phone app dumps this error to the output window, when DrawInstanced is called:
D3D11: Removing Device.
D3D11 WARNING: ID3D11Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DRIVER_INTERNAL_ERROR: There is strong evidence that the driver has performed an undefined operation; but it may be because the application performed an illegal or undefined operation to begin with.). [ EXECUTION WARNING #379: DEVICE_REMOVAL_PROCESS_POSSIBLY_AT_FAULT]
void Sample3DSceneRenderer::Render() { // Loading is asynchronous. Only draw geometry after it's loaded. if (!m_loadingComplete) { return; } auto context = m_deviceResources->GetD3DDeviceContext(); // Prepare the constant buffer to send it to the graphics device. context->UpdateSubresource( m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0 ); // Each vertex is one instance of the VertexPositionColor struct. UINT stride[] = { sizeof(VertexPositionColor), sizeof(XMFLOAT3) }; UINT offset[] = { 0, 0 }; ID3D11Buffer* buf[] = { m_vertexBuffer.Get(), m_instanceBuffer.Get() }; context->IASetVertexBuffers( 0, 2, buf, stride, offset); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->IASetInputLayout(m_inputLayout.Get()); // Attach our vertex shader. context->VSSetShader( m_vertexShader.Get(), nullptr, 0 ); // Send the constant buffer to the graphics device. context->VSSetConstantBuffers( 0, 1, m_constantBuffer.GetAddressOf() ); // Attach our pixel shader. context->PSSetShader( m_pixelShader.Get(), nullptr, 0 ); context->DrawInstanced(8, 1, 0, 0); }
Monday, February 23, 2015 3:51 PM -
Hi Andras,
* Have you checked the DirectX Level supported by the Nokia Phone? I got this same error with DirectX level 9-1 and 9-2 when calling DrawIndexedInstanced.
* What DirectX level was used to compile your shaders?
* Try running your game using a Warp device and see if the problem is present as well.
Note that Driver bugs fall under the hardware manufacturer's responsibility.
I hope it helps!!!
Tarh Ik
PS: This posting has been posted "AS IS"
Tarh ik
Thursday, February 26, 2015 10:18 PM -
Hi,
Thanks for the answer.
Lumia 930 supports DX 11 profile 9.3.
And the shaders are compiled as Shader Model 4 level 9_3
A.
Thursday, February 26, 2015 11:43 PM