Sign in to follow this  
damix911

D3D11 Shader reflection

Recommended Posts

Hi guys! I'm not being able to retrieve reflection info from my compute shader. I have the following C++ code:
	ID3D11ComputeShader *compute;
	hr = d3dDevice->CreateComputeShader(
		bytecode->GetBufferPointer(),
		bytecode->GetBufferSize(),
		NULL,
		&compute);

	d3dContext->CSSetShader(compute, NULL, NULL);

	ID3D11ShaderReflection *computeRefl;
	hr = D3DReflect(
		bytecode->GetBufferPointer(),
		bytecode->GetBufferSize(),
		IID_ID3D11ShaderReflection,
		(void **)&computeRefl);

	D3D11_SHADER_VARIABLE_DESC descA;
	computeRefl->GetVariableByName("a")->GetDesc(&descA);
	D3D11_SHADER_VARIABLE_DESC descY;
	computeRefl->GetVariableByName("y")->GetDesc(&descY);

And an empty compute shader that declares the following global variables:
RWStructuredBuffer<float> y;
float a;
StructuredBuffer<float> x;
StructuredBuffer<float> b;
int N;

...

Both calls to GetVariableByName return something invalid, unless I put variable a inside a constant buffer, in which case the first call works fine. I'm doing this because in the end I want to retrieve the input slots of the variable, in order to set the input values; I saw some examples on the Internet in which people call CSSetShaderResources and CSSetUnorderedAccessViews passing 0 as the first parameter, but I couldn't find anything in the MSDN saying that by doing this they actually access the first global variable of the shader. Any suggestion? Thank you! Dario

Share this post


Link to post
Share on other sites
Is your shader body empty as well? If the variables isn't actually used in the shader they probably wont show up in the reflection either. Now I haven't played with compute shaders yet, but that's how it works for the other shader types anyway.

Share this post


Link to post
Share on other sites
Hi panic, thank you for the suggestion, I didn't really consider that aspect! It looks like it applies to variables in constant buffer, but I'm still not able to reflect Buffers declared in HLSL. By the way, in the meantime I completed the application, but I am unsatisfied because in the end I'm doing what I didn't want to do:


UINT initCounts = 0;
d3dContext->CSSetUnorderedAccessViews(0, 1, &viewY, &initCounts);
d3dContext->CSSetShaderResources(0, 1, &viewX);
d3dContext->CSSetShaderResources(1, 1, &viewB);
d3dContext->CSSetConstantBuffers(0, 1, &buffCB);
d3dContext->CSSetShader(compute, NULL, NULL);

int nGroups = (N / 4) + ((N % 4) ? 1 : 0);
d3dContext->Dispatch(nGroups, 1, 1);



that is, blindy setting the slots in the same order as the (supposedly) corresponding variables appear in the HLSL. One of my mistakes was in the fact that I assumed that different kinds of resources used consecutive slots, while aparently different kinds are all based at slot 0. So the only non-zero slot I'm setting is the one for buffer viewB, because it is the second of its kind.

The following is the full source code of my program, without reflection; it implements the vector operation:

y := a * x + b

where x, b and y are same-size vectors and a is a scalar, hopefully someone will find it useful! It should work on most DirectX 10 hardware; it was developed and tested on a GeForce 210 (DirectX 10.1). Code should be linked against d3d11.lib and d3dx11.lib.

Bye!

Dario

Compute shader (compute.csh)

RWStructuredBuffer<float> y;
Buffer<float> x;
Buffer<float> b;

cbuffer CB
{
float a;
int N;
};

