I failed a bit with the Y axis there, my bad. Thanks for pointing that out! :) But as you say it still shouldn't matter with culling turned off, and I tried to change the vertex data to the correct coordinates now but with no effect.
I'm pretty sure the render target and the shaders are being set properly. I do have the D3D11_CREATE_DEVICE_DEBUG flag set, but there are no D3D warnings or errors in the debug output. Here's the full initializaiton procedure of the device and render target:
bool D3D11RenderSystem::Initialize()
{
Log::LoggingContext loggingContext( "D3D11RenderSystem::Initialize()" );
IDXGIFactory* pFactory;
HRESULT hr = CreateDXGIFactory( __uuidof( IDXGIFactory ), reinterpret_cast< void** >( &pFactory ) );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create DXGI factory!" );
return false;
}
IDXGIAdapter* pAdapter;
hr = pFactory->EnumAdapters( 0, &pAdapter );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not get DXGI adapter!" );
return false;
}
IDXGIOutput* pAdapterOutput;
hr = pAdapter->EnumOutputs( 0, &pAdapterOutput );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not get DXGI adapter output!" );
return false;
}
unsigned int numDisplayModes;
hr = pAdapterOutput->GetDisplayModeList( DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numDisplayModes, nullptr );
if ( FAILED( hr ) || numDisplayModes == 0 )
{
Log::Write( "ERROR: Could not get number of adapter display modes!" );
return false;
}
auto displayModeList = new DXGI_MODE_DESC[ numDisplayModes ];
hr = pAdapterOutput->GetDisplayModeList( DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numDisplayModes, displayModeList );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not get list of adapter display modes!" );
return false;
}
RECT cr;
GetClientRect( m_pWindow, &cr );
unsigned int width = cr.right - cr.left;
unsigned int height = cr.bottom - cr.top;
unsigned int numerator = 0;
unsigned int denominator = 1;
for ( unsigned int i = 0; i < numDisplayModes; ++i )
if ( displayModeList[ i ].Width == width && displayModeList[ i ].Height == height )
{
numerator = displayModeList[ i ].RefreshRate.Numerator;
denominator = displayModeList[ i ].RefreshRate.Denominator;
}
DXGI_ADAPTER_DESC adapterDesc;
hr = pAdapter->GetDesc( &adapterDesc );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not get adapter description!" );
return false;
}
std::wstring videoCardDescription( adapterDesc.Description );
m_videoCardDescription = std::string( videoCardDescription.begin(), videoCardDescription.end() );
m_videoCardMemory = adapterDesc.DedicatedVideoMemory / 1024 / 1024;
std::stringstream ss;
ss << "Detected video card: " << m_videoCardDescription;
Log::Write( ss.str() );
ss.str( "" );
ss << "Video memory: " << m_videoCardMemory << " MB";
Log::Write( ss.str() );
delete[] displayModeList;
ComRelease( pAdapterOutput );
ComRelease( pAdapter );
ComRelease( pFactory );
unsigned int debugFlags = 0;
bool tripleBuffering = true;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferCount = tripleBuffering ? 2 : 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.RefreshRate.Denominator = m_vsync ? denominator : 1;
swapChainDesc.BufferDesc.RefreshRate.Numerator = m_vsync ? numerator : 0;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = m_pWindow;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Windowed = !m_fullscreen;
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0
};
const unsigned int numFeatureLevels = ARRAYSIZE( featureLevels );
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
const unsigned int numDriverTypes = ARRAYSIZE( driverTypes );
unsigned int creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
for ( unsigned int driverType = 0; driverType < numDriverTypes; ++driverType )
{
hr = D3D11CreateDeviceAndSwapChain(
nullptr,
driverTypes[ driverType ],
nullptr,
creationFlags,
featureLevels,
numFeatureLevels,
D3D11_SDK_VERSION,
&swapChainDesc,
&m_pSwapChain,
&m_pDevice,
&m_featureLevel,
&m_pDeviceContext
);
if ( SUCCEEDED( hr ) )
{
m_driverType = driverTypes[ driverType ];
break;
}
}
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create device and swap chain!" );
return false;
}
ID3D11Texture2D* pBackBuffer;
hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pBackBuffer ) );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not get back buffer texture!" );
return false;
}
hr = m_pDevice->CreateRenderTargetView( pBackBuffer, nullptr, &m_pRenderTargetView );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create render target view!" );
return false;
}
ComRelease( pBackBuffer );
D3D11_TEXTURE2D_DESC depthBufferDesc;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.Height = height;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.MiscFlags = 0;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.Width = width;
hr = m_pDevice->CreateTexture2D( &depthBufferDesc, nullptr, &m_pDepthStencilBuffer );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create depth stencil buffer!" );
return false;
}
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
hr = m_pDevice->CreateDepthStencilState( &depthStencilDesc, &m_pDepthStencilState );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create depth stencil state!" );
return false;
}
m_pDeviceContext->OMSetDepthStencilState( m_pDepthStencilState, 1 );
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
ZeroMemory( &depthStencilViewDesc, sizeof( depthStencilViewDesc ) );
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.Texture2D.MipSlice = 0;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
hr = m_pDevice->CreateDepthStencilView( m_pDepthStencilBuffer, &depthStencilViewDesc, &m_pDepthStencilView );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create depth stencil view!" );
return false;
}
m_pDeviceContext->OMSetRenderTargets( 1, &m_pRenderTargetView, m_pDepthStencilView );
D3D11_RASTERIZER_DESC rasterizerDesc;
rasterizerDesc.AntialiasedLineEnable = false;
rasterizerDesc.CullMode = D3D11_CULL_NONE;
rasterizerDesc.DepthBias = 0;
rasterizerDesc.DepthBiasClamp = 0.0f;
rasterizerDesc.DepthClipEnable = true;
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.FrontCounterClockwise = false;
rasterizerDesc.MultisampleEnable = false;
rasterizerDesc.ScissorEnable = false;
rasterizerDesc.SlopeScaledDepthBias = 0.0f;
hr = m_pDevice->CreateRasterizerState( &rasterizerDesc, &m_pRasterizerState );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create rasterizer state!" );
return false;
}
m_pDeviceContext->RSSetState( m_pRasterizerState );
D3D11_VIEWPORT viewport;
viewport.Height = static_cast< float >( height );
viewport.MaxDepth = 1.0f;
viewport.MinDepth = 0.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast< float >( width );
m_pDeviceContext->RSSetViewports( 1, &viewport );
IDXGIDevice* pDevice = nullptr;
m_pDevice->QueryInterface( __uuidof( IDXGIDevice ), reinterpret_cast<void** >( &pDevice ) );
pDevice->GetParent( __uuidof( IDXGIAdapter ), reinterpret_cast< void** >( &pAdapter ) );
pAdapter->GetParent( __uuidof( IDXGIFactory ), reinterpret_cast< void** >( &pFactory ) );
pFactory->MakeWindowAssociation( m_pWindow, DXGI_MWA_NO_ALT_ENTER );
ComRelease( pDevice );
ComRelease( pAdapter );
ComRelease( pFactory );
return true;
}
And here's the shader creation:
bool StartupScene::Load( Untopia::ICore* pCore )
{
Log::LoggingContext loggingContext( "StartupScene::Load()" );
auto pRenderSystem = reinterpret_cast< D3D11RenderSystem* >( pCore->GetSubsystem( "render" ) );
auto pDevice = pRenderSystem->GetDevice();
SimpleVertex vertices[]=
{
{ XMFLOAT3( -1.0f, 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, 0.0f ) },
{ XMFLOAT3( -1.0f, -1.0f, 0.0f ) },
};
m_vertexCount = ARRAYSIZE( vertices );
D3D11_BUFFER_DESC vertexBufferDesc;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.ByteWidth = sizeof( Vertex ) * m_vertexCount;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
D3D11_SUBRESOURCE_DATA vertexData;
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;
HRESULT hr = pDevice->CreateBuffer( &vertexBufferDesc, &vertexData, &m_pVertexBuffer );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create vertex buffer!" );
return false;
}
char* vsBytes = nullptr;
unsigned int numVsBytes = 0;
std::ifstream vsFile( "SimpleVS.cso", std::ios::in | std::ios::binary | std::ios::ate );
if ( vsFile.is_open() )
{
numVsBytes = static_cast<unsigned int>( vsFile.tellg() );
vsBytes = new char[ numVsBytes ];
vsFile.seekg( 0, std::ios::beg );
vsFile.read( vsBytes, numVsBytes );
vsFile.close();
}
hr = pDevice->CreateVertexShader( vsBytes, numVsBytes, nullptr, &m_pVertexShader );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create vertex shader!" );
return false;
}
D3D11_INPUT_ELEMENT_DESC inputLayouts[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, };
hr = pDevice->CreateInputLayout( inputLayouts, ARRAYSIZE( inputLayouts ), vsBytes, numVsBytes, &m_pInputLayout );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create input layout!" );
return false;
}
delete[] vsBytes;
char* psBytes = nullptr;
unsigned int numPsBytes = 0;
std::ifstream psFile( "SimplePS.cso", std::ios::in | std::ios::binary | std::ios::ate );
if ( psFile.is_open() )
{
numPsBytes = static_cast<unsigned int>( psFile.tellg() );
psBytes = new char[ numPsBytes ];
psFile.seekg( 0, std::ios::beg );
psFile.read( psBytes, numPsBytes );
psFile.close();
}
hr = pDevice->CreatePixelShader( psBytes, numPsBytes, nullptr, &m_pPixelShader );
if ( FAILED( hr ) )
{
Log::Write( "ERROR: Could not create pixel shader!" );
return false;
}
delete[] psBytes;
return true;
}
And finally, the rendering function:
void StartupScene::Render( IRenderSystem* pRenderSystem )
{
auto pDeviceContext = reinterpret_cast< D3D11RenderSystem* >( pRenderSystem )->GetDeviceContext();
unsigned int stride = 0;
unsigned int offset = 0;
pDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );
pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
pDeviceContext->VSSetConstantBuffers( 0, 1, &m_pMatrixBuffer );
pDeviceContext->IASetInputLayout( m_pInputLayout );
pDeviceContext->VSSetShader( m_pVertexShader, nullptr, 0 );
pDeviceContext->PSSetShader( m_pPixelShader, nullptr, 0 );
pDeviceContext->Draw( m_vertexCount, 0 );
}