Advertisement

DX11 draw is skipping the first vertex?

Started by December 23, 2019 07:24 PM
5 comments, last by coderchris 5 years, 1 month ago

Hello,

I am running into a bizarre issue. I am rendering a bunch of cubes by expanding points in the geometry shader. My input topology is POINT_LIST. I am using a dynamic usage vertex buffer which is updated every frame. The vertex shader is basically pass through. The geometry shader then expands the point into a cube. What I am observing is that everything is rendering properly except the FIRST point / cube in the list.

I have run the graphics debugger from VS2019 and examined a frame. Looking at the actual vertex buffer for a given frame, it does contain the proper data (including the missing point in the proper location). However, when I then debug the vertex shader, the first point I see is actually the second point in the list. And from my understanding, the shader debugger only shows the first invocation of each shader, so I should be seeing that first point instead.

I then went one step further and downloaded nvidia nsight. From there I am seeing the same thing: the vertex buffer has all the right data. The input assembler however, is skipping the first point! It is even reading beyond the end of the vertex buffer by 1, resulting in a single garbage vertex...

I have tried adding a dummy point as the first point, and everything renders fine... but I'm not happy with that hack.

So, my question is, is there anything other way I can go about debugging this? Anything specific I should look for?

For reference, here are my actual rendering calls:

	uint stride = sizeof(VoxelVertex);
	uint offset = 0;

    context->VSSetShader(vs, NULL, 0);
	context->GSSetShader(gs, NULL, 0);
	context->PSSetShader(ps, NULL, 0);
	context->IASetInputLayout(layout);
	context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
    context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
  	context->VSSetConstantBuffers(0, 2, constantBuffers);
  	context->GSSetConstantBuffers(0, 2, constantBuffers);
  	context->PSSetConstantBuffers(0, 2, constantBuffers);
  	context->Draw(vertexCount, 0);


Hi Chris!

Can you post more code? I can't see anything wrong with that code.

Advertisement

Sure thing. Let me know if there's any other code you want to see.

vector<VoxelVertex> data;
//... fill in data

// Load bytecode
auto vsCSO = readFileBytes("cso/voxel_grid_vs.cso");
auto gsCSO = readFileBytes("cso/voxel_grid_gs.cso");
auto psCSO = readFileBytes("cso/voxel_grid_ps.cso");

// Create shaders
if (device->CreateVertexShader(vsCSO.data(), vsCSO.size(), nullptr, &vs) != S_OK)
	throw exception("failed to create vertex shader");
if (device->CreateGeometryShader(gsCSO.data(), gsCSO.size(), nullptr, &gs) != S_OK)
	throw exception("failed to create geometry shader");
if (device->CreatePixelShader(psCSO.data(), psCSO.size(), nullptr, &ps) != S_OK)
	throw exception("failed to create pixel shader");

// Create the input layout
D3D11_INPUT_ELEMENT_DESC local_layout[] =
{
	{ "POSITION", 0, DXGI_FORMAT_R16G16B16A16_UINT,   0, sizeof(VoxelVertex), D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

if (device->CreateInputLayout(local_layout, 1, vsCSO.data(), vsCSO.size(), &layout) != S_OK)
	throw exception("failed to create input layout");

// Create buffer			
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (uint)(sizeof(VoxelVertex) * data.size());
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;

if (device->CreateBuffer(&desc, NULL, &vb) != S_OK)
	throw exception("failed to create vertex buffer");

// Load data into buffer
D3D11_MAPPED_SUBRESOURCE mapped;
if (context->Map(vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped) != S_OK)
	throw exception("failed to map vertex buffer");
memcpy(mapped.pData, data.data(), sizeof(VoxelVertex) * data.size());
context->Unmap(vb, 0);

...

// Draw
uint vertexCount = data.size();
uint stride = sizeof(VoxelVertex);
uint offset = 0;

context->VSSetShader(vs, NULL, 0);
context->GSSetShader(gs, NULL, 0);
context->PSSetShader(ps, NULL, 0);
context->IASetInputLayout(layout);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
context->VSSetConstantBuffers(0, 2, constantBuffers);
context->GSSetConstantBuffers(0, 2, constantBuffers);
context->PSSetConstantBuffers(0, 2, constantBuffers);
context->Draw(vertexCount, 0);

Forum edit doesn't seem to be working, forgot to put this:

struct VoxelVertex
{
	ushort x, y, z;
	ushort properties;
};

You are setting AlignedByteOffset of local_layout[0] to the size of the vertex, so it will read from the next vertex. It has to be 0 in this case.

See here for more info: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11inputelement_desc

And yes, the forum is working properly. No problems whatsoever. Even the link is formatted correctly with "input" in italics.

Thank you so much, problem solved!

This topic is closed to new replies.

Advertisement