[numthreads(4, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
int index = DTid.x;

if (index < N)
y[index] = a * x[index] + b[index];
}



C++ Application (main.cpp)

#include <iostream>
#include <d3d11.h>
#include <d3dx11.h>

template<class T>
inline void SafeRelease(T *&p)
{
if (p)
{
p->Release();
p = NULL;
}
}

HRESULT ShowData(ID3D11Buffer *buff, int N, ID3D11Buffer *buffStaging, ID3D11DeviceContext *d3dContext)
{
d3dContext->CopyResource(buffStaging, buff);

D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = d3dContext->Map(buffStaging, 0, D3D11_MAP_READ, 0, &mapped);
float *result = (float *)mapped.pData;

for (int i = 0; i < N; ++i)
{
std::cout << " " << result[i];
}

d3dContext->Unmap(buffStaging, 0);

return hr;
}

int main(int argc, char *argv[])
{
float a = 2.0f;
int N = 13;

HRESULT hr;

ID3D11Device *d3dDevice;
D3D_FEATURE_LEVEL features;
ID3D11DeviceContext *d3dContext;

hr = D3D11CreateDevice(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_DEBUG,
NULL,
0,
D3D11_SDK_VERSION,
&d3dDevice,
&features,
&d3dContext);

ID3D10Blob *bytecode;
ID3D10Blob *errors;

hr = D3DX11CompileFromFile(
L"compute.csh",
NULL,
NULL,
"main",
"cs_4_0",
D3D10_SHADER_ENABLE_STRICTNESS,
0,
NULL,
&bytecode,
&errors,
NULL);

if (errors)
{
MessageBoxA(NULL, (LPSTR)errors->GetBufferPointer(), "Error!", MB_ICONSTOP);
errors->Release();
}

ID3D11ComputeShader *compute;
hr = d3dDevice->CreateComputeShader(
bytecode->GetBufferPointer(),
bytecode->GetBufferSize(),
NULL,
&compute);

ID3D11Buffer *buffCB;
ID3D11Buffer *buffY;
ID3D11Buffer *buffX;
ID3D11Buffer *buffB;
ID3D11Buffer *buffStaging;

D3D11_BUFFER_DESC descCB;
descCB.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
descCB.ByteWidth = 16;
descCB.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
descCB.MiscFlags = 0;
descCB.StructureByteStride = 0;
descCB.Usage = D3D11_USAGE_DYNAMIC;

struct MyCB {
float a;
int N;
int foo1;
int foo2;
} dataCB;

dataCB.a = a;
dataCB.N = N;
D3D11_SUBRESOURCE_DATA initCB;
initCB.pSysMem = &dataCB;
initCB.SysMemPitch = 0;
initCB.SysMemSlicePitch = 0;

hr = d3dDevice->CreateBuffer(&descCB, &initCB, &buffCB);

{
D3D11_BUFFER_DESC descY;
descY.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
descY.ByteWidth = N * sizeof(float);
descY.CPUAccessFlags = 0;
descY.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
descY.StructureByteStride = sizeof(float);
descY.Usage = D3D11_USAGE_DEFAULT;

float *dataY = new float[N];
D3D11_SUBRESOURCE_DATA initY;
initY.pSysMem = dataY;
initY.SysMemPitch = 0;
initY.SysMemSlicePitch = 0;
hr = d3dDevice->CreateBuffer(&descY, &initY, &buffY);
delete [] dataY;
}

{
D3D11_BUFFER_DESC descX;
descX.BindFlags = D3D11_BIND_SHADER_RESOURCE;
descX.ByteWidth = N * sizeof(float);
descX.CPUAccessFlags = 0;
descX.MiscFlags = 0;
descX.StructureByteStride = 0;
descX.Usage = D3D11_USAGE_DEFAULT;

float *dataX = new float[N];
for (int i = 0; i < N; ++i) dataX[i] = 10 * i;
D3D11_SUBRESOURCE_DATA initX;
initX.pSysMem = dataX;
initX.SysMemPitch = 0;
initX.SysMemSlicePitch = 0;
hr = d3dDevice->CreateBuffer(&descX, &initX, &buffX);
delete [] dataX;
}

{
D3D11_BUFFER_DESC descB;
descB.BindFlags = D3D11_BIND_SHADER_RESOURCE;
descB.ByteWidth = N * sizeof(float);
descB.CPUAccessFlags = 0;
descB.MiscFlags = 0;
descB.StructureByteStride = 0;
descB.Usage = D3D11_USAGE_DEFAULT;

float *dataB = new float[N];
for (int i = 0; i < N; ++i) dataB[i] = i;
D3D11_SUBRESOURCE_DATA initB;
initB.pSysMem = dataB;
initB.SysMemPitch = 0;
initB.SysMemSlicePitch = 0;
hr = d3dDevice->CreateBuffer(&descB, &initB, &buffB);
delete [] dataB;
}

ID3D11UnorderedAccessView *viewY;
D3D11_UNORDERED_ACCESS_VIEW_DESC vDescY;
vDescY.Format = DXGI_FORMAT_UNKNOWN;
vDescY.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
vDescY.Buffer.FirstElement = 0;
vDescY.Buffer.NumElements = N;
vDescY.Buffer.Flags = 0;
hr = d3dDevice->CreateUnorderedAccessView(buffY, &vDescY, &viewY);

ID3D11ShaderResourceView *viewX;
D3D11_SHADER_RESOURCE_VIEW_DESC vDescX;
vDescX.Format = DXGI_FORMAT_R32_FLOAT;
vDescX.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
vDescX.BufferEx.FirstElement = 0;
vDescX.BufferEx.NumElements = N;
vDescX.BufferEx.Flags = 0;
hr = d3dDevice->CreateShaderResourceView(buffX, &vDescX, &viewX);

ID3D11ShaderResourceView *viewB;
D3D11_SHADER_RESOURCE_VIEW_DESC vDescB;
vDescB.Format = DXGI_FORMAT_R32_FLOAT;
vDescB.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
vDescB.BufferEx.FirstElement = 0;
vDescB.BufferEx.NumElements = N;
vDescB.BufferEx.Flags = 0;
hr = d3dDevice->CreateShaderResourceView(buffB, &vDescB, &viewB);

UINT initCounts = 0;
d3dContext->CSSetUnorderedAccessViews(0, 1, &viewY, &initCounts);
d3dContext->CSSetShaderResources(0, 1, &viewX);
d3dContext->CSSetShaderResources(1, 1, &viewB);
d3dContext->CSSetConstantBuffers(0, 1, &buffCB);
d3dContext->CSSetShader(compute, NULL, NULL);

int nGroups = (N / 4) + ((N % 4) ? 1 : 0);
d3dContext->Dispatch(nGroups, 1, 1);

D3D11_BUFFER_DESC descStaging;
descStaging.BindFlags = 0;
descStaging.ByteWidth = N * sizeof(float);
descStaging.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
descStaging.MiscFlags = 0;
descStaging.StructureByteStride = sizeof(float);
descStaging.Usage = D3D11_USAGE_STAGING;

float *dataStaging = new float[N];
D3D11_SUBRESOURCE_DATA initStaging;
initStaging.pSysMem = dataStaging;
initStaging.SysMemPitch = 0;
initStaging.SysMemSlicePitch = 0;
hr = d3dDevice->CreateBuffer(&descStaging, &initStaging, &buffStaging);
delete [] dataStaging;

std::cout << " " << a << " * " << std::endl;
hr = ShowData(buffX, N, buffStaging, d3dContext);
std::cout << " + " << std::endl;
hr = ShowData(buffB, N, buffStaging, d3dContext);
std::cout << " = " << std::endl;
hr = ShowData(buffY, N, buffStaging, d3dContext);

SafeRelease(buffCB);
SafeRelease(buffY);
SafeRelease(buffX);
SafeRelease(buffB);
SafeRelease(buffStaging);
SafeRelease(viewY);
SafeRelease(viewX);
SafeRelease(viewB);
SafeRelease(bytecode);
SafeRelease(errors);
SafeRelease(compute);
SafeRelease(d3dDevice);
SafeRelease(d3dContext);

std::cin.get();

return 0;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this