Just for background, I'm designing a soft engine in C# using the SharpDX DirectX wrapper library. I've gotten around to implementing the render engine, and I can render a texture to a face, except it only renders exactly one frame. It renders a triangle once, but on the next draw call, the screen is cleared. Even though I've made sure the render call is still firing every frame, the rendered item goes away, and does not get re-drawn in the next or any subsequent frame.
I think it has something to do with the way I initialize my resources; to minimize shader switching and boost performance, I have my render engine hold a set of pre-defined shader classes. Then, only when it is necessary will the shader access the device context and set the vertex, constant, index, etc. buffers one time when the method Shader.SetActive()
is called. When the shader needs to render something, it can write directly to the buffers that have been created and set in the Shader.SetActive()
method, using a method called UpdateShader()
.
Here's the source for SetActive()
:
public override void SetActive(D3D11.Device device, D3D11.DeviceContext context)
{
/*========================== Set Pointers to GPU Buffers ==========================*/
// write Matrix data first to constant buffer
matrixBuffer = new D3D11.Buffer(device, matrixBufferDesc);
vertexBuffer = new D3D11.Buffer(device, vertexBufferDesc);
indexBuffer = new D3D11.Buffer(device, indexBufferDesc);
context.InputAssembler.SetVertexBuffers(0, new D3D11.VertexBufferBinding(vertexBuffer,
Utilities.SizeOf<VertexPositionTexture>(), 0));
context.InputAssembler.SetIndexBuffer(indexBuffer, Format.R32_UInt, 0);
context.VertexShader.SetConstantBuffer(matrixBufferPos, matrixBuffer);
context.PixelShader.SetShaderResource(0, shaderTexture);
context.InputAssembler.InputLayout = inputLayout;
/*========================== set context shaders ==========================*/
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
context.PixelShader.SetSampler(0, samplerState);
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
}
Here's the code for UpdateShader():
public void UpdateShader(D3D11.Device device, D3D11.DeviceContext context,
Matrix worldViewProj, VertexPositionTexture[] vpts, int[] indices)
{
DataStream mappedResource;
//write to buffers
context.MapSubresource(matrixBuffer, D3D11.MapMode.WriteDiscard, D3D11.MapFlags.None,
out mappedResource);
mappedResource.Write(worldViewProj);
context.UnmapSubresource(matrixBuffer, 0);
context.MapSubresource(vertexBuffer, D3D11.MapMode.WriteDiscard, D3D11.MapFlags.None,
out mappedResource);
mappedResource.WriteRange(vpts);
context.UnmapSubresource(vertexBuffer, 0);
context.MapSubresource(indexBuffer, D3D11.MapMode.WriteDiscard, D3D11.MapFlags.None,
out mappedResource);
mappedResource.WriteRange(indices);
context.UnmapSubresource(indexBuffer, 0);
context.DrawIndexed(indices.Length, 0, 0);
}
I think something that happens once in the SetActive()
method should need to actually happen multiple times, and should be moved to the UpdateShader()
method, but for the life of me I can't figure out what it is, or even if my reasoning is the correct.
Why is my render engine only rendering one frame?