DirectX11 Setting up the Constant Buffer help

Started by
6 comments, last by Tim Lawton 11 years, 5 months ago
Hey there,

I've just setup my Constant Buffer in DirectX11, everything seems to be going fine, but the "IASetVertexBuffers" seems to be breaking while I debug, I havn't any idea why, could an experienced programmer please take a look and tell me if I have made a mistake in Syntax or something?

here is a screenshot of where it breaks: http://img194.imageshack.us/img194/6109/herrrx.jpg

Thanks

Object.cpp

#include "Object.h"
Object::Object()
{
}
Object::~Object()
{
}
void Object::Render(ID3D11DeviceContext * pImmediateContext)
{
OFFSET Offset;
Offset.X = 0.5f;
Offset.Y = 0.2f;
Offset.Z = 0.7f;
pImmediateContext->UpdateSubresource(pCBuffer, 0, 0, &Offset, 0, 0);
// Render a triangle
VertexShader(pImmediateContext);
PixelShader(pImmediateContext);
pImmediateContext->Draw( 3, 0 );
}

void Object::VertexShader(ID3D11DeviceContext * pImmediateContext)
{
pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
}

void Object::PixelShader(ID3D11DeviceContext * pImmediateContext)
{
pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
}

HRESULT Object::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* pErrorBlob;
hr = D3DX11CompileFromFile( szFileName,
NULL,
NULL,
szEntryPoint,
szShaderModel,
dwShaderFlags,
0,
NULL,
ppBlobOut,
&pErrorBlob,
NULL );
if( FAILED(hr) )
{
if( pErrorBlob != NULL )
OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
if( pErrorBlob ) pErrorBlob->Release();
return hr;
}
if( pErrorBlob ) pErrorBlob->Release();
return S_OK;
}

HRESULT Object::InitObject(ID3D11Device * device, ID3D11DeviceContext * pImmediateContext)
{
HRESULT hr = S_OK;

// Compile the vertex shader
ID3DBlob* pVSBlob = NULL;
hr = CompileShaderFromFile( L"Shader.fx",
"VShader",
"vs_4_0",
&pVSBlob );

if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}

// Create the vertex shader
hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
if( FAILED( hr ) )
{
pVSBlob->Release();
return hr;
}

// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
UINT numElements = ARRAYSIZE( layout );
// Create the input layout
hr = device->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout );
pVSBlob->Release();
if( FAILED( hr ) )
return hr;
// Set the input layout
pImmediateContext->IASetInputLayout( g_pVertexLayout );
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile( L"Shader.fx",
"PShader",
"ps_4_0",
&pPSBlob );
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the pixel shader
hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
pPSBlob->Release();
if( FAILED( hr ) )
return hr;
// Create vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 16;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
/*
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
*/
hr = device->CreateBuffer( &bd, NULL, &pCBuffer );
pImmediateContext->VSSetConstantBuffers(0, 1, &pCBuffer);
if( FAILED( hr ) )
return hr;
return hr;
}
void Object::SetupVertex(ID3D11DeviceContext * pImmediateContext)
{
// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);
// Set primitive topology
pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
}

void Object::CleanupObject()
{
if( g_pVertexBuffer ) g_pVertexBuffer->Release();
if( g_pVertexLayout ) g_pVertexLayout->Release();
if( g_pVertexShader ) g_pVertexShader->Release();
if( g_pPixelShader ) g_pPixelShader->Release();
}


Shader.fx

//Created by Tim Lawton 2012
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
//Constant Buffer
cbuffer ConstantBuffer
{
float3 Offset;
}

//Struct to return two values
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
// create a VOut struct
VOut output;
// set the output values
output.position = position;
output.position.x += Offset.x;
output.position.y += Offset.y;
output.position.xy *= Offset.z;
output.color = color;
// return the output values
return output;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
Advertisement
Where do you create your vertex buffer? According to your code, you don't create a vertex buffer.

Cheers!
[sub]As Kauna says... You sort of set off trying to create one and then don't[/sub]

[sub]// Create vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 16;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;[/sub]

[sub]//You comment out your vertices sub resource??[/sub]

[sub]/*
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
*/[/sub]

[sub]//You dont create the buffer![/sub]
[sub]something like...device->Createe buffer(&bd, &initdata, &vertexbuffer) or whatever the names are exactly![/sub]

[sub] hr = device->CreateBuffer( &bd, NULL, &pCBuffer );[/sub]
ok guys, taken what you said and made some changes, yet I still get the same problems. I've commented it so it might be easier to read.

The constant buffer is created and Setup at the bottom of Object::InitObject. and then the UpdateSubresource is in Object::Render to update the constant buffer, yet I still get the same problem in the screenshot with the "pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);"

I get the feeling something is suppose to be passed from InitObject into the UpdateSubresources parameters, but I'm not sure what. If you could take a look at this updated code and point me in the right direction that'd be great, thanks!


