I am attempting to pass vertex data from the CPU to the GPU for a compute shader. The vertex data is contained in a structured buffer
// CS VERTEX BUFFER CONTENT (SHADER RESOURCE) -----------------------------------------------------
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(VertexBufferContent) * _osInstance.m_VertexBufferVertexCount;
bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.StructureByteStride = sizeof(VertexBufferContent);
hr = m_Device->CreateBuffer(&bufferDesc, &data, &_osInstance.m_VertexBufferComputeShader);
CheckFailure(hr, "Failed CS vertex buffer create", "");
I fill _osInstance.m_VertexSource (float*) in here:
osInstances[_id].get()->m_VertexSource = new VertexBufferContent[osInstances[_id].get()->m_VertexBufferVertexCount];
for (int i = 0; i < osInstances[_id].get()->m_VertexBufferVertexCount; ++i)
{
VertexBufferContent& v = osInstances[_id].get()->m_VertexSource[i];
v.position.x = sourceVertices[0];
v.position.y = sourceVertices[1];
v.position.z = sourceVertices[2];
v.position.w = 1.0f;
v.normal.x = sourceNormals[0];
v.normal.y = sourceNormals[1];
v.normal.z = sourceNormals[2];
v.texCoord.x = sourceUV[0];
v.texCoord.y = sourceUV[1];
sourceVertices += 3;
sourceNormals += 3;
sourceUV += 2;
ss << "(" << v.texCoord.x << ", " << v.texCoord.y << ") ";
}
DebugInUnity(ss.str());
My debugging out method tells me that this data has been filled, I also check the data again before I pass it to the buffer, and it is still correct then.
I then create a SRV for the buffer:
// CS VERTEX BUFFER SRV --------------------------------------------------------------------
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srvDesc.BufferEx.FirstElement = 0;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
srvDesc.BufferEx.NumElements = _osInstance.m_VertexBufferVertexCount;
hr = m_Device->CreateShaderResourceView(_osInstance.m_VertexBufferComputeShader, &srvDesc,
&_osInstance.m_VertexBufferComputeShaderSRV);
CheckFailure(hr, "Failed CS vertex buffer SRV create", "");
I supply the data to the compute shader
// set back to defaults
ID3D11UnorderedAccessView* ppUAViewNULL[1] = { NULL };
ID3D11ShaderResourceView* ppSRVNULL[1] = { NULL };
ctx->CSSetShader(NULL, NULL, 0);
ctx->CSSetUnorderedAccessViews(0, 1, ppUAViewNULL, NULL);
ctx->CSSetShaderResources(0, 1, ppSRVNULL);
// set texture map shader & resources
ctx->CSSetShader(m_ComputeTextureMap, NULL, 0);
ctx->CSSetUnorderedAccessViews(0, 1, &_osInstance.m_TexMapUAV, NULL);
ctx->CSSetShaderResources(0, 1, &_osInstance.m_VertexBufferComputeShaderSRV);
// run the shader (32 * 16, 32 * 16, 1 * 1) (512, 512, 1)
ctx->Dispatch(32, 32, 1);
And finally, here is my compute shader, which has been stripped down to simply return my input data as output, for debugging purposes
struct Input
{
float4 Pos;
float2 Tex;
float3 Norm;
};
StructuredBuffer<Input> inputBuffer : register(t0);
RWTexture2D<float4> outTex : register(u0);
[numthreads(16, 16, 1)]
void main( uint3 dispatchThreadId : SV_DispatchThreadID)
{
// identify texel via various IDs
float2 p = dispatchThreadId.xy;
int index = dispatchThreadId.x + (dispatchThreadId.y * 16) +
dispatchThreadId.z;
outTex[p] = float4(inputBuffer[index].Tex.x, inputBuffer[index].Tex.y,
index, 1);
}
This is a sample of the UV coordinates of the vertex data from CPU side:
NativePlugin: (0.373799, 0.318191) (0.393596, 0.304814) (0.373799, 0.2834) (0.354002, 0.304814) (0.342019, 0.250794) (0.324335, 0.290564) (0.299219, 0.23788) (0.288421, 0.280647) (0.248892, 0.233575) (0.248892, 0.277129) (0.40558, 0.250794) (0.423263, 0.290564) (0.373799, 0.214219) (0.321637, 0.185627) (0.248892, 0.17434) (0.448379, 0.23788) (0.459178, 0.280647) (0.425961, 0.175268) (0.37258, 0.133626) (0.248892, 0.102047) (0.498706, 0.233575) (0.498706, 0.277129) (0.498706, 0.169569) (0.498706, 0.0975687) (0.498706, 0.0975687) (0.373458, 0.0217557) (0.373458, 0.0217557) (0.125205, 0.142171) (0.176148, 0.18481) (0.0718234, 0.18592) (0.123986, 0.209653) (0.0494056, 0.23788) (0.092205, 0.250794) (0.0386071, 0.280647) (0.0745213, 0.290564) (0.123986, 0.2834) (0.104189, 0.304814) (0.143782, 0.304814)
And this the same sample of UV coordinates of the vertex data from the GPU (first 2 coordinates are UV, 3rd coordinate is vertex index):
NativePlugin: Texel Map ( 0.144993, 0, 0, 1)( 0, 5.04467e-44, 1, 1)( 0, 0, 2, 1)( 0, 0, 3, 1)( 0, 0, 4, 1)( 0, 0, 5, 1)( 1.04694e-38, 9.45921e-39, 6, 1)( 6.79596e-39, 1.08367e-38, 7, 1)( 1.04694e-38, 9.45921e-39, 8, 1)( 8.44892e-39, 7.89796e-39, 9, 1)( 1.01021e-38, 7.34697e-39, 10, 1)( 7.98982e-39, 7.16327e-39, 11, 1)( 5.32655e-39, 7.98982e-39, 12, 1)( 7.9898e-39, 8.44898e-39, 13, 1)( 5.32655e-39, 7.98982e-39, 14, 1)( 8.44894e-39, 9.64285e-39, 15, 1)( 8.44902e-39, 4.5001e-39, 16, 1)( 6.42853e-39, 9.91838e-39, 17, 1)( 1.04694e-38, 8.44902e-39, 18, 1)( 9.45921e-39, 8.9082e-39, 19, 1)( 7.07142e-39, 8.44896e-39, 20, 1)( 8.90821e-39, 9.64289e-39, 21, 1)( 9.91838e-39, 1.05612e-38, 22, 1)( 6.88771e-39, 1.06531e-38, 23, 1)( 9.2755e-39, 9.36738e-39, 24, 1)
If I run it again, I get different (still wrong) floats:
NativePlugin: Texel Map ( 0.16544, 0, 0, 1)( 0, 5.04467e-44, 1, 1)( 0, 0, 2, 1)( 0, 0, 3, 1)( 0, 0, 4, 1)( 0, 0, 5, 1)( 1.4013e-45, 0, 6, 1)( 0, 1.86373e-43, 7, 1)( 1.86373e-43, 0, 8, 1)( 0, 3.78351e-43, 9, 1)( 0, 0, 10, 1)( 0, 4.2039e-45, 11, 1)( 1.4013e-45, 0, 12, 1)( 0, 5.60519e-45, 13, 1)( 3.08286e-44, 0, 14, 1)( 0, 3.7652e-31, 15, 1)( 1.41531e-43, 0, 16, 1)( 0, 4.07297e-28, 17, 1)( 3.75548e-43, 0, 18, 1)( 0, 0, 19, 1)( 4.2039e-45, 0, 20, 1)( 0, 3.08286e-44, 21, 1)( 1.86373e-43, 0, 22, 1)( 0, 4.07325e-28, 23, 1)( 0, 0, 24, 1)( 0, 0, 25, 1)( 0, 0, 26, 1)( 0, 0, 27, 1)( 0, 0, 28, 1)( 0, 3.65425e-31, 29, 1)( 3.76528e-31, 0, 30, 1)( -3.85186e-34, 4.04443e-34, 31, 1)( 3.21674e-35, 1.00073e-34, 32, 1)( 8.83558e-33, 4.03289e-34, 33, 1)( 2.86998e+37, -2.52443e-29, 34, 1)( 1.01939e-38, 4.79631e-30, 35, 1)( 0, 0, 36, 1)( 1.41531e-43, 3.01952e+37, 37, 1)( 9.09186e-39, 9.27553e-39, 38, 1)( 1.06531e-38, 1.00102e-38, 39, 1)( 1.01939e-38, 1.62551e-43, 40, 1)( 0, 0, 41, 1)( 4.03013e-42, 0, 42, 1)( 7.53065e-39, 1.01939e-38, 43, 1)( 0, 0, 44, 1)( 0, 3.73866e-42, 45, 1)
My question is: does anyone understand why I appear to be getting random numbers when I pass the data to the GPU?
EDIT: I have created a staging buffer to check the structured vertex buffer's content prior to the dispatch call, and found that the data is incorrect in that stage. I still have no idea why, though.
Solved
I have fixed the problem. I changed m_VertexSource to use a unique_ptr and where I was passing m_VertexSource to data.pSysMem I changed the line from
data.pSysMem = &_osInstance.m_VertexSource;
to
data.pSysMem = _osInstance.m_VertexSource.get();