in DDSView/ddsview.cpp [331:699]
HRESULT InitDevice( const TexMetadata& mdata )
{
HRESULT hr = S_OK;
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#if defined( DEBUG ) || defined( _DEBUG )
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
constexpr UINT numDriverTypes = static_cast<UINT>(std::size(driverTypes));
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
constexpr UINT numFeatureLevels = static_cast<UINT>(std::size(featureLevels));
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
if( SUCCEEDED( hr ) )
break;
}
if( FAILED( hr ) )
return hr;
// Create a render target view
ID3D11Texture2D* pBackBuffer = nullptr;
hr = g_pSwapChain->GetBuffer( 0, IID_PPV_ARGS(&pBackBuffer) );
if( FAILED( hr ) )
return hr;
D3D11_RENDER_TARGET_VIEW_DESC vd = {};
vd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
vd.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, &vd, &g_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return hr;
// Create depth stencil texture
D3D11_TEXTURE2D_DESC descDepth = {};
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = g_pd3dDevice->CreateTexture2D( &descDepth, nullptr, &g_pDepthStencil );
if( FAILED( hr ) )
return hr;
// Create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV = {};
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
if( FAILED( hr ) )
return hr;
g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView );
// Setup the viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports( 1, &vp );
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader( g_VS, sizeof(g_VS), nullptr, &g_pVertexShader );
if( FAILED( hr ) )
return hr;
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, sizeof(XMFLOAT4), D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
constexpr UINT numElements = static_cast<UINT>(std::size(layout));
// Create the input layout
hr = g_pd3dDevice->CreateInputLayout( layout, numElements, g_VS, sizeof(g_VS), &g_pVertexLayout );
if( FAILED( hr ) )
return hr;
// Set the input layout
g_pImmediateContext->IASetInputLayout( g_pVertexLayout );
// Select the pixel shader
bool isCubeMap = false;
bool is1D = false;
const BYTE* pshader = nullptr;
size_t pshader_size = 0;
switch ( mdata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
if ( mdata.arraySize > 1)
{
pshader = g_PS_1DArray;
pshader_size = sizeof(g_PS_1DArray);
}
else
{
pshader = g_PS_1D;
pshader_size = sizeof(g_PS_1D);
}
is1D = true;
break;
case TEX_DIMENSION_TEXTURE2D:
if ( mdata.miscFlags & TEX_MISC_TEXTURECUBE )
{
pshader = g_PS_Cube;
pshader_size = sizeof(g_PS_Cube);
isCubeMap = true;
}
else if ( mdata.arraySize > 1 )
{
pshader = g_PS_2DArray;
pshader_size = sizeof(g_PS_2DArray);
}
else
{
pshader = g_PS_2D;
pshader_size = sizeof(g_PS_2D);
}
break;
case TEX_DIMENSION_TEXTURE3D:
pshader = g_PS_3D;
pshader_size = sizeof(g_PS_3D);
break;
default:
return E_FAIL;
}
assert( pshader && pshader_size > 0 );
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader( pshader, pshader_size, nullptr, &g_pPixelShader );
if( FAILED( hr ) )
return hr;
// Create vertex buffer
UINT nverts;
D3D11_SUBRESOURCE_DATA InitData = {};
static const SimpleVertex verticesCube[] =
{
// Render cubemaps as horizontal cross
// XPOS
{ XMFLOAT4( .5f, .25f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, .25f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( .5f, -.25f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, -.25f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 0.f, 0.f ) },
// XNEG
{ XMFLOAT4( -.5f, .25f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 1.f, 0.f ) },
{ XMFLOAT4( 0.f, .25f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 1.f, 0.f ) },
{ XMFLOAT4( -.5f, -.25f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 1.f, 0.f ) },
{ XMFLOAT4( 0.f, -.25f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 1.f, 0.f ) },
// YPOS
{ XMFLOAT4( -.5f, .75f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 2.f, 0.f ) },
{ XMFLOAT4( 0.f, .75f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 2.f, 0.f ) },
{ XMFLOAT4( -.5f, .25f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 2.f, 0.f ) },
{ XMFLOAT4( 0.f, .25f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 2.f, 0.f ) },
// YNEG
{ XMFLOAT4( -.5f, -.25f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 3.f, 0.f ) },
{ XMFLOAT4( 0.f, -.25f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 3.f, 0.f ) },
{ XMFLOAT4( -.5f, -.75f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 3.f, 0.f ) },
{ XMFLOAT4( 0.f, -.75f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 3.f, 0.f ) },
// ZPOS
{ XMFLOAT4( 0.f, .25f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 4.f, 0.f ) },
{ XMFLOAT4( .5f, .25f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 4.f, 0.f ) },
{ XMFLOAT4( 0.f, -.25f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 4.f, 0.f ) },
{ XMFLOAT4( .5f, -.25f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 4.f, 0.f ) },
// ZNEG
{ XMFLOAT4( -1.f, .25f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 5.f, 0.f ) },
{ XMFLOAT4( -.5f, .25f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 5.f, 0.f ) },
{ XMFLOAT4( -1.f, -.25f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 5.f, 0.f ) },
{ XMFLOAT4( -.5f, -.25f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 5.f, 0.f ) },
};
static const SimpleVertex vertices[] =
{
{ XMFLOAT4( -1.f, 1.f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, 1.f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( -1.f, -1.f, 0.f, 1.f ), XMFLOAT4( 0.f, 1.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, -1.f, 0.f, 1.f ), XMFLOAT4( 1.f, 1.f, 0.f, 0.f ) },
};
static const SimpleVertex vertices1D[] =
{
{ XMFLOAT4( -1.f, .05f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, .05f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( -1.f, -.05f, 0.f, 1.f ), XMFLOAT4( 0.f, 0.f, 0.f, 0.f ) },
{ XMFLOAT4( 1.f, -.05f, 0.f, 1.f ), XMFLOAT4( 1.f, 0.f, 0.f, 0.f ) },
};
if ( isCubeMap )
{
nverts = static_cast<UINT>(std::size(verticesCube));
InitData.pSysMem = verticesCube;
}
else if ( is1D )
{
nverts = static_cast<UINT>(std::size(vertices1D));
InitData.pSysMem = vertices1D;
}
else
{
nverts = static_cast<UINT>(std::size(vertices));
InitData.pSysMem = vertices;
}
D3D11_BUFFER_DESC bd = {};
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * nverts;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED( hr ) )
return hr;
// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
// Create index buffer
static const WORD indicesCube[] =
{
0, 1, 2,
2, 1, 3,
4, 5, 6,
6, 5, 7,
8, 9, 10,
10, 9, 11,
12, 13, 14,
14, 13, 15,
16, 17, 18,
18, 17, 19,
20, 21, 22,
22, 21, 23
};
static const WORD indices[] =
{
0, 1, 2,
2, 1, 3
};
if ( isCubeMap )
{
g_iIndices = static_cast<UINT>(std::size(indicesCube));
InitData.pSysMem = indicesCube;
}
else
{
g_iIndices = static_cast<UINT>(std::size(indices));
InitData.pSysMem = indices;
}
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = g_iIndices * sizeof(WORD);
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer );
if( FAILED( hr ) )
return hr;
// Set index buffer
g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );
// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
// Create the constant buffers
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(CBArrayControl);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pCBArrayControl );
if( FAILED( hr ) )
return hr;
// Create the state objects
D3D11_SAMPLER_DESC sampDesc = {};
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );
if( FAILED( hr ) )
return hr;
D3D11_BLEND_DESC dsc =
{
false,
false,
{
{
true,
D3D11_BLEND_SRC_ALPHA,
D3D11_BLEND_INV_SRC_ALPHA,
D3D11_BLEND_OP_ADD,
D3D11_BLEND_ZERO,
D3D11_BLEND_ZERO,
D3D11_BLEND_OP_ADD,
D3D11_COLOR_WRITE_ENABLE_ALL
},
// ...
}
};
hr = g_pd3dDevice->CreateBlendState(&dsc, &g_AlphaBlendState );
if( FAILED(hr) )
return hr;
return S_OK;
}