Object.cpp
#include "Object.h"
Object::Object()
{
}
Object::~Object()
{
}
void Object::Render(ID3D11DeviceContext * pImmediateContext)
{
OFFSET Offset;
Offset.X = 0.5f;
Offset.Y = 0.2f;
Offset.Z = 0.7f;
pImmediateContext->UpdateSubresource(g_pCBuffer, 0, 0, &Offset, 0, 0);
// select which vertex buffer to display
UINT stride = sizeof(VERTEX);
UINT offset = 0;
pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);
// select which primtive type we are using
pImmediateContext->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Render a triangle
VertexShader(pImmediateContext);
PixelShader(pImmediateContext);
pImmediateContext->Draw( 3, 0 );
}
void Object::InitGraphics(ID3D11Device * device, ID3D11DeviceContext * pImmediateContext)
{
// create a triangle using the VERTEX struct
VERTEX OurVertices[] =
{
{0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
{0.45f, -0.5, 0.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
{-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)}
};

// create the vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC; // write access access by CPU and GPU
bd.ByteWidth = sizeof(VERTEX) * 3; // size is the VERTEX struct * 3
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // use as a vertex buffer
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // allow CPU to write in buffer
device->CreateBuffer(&bd, NULL, &g_pVertexBuffer); // create the buffer

// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
pImmediateContext->Map(g_pVertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices)); // copy the data
pImmediateContext->Unmap(g_pVertexBuffer, NULL); // unmap the buffer
}

void Object::VertexShader(ID3D11DeviceContext * pImmediateContext)
{
pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
}

void Object::PixelShader(ID3D11DeviceContext * pImmediateContext)
{
pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
}

HRESULT Object::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* pErrorBlob;
hr = D3DX11CompileFromFile( szFileName,
NULL,
NULL,
szEntryPoint,
szShaderModel,
dwShaderFlags,
0,
NULL,
ppBlobOut,
&pErrorBlob,
NULL );
if( FAILED(hr) )
{
if( pErrorBlob != NULL )
OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
if( pErrorBlob ) pErrorBlob->Release();
return hr;
}
if( pErrorBlob ) pErrorBlob->Release();
return S_OK;
}

HRESULT Object::InitObject(ID3D11Device * device, ID3D11DeviceContext * pImmediateContext)
{
HRESULT hr = S_OK;
//------------------
// VERTEX SHADER
//------------------
// Compile the vertex shader
ID3DBlob* pVSBlob = NULL;
hr = CompileShaderFromFile( L"Shader.fx",
"VShader",
"vs_4_0",
&pVSBlob );

//Error Handling
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}

// Create the vertex shader
hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
if( FAILED( hr ) )
{
pVSBlob->Release();
return hr;
}

//Allows the Vertex Shader to return 2 values, Position and Color
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
UINT numElements = ARRAYSIZE( layout );
// Create the input layout
hr = device->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout );
pVSBlob->Release();
if( FAILED( hr ) )
return hr;
// Set the input layout
pImmediateContext->IASetInputLayout( g_pVertexLayout );
//------------------
// PIXEL SHADER
//------------------
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile( L"Shader.fx",
"PShader",
"ps_4_0",
&pPSBlob );
//Error handling
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the pixel shader
hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
pPSBlob->Release();
if( FAILED( hr ) )
return hr;
//------------------
// CONSTANT BUFFER
//------------------
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = 16;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
//Create Constant Buffer
device->CreateBuffer(&bd, NULL, &g_pCBuffer);
//Setup Constant Buffer
pImmediateContext->VSSetConstantBuffers(0, 1, &g_pCBuffer);
if( FAILED( hr ) )
return hr;

return hr;
}

void Object::CleanupObject()
{
if( g_pVertexBuffer ) g_pVertexBuffer->Release();
if( g_pVertexLayout ) g_pVertexLayout->Release();
if( g_pVertexShader ) g_pVertexShader->Release();
if( g_pPixelShader ) g_pPixelShader->Release();
}


Here is also my main loop in main.cpp if you are interested

// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
gfx.clearBackBuffer(); //Clear Stage
obj.Render(gfx.getImmediateContext()); //Draw
obj.InitGraphics(gfx.getDevice(),
gfx.getImmediateContext());
obj.CleanupObject(); //Cleanup objects
gfx.present(); //Present
}
}
gfx.CleanupDevice();
return ( int )msg.wParam;
Has your OFFSET type got a fourth float member? Remember that your cbuffer size must be a multiple of 16, UpdateSubresource must update the entire cbuffer in D3D11, so when you're calling UpdateSubresource you're reading from a 12-byte source into a 16-byte destination, you overflow the bounds of the source data and - BOOM!

Simple solution - pad OFFSET to 4 floats (you can leave it as float3 in your shader).

Alternatively, and if you really don't want to do that, use a dynamic cbuffer and Map it with discard instead.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Well heres my struct which takes the floats:


struct OFFSET{float X, Y, Z, A;};


I added the A on the end to make it a multiply of 4, but I still get the same problem

edit:

and struct VERTEX taken by UINT stride has always been 4


struct VERTEX{FLOAT X, Y, Z; D3DXCOLOR Color;};
OK, that's fine then.

Your main loop looks very suspect - you're calling Render before you call InitGraphics, meaning that your objects haven't yet been created when you call Render. It's also a baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad idea to create and destroy objects like that every frame. Object creation is expensive so do it once only during startup.

Something like this would be better:


// Main message loop
MSG msg = {0};
obj.InitGraphics(gfx.getDevice(), gfx.getImmediateContext());
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
gfx.clearBackBuffer();
obj.Render(gfx.getImmediateContext());
gfx.present();
}
}
obj.CleanupObject();
gfx.CleanupDevice();
return ( int )msg.wParam;

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Ah you are the man! this has fixed all my problems :) thank you

This topic is closed to new replies.

Advertisement