2015-01-24 22:19:42 -08:00
/*
* Copyright 2011 - 2015 Branimir Karadzic . All rights reserved .
* License : http : //www.opensource.org/licenses/BSD-2-Clause
*/
# include "bgfx_p.h"
2015-02-08 11:02:39 -08:00
# if BGFX_CONFIG_RENDERER_DIRECT3D12
2015-07-29 19:38:17 -07:00
# include "renderer_d3d12.h"
# if !USE_D3D12_DYNAMIC_LIB
# pragma comment(lib, "D3D12.lib")
# endif // !USE_D3D12_DYNAMIC_LIB
namespace bgfx { namespace d3d12
{
static wchar_t s_viewNameW [ BGFX_CONFIG_MAX_VIEWS ] [ 256 ] ;
struct PrimInfo
{
D3D_PRIMITIVE_TOPOLOGY m_toplogy ;
D3D12_PRIMITIVE_TOPOLOGY_TYPE m_topologyType ;
uint32_t m_min ;
uint32_t m_div ;
uint32_t m_sub ;
} ;
2015-07-29 19:50:25 -07:00
2015-07-29 19:38:17 -07:00
static const PrimInfo s_primInfo [ ] =
{
{ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST , D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE , 3 , 3 , 0 } ,
{ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP , D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE , 3 , 1 , 2 } ,
{ D3D_PRIMITIVE_TOPOLOGY_LINELIST , D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE , 2 , 2 , 0 } ,
{ D3D_PRIMITIVE_TOPOLOGY_POINTLIST , D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT , 1 , 1 , 0 } ,
{ D3D_PRIMITIVE_TOPOLOGY_UNDEFINED , D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED , 0 , 0 , 0 } ,
} ;
static const char * s_primName [ ] =
{
" TriList " ,
" TriStrip " ,
" Line " ,
" Point " ,
} ;
BX_STATIC_ASSERT ( BX_COUNTOF ( s_primInfo ) = = BX_COUNTOF ( s_primName ) + 1 ) ;
static const uint32_t s_checkMsaa [ ] =
{
0 ,
2 ,
4 ,
8 ,
16 ,
} ;
static DXGI_SAMPLE_DESC s_msaa [ ] =
{
{ 1 , 0 } ,
{ 2 , 0 } ,
{ 4 , 0 } ,
{ 8 , 0 } ,
{ 16 , 0 } ,
} ;
static const D3D12_BLEND s_blendFactor [ ] [ 2 ] =
{
{ ( D3D12_BLEND ) 0 , ( D3D12_BLEND ) 0 } , // ignored
{ D3D12_BLEND_ZERO , D3D12_BLEND_ZERO } , // ZERO
{ D3D12_BLEND_ONE , D3D12_BLEND_ONE } , // ONE
{ D3D12_BLEND_SRC_COLOR , D3D12_BLEND_SRC_ALPHA } , // SRC_COLOR
{ D3D12_BLEND_INV_SRC_COLOR , D3D12_BLEND_INV_SRC_ALPHA } , // INV_SRC_COLOR
{ D3D12_BLEND_SRC_ALPHA , D3D12_BLEND_SRC_ALPHA } , // SRC_ALPHA
{ D3D12_BLEND_INV_SRC_ALPHA , D3D12_BLEND_INV_SRC_ALPHA } , // INV_SRC_ALPHA
{ D3D12_BLEND_DEST_ALPHA , D3D12_BLEND_DEST_ALPHA } , // DST_ALPHA
{ D3D12_BLEND_INV_DEST_ALPHA , D3D12_BLEND_INV_DEST_ALPHA } , // INV_DST_ALPHA
{ D3D12_BLEND_DEST_COLOR , D3D12_BLEND_DEST_ALPHA } , // DST_COLOR
{ D3D12_BLEND_INV_DEST_COLOR , D3D12_BLEND_INV_DEST_ALPHA } , // INV_DST_COLOR
{ D3D12_BLEND_SRC_ALPHA_SAT , D3D12_BLEND_ONE } , // SRC_ALPHA_SAT
{ D3D12_BLEND_BLEND_FACTOR , D3D12_BLEND_BLEND_FACTOR } , // FACTOR
{ D3D12_BLEND_INV_BLEND_FACTOR , D3D12_BLEND_INV_BLEND_FACTOR } , // INV_FACTOR
} ;
static const D3D12_BLEND_OP s_blendEquation [ ] =
{
D3D12_BLEND_OP_ADD ,
D3D12_BLEND_OP_SUBTRACT ,
D3D12_BLEND_OP_REV_SUBTRACT ,
D3D12_BLEND_OP_MIN ,
D3D12_BLEND_OP_MAX ,
} ;
static const D3D12_COMPARISON_FUNC s_cmpFunc [ ] =
{
D3D12_COMPARISON_FUNC ( 0 ) , // ignored
D3D12_COMPARISON_FUNC_LESS ,
D3D12_COMPARISON_FUNC_LESS_EQUAL ,
D3D12_COMPARISON_FUNC_EQUAL ,
D3D12_COMPARISON_FUNC_GREATER_EQUAL ,
D3D12_COMPARISON_FUNC_GREATER ,
D3D12_COMPARISON_FUNC_NOT_EQUAL ,
D3D12_COMPARISON_FUNC_NEVER ,
D3D12_COMPARISON_FUNC_ALWAYS ,
} ;
static const D3D12_STENCIL_OP s_stencilOp [ ] =
{
D3D12_STENCIL_OP_ZERO ,
D3D12_STENCIL_OP_KEEP ,
D3D12_STENCIL_OP_REPLACE ,
D3D12_STENCIL_OP_INCR ,
D3D12_STENCIL_OP_INCR_SAT ,
D3D12_STENCIL_OP_DECR ,
D3D12_STENCIL_OP_DECR_SAT ,
D3D12_STENCIL_OP_INVERT ,
} ;
static const D3D12_CULL_MODE s_cullMode [ ] =
{
D3D12_CULL_MODE_NONE ,
D3D12_CULL_MODE_FRONT ,
D3D12_CULL_MODE_BACK ,
} ;
static const D3D12_TEXTURE_ADDRESS_MODE s_textureAddress [ ] =
{
D3D12_TEXTURE_ADDRESS_MODE_WRAP ,
D3D12_TEXTURE_ADDRESS_MODE_MIRROR ,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP ,
} ;
/*
* D3D11_FILTER_MIN_MAG_MIP_POINT = 0x00 ,
* D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x01 ,
* D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x04 ,
* D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x05 ,
* D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10 ,
* D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11 ,
* D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14 ,
* D3D11_FILTER_MIN_MAG_MIP_LINEAR = 0x15 ,
* D3D11_FILTER_ANISOTROPIC = 0x55 ,
*
* D3D11_COMPARISON_FILTERING_BIT = 0x80 ,
* D3D11_ANISOTROPIC_FILTERING_BIT = 0x40 ,
*
* According to D3D11_FILTER enum bits for mip , mag and mip are :
* 0x10 // MIN_LINEAR
* 0x04 // MAG_LINEAR
* 0x01 // MIP_LINEAR
*/
static const uint8_t s_textureFilter [ 3 ] [ 3 ] =
{
{
0x10 , // min linear
0x00 , // min point
0x55 , // anisotropic
} ,
{
0x04 , // mag linear
0x00 , // mag point
0x55 , // anisotropic
} ,
{
0x01 , // mip linear
0x00 , // mip point
0x55 , // anisotropic
} ,
} ;
struct TextureFormatInfo
{
DXGI_FORMAT m_fmt ;
DXGI_FORMAT m_fmtSrv ;
DXGI_FORMAT m_fmtDsv ;
} ;
static const TextureFormatInfo s_textureFormat [ ] =
{
{ DXGI_FORMAT_BC1_UNORM , DXGI_FORMAT_BC1_UNORM , DXGI_FORMAT_UNKNOWN } , // BC1
{ DXGI_FORMAT_BC2_UNORM , DXGI_FORMAT_BC2_UNORM , DXGI_FORMAT_UNKNOWN } , // BC2
{ DXGI_FORMAT_BC3_UNORM , DXGI_FORMAT_BC3_UNORM , DXGI_FORMAT_UNKNOWN } , // BC3
{ DXGI_FORMAT_BC4_UNORM , DXGI_FORMAT_BC4_UNORM , DXGI_FORMAT_UNKNOWN } , // BC4
{ DXGI_FORMAT_BC5_UNORM , DXGI_FORMAT_BC5_UNORM , DXGI_FORMAT_UNKNOWN } , // BC5
{ DXGI_FORMAT_BC6H_SF16 , DXGI_FORMAT_BC6H_SF16 , DXGI_FORMAT_UNKNOWN } , // BC6H
{ DXGI_FORMAT_BC7_UNORM , DXGI_FORMAT_BC7_UNORM , DXGI_FORMAT_UNKNOWN } , // BC7
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // ETC1
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // ETC2
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // ETC2A
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // ETC2A1
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC12
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC14
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC12A
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC14A
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC22
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // PTC24
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // Unknown
{ DXGI_FORMAT_R1_UNORM , DXGI_FORMAT_R1_UNORM , DXGI_FORMAT_UNKNOWN } , // R1
{ DXGI_FORMAT_R8_UNORM , DXGI_FORMAT_R8_UNORM , DXGI_FORMAT_UNKNOWN } , // R8
{ DXGI_FORMAT_R16_UNORM , DXGI_FORMAT_R16_UNORM , DXGI_FORMAT_UNKNOWN } , // R16
{ DXGI_FORMAT_R16_FLOAT , DXGI_FORMAT_R16_FLOAT , DXGI_FORMAT_UNKNOWN } , // R16F
{ DXGI_FORMAT_R32_UINT , DXGI_FORMAT_R32_UINT , DXGI_FORMAT_UNKNOWN } , // R32
{ DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_UNKNOWN } , // R32F
{ DXGI_FORMAT_R8G8_UNORM , DXGI_FORMAT_R8G8_UNORM , DXGI_FORMAT_UNKNOWN } , // RG8
{ DXGI_FORMAT_R16G16_UNORM , DXGI_FORMAT_R16G16_UNORM , DXGI_FORMAT_UNKNOWN } , // RG16
{ DXGI_FORMAT_R16G16_FLOAT , DXGI_FORMAT_R16G16_FLOAT , DXGI_FORMAT_UNKNOWN } , // RG16F
{ DXGI_FORMAT_R32G32_UINT , DXGI_FORMAT_R32G32_UINT , DXGI_FORMAT_UNKNOWN } , // RG32
{ DXGI_FORMAT_R32G32_FLOAT , DXGI_FORMAT_R32G32_FLOAT , DXGI_FORMAT_UNKNOWN } , // RG32F
{ DXGI_FORMAT_B8G8R8A8_UNORM , DXGI_FORMAT_B8G8R8A8_UNORM , DXGI_FORMAT_UNKNOWN } , // BGRA8
{ DXGI_FORMAT_R8G8B8A8_UNORM , DXGI_FORMAT_R8G8B8A8_UNORM , DXGI_FORMAT_UNKNOWN } , // RGBA8
{ DXGI_FORMAT_R16G16B16A16_UNORM , DXGI_FORMAT_R16G16B16A16_UNORM , DXGI_FORMAT_UNKNOWN } , // RGBA16
{ DXGI_FORMAT_R16G16B16A16_FLOAT , DXGI_FORMAT_R16G16B16A16_FLOAT , DXGI_FORMAT_UNKNOWN } , // RGBA16F
{ DXGI_FORMAT_R32G32B32A32_UINT , DXGI_FORMAT_R32G32B32A32_UINT , DXGI_FORMAT_UNKNOWN } , // RGBA32
{ DXGI_FORMAT_R32G32B32A32_FLOAT , DXGI_FORMAT_R32G32B32A32_FLOAT , DXGI_FORMAT_UNKNOWN } , // RGBA32F
{ DXGI_FORMAT_B5G6R5_UNORM , DXGI_FORMAT_B5G6R5_UNORM , DXGI_FORMAT_UNKNOWN } , // R5G6B5
{ DXGI_FORMAT_B4G4R4A4_UNORM , DXGI_FORMAT_B4G4R4A4_UNORM , DXGI_FORMAT_UNKNOWN } , // RGBA4
{ DXGI_FORMAT_B5G5R5A1_UNORM , DXGI_FORMAT_B5G5R5A1_UNORM , DXGI_FORMAT_UNKNOWN } , // RGB5A1
{ DXGI_FORMAT_R10G10B10A2_UNORM , DXGI_FORMAT_R10G10B10A2_UNORM , DXGI_FORMAT_UNKNOWN } , // RGB10A2
{ DXGI_FORMAT_R11G11B10_FLOAT , DXGI_FORMAT_R11G11B10_FLOAT , DXGI_FORMAT_UNKNOWN } , // R11G11B10F
{ DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , // UnknownDepth
{ DXGI_FORMAT_R16_TYPELESS , DXGI_FORMAT_R16_UNORM , DXGI_FORMAT_D16_UNORM } , // D16
{ DXGI_FORMAT_R24G8_TYPELESS , DXGI_FORMAT_R24_UNORM_X8_TYPELESS , DXGI_FORMAT_D24_UNORM_S8_UINT } , // D24
{ DXGI_FORMAT_R24G8_TYPELESS , DXGI_FORMAT_R24_UNORM_X8_TYPELESS , DXGI_FORMAT_D24_UNORM_S8_UINT } , // D24S8
{ DXGI_FORMAT_R24G8_TYPELESS , DXGI_FORMAT_R24_UNORM_X8_TYPELESS , DXGI_FORMAT_D24_UNORM_S8_UINT } , // D32
{ DXGI_FORMAT_R32_TYPELESS , DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_D32_FLOAT } , // D16F
{ DXGI_FORMAT_R32_TYPELESS , DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_D32_FLOAT } , // D24F
{ DXGI_FORMAT_R32_TYPELESS , DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_D32_FLOAT } , // D32F
{ DXGI_FORMAT_R24G8_TYPELESS , DXGI_FORMAT_R24_UNORM_X8_TYPELESS , DXGI_FORMAT_D24_UNORM_S8_UINT } , // D0S8
} ;
BX_STATIC_ASSERT ( TextureFormat : : Count = = BX_COUNTOF ( s_textureFormat ) ) ;
static const D3D12_INPUT_ELEMENT_DESC s_attrib [ ] =
{
{ " POSITION " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " NORMAL " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TANGENT " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " BITANGENT " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " COLOR " , 0 , DXGI_FORMAT_R8G8B8A8_UINT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " COLOR " , 1 , DXGI_FORMAT_R8G8B8A8_UINT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " BLENDINDICES " , 0 , DXGI_FORMAT_R8G8B8A8_UINT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " BLENDWEIGHT " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 0 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 1 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 2 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 3 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 4 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 5 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 6 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
{ " TEXCOORD " , 7 , DXGI_FORMAT_R32G32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0 } ,
} ;
BX_STATIC_ASSERT ( Attrib : : Count = = BX_COUNTOF ( s_attrib ) ) ;
static const DXGI_FORMAT s_attribType [ ] [ 4 ] [ 2 ] =
{
{
{ DXGI_FORMAT_R8_UINT , DXGI_FORMAT_R8_UNORM } ,
{ DXGI_FORMAT_R8G8_UINT , DXGI_FORMAT_R8G8_UNORM } ,
{ DXGI_FORMAT_R8G8B8A8_UINT , DXGI_FORMAT_R8G8B8A8_UNORM } ,
{ DXGI_FORMAT_R8G8B8A8_UINT , DXGI_FORMAT_R8G8B8A8_UNORM } ,
} ,
{
{ DXGI_FORMAT_R16_SINT , DXGI_FORMAT_R16_SNORM } ,
{ DXGI_FORMAT_R16G16_SINT , DXGI_FORMAT_R16G16_SNORM } ,
{ DXGI_FORMAT_R16G16B16A16_SINT , DXGI_FORMAT_R16G16B16A16_SNORM } ,
{ DXGI_FORMAT_R16G16B16A16_SINT , DXGI_FORMAT_R16G16B16A16_SNORM } ,
} ,
{
{ DXGI_FORMAT_R16_FLOAT , DXGI_FORMAT_R16_FLOAT } ,
{ DXGI_FORMAT_R16G16_FLOAT , DXGI_FORMAT_R16G16_FLOAT } ,
{ DXGI_FORMAT_R16G16B16A16_FLOAT , DXGI_FORMAT_R16G16B16A16_FLOAT } ,
{ DXGI_FORMAT_R16G16B16A16_FLOAT , DXGI_FORMAT_R16G16B16A16_FLOAT } ,
} ,
{
{ DXGI_FORMAT_R32_FLOAT , DXGI_FORMAT_R32_FLOAT } ,
{ DXGI_FORMAT_R32G32_FLOAT , DXGI_FORMAT_R32G32_FLOAT } ,
{ DXGI_FORMAT_R32G32B32_FLOAT , DXGI_FORMAT_R32G32B32_FLOAT } ,
{ DXGI_FORMAT_R32G32B32A32_FLOAT , DXGI_FORMAT_R32G32B32A32_FLOAT } ,
} ,
} ;
BX_STATIC_ASSERT ( AttribType : : Count = = BX_COUNTOF ( s_attribType ) ) ;
static D3D12_INPUT_ELEMENT_DESC * fillVertexDecl ( D3D12_INPUT_ELEMENT_DESC * _out , const VertexDecl & _decl )
{
D3D12_INPUT_ELEMENT_DESC * elem = _out ;
for ( uint32_t attr = 0 ; attr < Attrib : : Count ; + + attr )
{
if ( 0xff ! = _decl . m_attributes [ attr ] )
{
memcpy ( elem , & s_attrib [ attr ] , sizeof ( D3D12_INPUT_ELEMENT_DESC ) ) ;
if ( 0 = = _decl . m_attributes [ attr ] )
{
elem - > AlignedByteOffset = 0 ;
}
else
{
uint8_t num ;
AttribType : : Enum type ;
bool normalized ;
bool asInt ;
_decl . decode ( Attrib : : Enum ( attr ) , num , type , normalized , asInt ) ;
elem - > Format = s_attribType [ type ] [ num - 1 ] [ normalized ] ;
elem - > AlignedByteOffset = _decl . m_offset [ attr ] ;
}
+ + elem ;
}
}
return elem ;
}
void setResourceBarrier ( ID3D12GraphicsCommandList * _commandList , ID3D12Resource * _resource , D3D12_RESOURCE_STATES _stateBefore , D3D12_RESOURCE_STATES _stateAfter )
{
D3D12_RESOURCE_BARRIER barrier ;
barrier . Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION ;
barrier . Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE ;
barrier . Transition . pResource = _resource ;
barrier . Transition . Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES ;
barrier . Transition . StateBefore = _stateBefore ;
barrier . Transition . StateAfter = _stateAfter ;
_commandList - > ResourceBarrier ( 1 , & barrier ) ;
}
struct HeapProperty
{
enum Enum
{
Default ,
Upload ,
Count
} ;
D3D12_HEAP_PROPERTIES m_properties ;
D3D12_RESOURCE_STATES m_state ;
} ;
static const HeapProperty s_heapProperties [ ] =
{
{ { D3D12_HEAP_TYPE_DEFAULT , D3D12_CPU_PAGE_PROPERTY_UNKNOWN , D3D12_MEMORY_POOL_UNKNOWN , 1 , 1 } , D3D12_RESOURCE_STATE_COMMON } ,
{ { D3D12_HEAP_TYPE_UPLOAD , D3D12_CPU_PAGE_PROPERTY_UNKNOWN , D3D12_MEMORY_POOL_UNKNOWN , 1 , 1 } , D3D12_RESOURCE_STATE_GENERIC_READ } ,
} ;
BX_STATIC_ASSERT ( BX_COUNTOF ( s_heapProperties ) = = HeapProperty : : Count ) ;
ID3D12Resource * createCommittedResource ( ID3D12Device * _device , HeapProperty : : Enum _heapProperty , D3D12_RESOURCE_DESC * _resourceDesc , D3D12_CLEAR_VALUE * _clearValue )
{
const HeapProperty & heapProperty = s_heapProperties [ _heapProperty ] ;
ID3D12Resource * resource ;
DX_CHECK ( _device - > CreateCommittedResource ( & heapProperty . m_properties
, D3D12_HEAP_FLAG_NONE
, _resourceDesc
, heapProperty . m_state
, _clearValue
, __uuidof ( ID3D12Resource )
, ( void * * ) & resource
) ) ;
return resource ;
}
ID3D12Resource * createCommittedResource ( ID3D12Device * _device , HeapProperty : : Enum _heapProperty , uint64_t _size , D3D12_RESOURCE_FLAGS _flags = D3D12_RESOURCE_FLAG_NONE )
{
D3D12_RESOURCE_DESC resourceDesc ;
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_BUFFER ;
resourceDesc . Alignment = 0 ;
resourceDesc . Width = _size ;
resourceDesc . Height = 1 ;
resourceDesc . DepthOrArraySize = 1 ;
resourceDesc . MipLevels = 1 ;
resourceDesc . Format = DXGI_FORMAT_UNKNOWN ;
resourceDesc . SampleDesc . Count = 1 ;
resourceDesc . SampleDesc . Quality = 0 ;
resourceDesc . Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR ;
resourceDesc . Flags = _flags ;
return createCommittedResource ( _device , _heapProperty , & resourceDesc , NULL ) ;
}
BX_NO_INLINE void setDebugObjectName ( ID3D12Object * _object , const char * _format , . . . )
{
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_OBJECT_NAME ) )
{
char temp [ 2048 ] ;
va_list argList ;
va_start ( argList , _format ) ;
int size = bx : : uint32_min ( sizeof ( temp ) - 1 , vsnprintf ( temp , sizeof ( temp ) , _format , argList ) ) ;
va_end ( argList ) ;
temp [ size ] = ' \0 ' ;
wchar_t * wtemp = ( wchar_t * ) alloca ( ( size + 1 ) * 2 ) ;
mbstowcs ( wtemp , temp , size + 1 ) ;
_object - > SetName ( wtemp ) ;
}
}
# if USE_D3D12_DYNAMIC_LIB
static PFN_D3D12_CREATE_DEVICE D3D12CreateDevice ;
static PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface ;
static PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignature ;
static PFN_CREATE_DXGI_FACTORY CreateDXGIFactory1 ;
# endif // USE_D3D12_DYNAMIC_LIB
struct RendererContextD3D12 : public RendererContextI
{
RendererContextD3D12 ( )
: m_wireframe ( false )
, m_flags ( BGFX_RESET_NONE )
, m_fsChanges ( 0 )
, m_vsChanges ( 0 )
, m_frame ( 0 )
, m_backBufferColorIdx ( 0 )
, m_rtMsaa ( false )
{
}
void init ( )
{
m_fbh . idx = invalidHandle ;
memset ( m_uniforms , 0 , sizeof ( m_uniforms ) ) ;
memset ( & m_resolution , 0 , sizeof ( m_resolution ) ) ;
# if USE_D3D12_DYNAMIC_LIB
m_d3d12dll = bx : : dlopen ( " d3d12.dll " ) ;
BGFX_FATAL ( NULL ! = m_d3d12dll , Fatal : : UnableToInitialize , " Failed to load d3d12.dll. " ) ;
D3D12CreateDevice = ( PFN_D3D12_CREATE_DEVICE ) bx : : dlsym ( m_d3d12dll , " D3D12CreateDevice " ) ;
BGFX_FATAL ( NULL ! = D3D12CreateDevice , Fatal : : UnableToInitialize , " Function D3D12CreateDevice not found. " ) ;
D3D12GetDebugInterface = ( PFN_D3D12_GET_DEBUG_INTERFACE ) bx : : dlsym ( m_d3d12dll , " D3D12GetDebugInterface " ) ;
BGFX_FATAL ( NULL ! = D3D12GetDebugInterface , Fatal : : UnableToInitialize , " Function D3D12GetDebugInterface not found. " ) ;
D3D12SerializeRootSignature = ( PFN_D3D12_SERIALIZE_ROOT_SIGNATURE ) bx : : dlsym ( m_d3d12dll , " D3D12SerializeRootSignature " ) ;
BGFX_FATAL ( NULL ! = D3D12SerializeRootSignature , Fatal : : UnableToInitialize , " Function D3D12SerializeRootSignature not found. " ) ;
m_dxgidll = bx : : dlopen ( " dxgi.dll " ) ;
BGFX_FATAL ( NULL ! = m_dxgidll , Fatal : : UnableToInitialize , " Failed to load dxgi.dll. " ) ;
CreateDXGIFactory1 = ( PFN_CREATE_DXGI_FACTORY ) bx : : dlsym ( m_dxgidll , " CreateDXGIFactory1 " ) ;
BGFX_FATAL ( NULL ! = CreateDXGIFactory1 , Fatal : : UnableToInitialize , " Function CreateDXGIFactory1 not found. " ) ;
# endif // USE_D3D12_DYNAMIC_LIB
HRESULT hr ;
hr = CreateDXGIFactory1 ( __uuidof ( IDXGIFactory ) , ( void * * ) & m_factory ) ;
BGFX_FATAL ( SUCCEEDED ( hr ) , Fatal : : UnableToInitialize , " Unable to create DXGI factory. " ) ;
m_adapter = NULL ;
m_driverType = D3D_DRIVER_TYPE_HARDWARE ;
IDXGIAdapter * adapter ;
for ( uint32_t ii = 0 ; DXGI_ERROR_NOT_FOUND ! = m_factory - > EnumAdapters ( ii , & adapter ) ; + + ii )
{
DXGI_ADAPTER_DESC desc ;
hr = adapter - > GetDesc ( & desc ) ;
if ( SUCCEEDED ( hr ) )
{
BX_TRACE ( " Adapter #%d " , ii ) ;
char description [ BX_COUNTOF ( desc . Description ) ] ;
wcstombs ( description , desc . Description , BX_COUNTOF ( desc . Description ) ) ;
BX_TRACE ( " \t Description: %s " , description ) ;
BX_TRACE ( " \t VendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x "
, desc . VendorId
, desc . DeviceId
, desc . SubSysId
, desc . Revision
) ;
BX_TRACE ( " \t Memory: % " PRIi64 " (video), % " PRIi64 " (system), % " PRIi64 " (shared) "
, desc . DedicatedVideoMemory
, desc . DedicatedSystemMemory
, desc . SharedSystemMemory
) ;
g_caps . gpu [ ii ] . vendorId = ( uint16_t ) desc . VendorId ;
g_caps . gpu [ ii ] . deviceId = ( uint16_t ) desc . DeviceId ;
+ + g_caps . numGPUs ;
if ( ( BGFX_PCI_ID_NONE ! = g_caps . vendorId | | 0 ! = g_caps . deviceId )
& & ( BGFX_PCI_ID_NONE = = g_caps . vendorId | | desc . VendorId = = g_caps . vendorId )
& & ( 0 = = g_caps . deviceId | | desc . DeviceId = = g_caps . deviceId ) )
{
m_adapter = adapter ;
m_adapter - > AddRef ( ) ;
m_driverType = D3D_DRIVER_TYPE_UNKNOWN ;
}
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PERFHUD )
& & 0 ! = strstr ( description , " PerfHUD " ) )
{
m_adapter = adapter ;
m_driverType = D3D_DRIVER_TYPE_REFERENCE ;
}
}
DX_RELEASE ( adapter , adapter = = m_adapter ? 1 : 0 ) ;
}
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG ) )
{
ID3D12Debug * debug ;
hr = D3D12GetDebugInterface ( __uuidof ( ID3D12Debug ) , ( void * * ) & debug ) ;
if ( SUCCEEDED ( hr ) )
{
debug - > EnableDebugLayer ( ) ;
}
}
hr = D3D12CreateDevice ( m_adapter
, D3D_FEATURE_LEVEL_11_0
, __uuidof ( ID3D12Device )
, ( void * * ) & m_device
) ;
BGFX_FATAL ( SUCCEEDED ( hr ) , Fatal : : UnableToInitialize , " Unable to create Direct3D12 device. " ) ;
if ( NULL ! = m_adapter )
{
DX_RELEASE ( m_adapter , 2 ) ;
}
memset ( & m_adapterDesc , 0 , sizeof ( m_adapterDesc ) ) ;
LUID luid = m_device - > GetAdapterLuid ( ) ;
for ( uint32_t ii = 0 ; DXGI_ERROR_NOT_FOUND ! = m_factory - > EnumAdapters ( ii , & adapter ) ; + + ii )
{
adapter - > GetDesc ( & m_adapterDesc ) ;
if ( m_adapterDesc . AdapterLuid . LowPart = = luid . LowPart
& & m_adapterDesc . AdapterLuid . HighPart = = luid . HighPart )
{
break ;
}
}
g_caps . vendorId = ( uint16_t ) m_adapterDesc . VendorId ;
g_caps . deviceId = ( uint16_t ) m_adapterDesc . DeviceId ;
m_architecture . NodeIndex = 0 ;
DX_CHECK ( m_device - > CheckFeatureSupport ( D3D12_FEATURE_ARCHITECTURE , & m_architecture , sizeof ( m_architecture ) ) ) ;
BX_TRACE ( " GPU Architecture, TileBasedRenderer %d, UMA %d, CacheCoherentUMA %d "
, m_architecture . TileBasedRenderer
, m_architecture . UMA
, m_architecture . CacheCoherentUMA
) ;
DX_CHECK ( m_device - > CheckFeatureSupport ( D3D12_FEATURE_D3D12_OPTIONS , & m_options , sizeof ( m_options ) ) ) ;
m_cmd . init ( m_device ) ;
m_scd . BufferDesc . Width = BGFX_DEFAULT_WIDTH ;
m_scd . BufferDesc . Height = BGFX_DEFAULT_HEIGHT ;
m_scd . BufferDesc . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
m_scd . BufferDesc . Scaling = DXGI_MODE_SCALING_STRETCHED ;
m_scd . BufferDesc . ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED ;
m_scd . BufferDesc . RefreshRate . Numerator = 60 ;
m_scd . BufferDesc . RefreshRate . Denominator = 1 ;
m_scd . SampleDesc . Count = 1 ;
m_scd . SampleDesc . Quality = 0 ;
m_scd . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
m_scd . BufferCount = bx : : uint32_min ( BX_COUNTOF ( m_backBufferColor ) , 4 ) ;
m_scd . OutputWindow = ( HWND ) g_platformData . nwh ;
m_scd . Windowed = true ;
m_scd . SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ;
m_scd . Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ;
BX_CHECK ( m_scd . BufferCount < = BX_COUNTOF ( m_backBufferColor ) , " Swap chain buffer count %d (max %d). "
, m_scd . BufferCount
, BX_COUNTOF ( m_backBufferColor )
) ;
hr = m_factory - > CreateSwapChain ( m_cmd . m_commandQueue
, & m_scd
, & m_swapChain
) ;
BGFX_FATAL ( SUCCEEDED ( hr ) , Fatal : : UnableToInitialize , " Failed to create swap chain. " ) ;
m_resolution . m_width = BGFX_DEFAULT_WIDTH ;
m_resolution . m_height = BGFX_DEFAULT_HEIGHT ;
DX_CHECK ( m_factory - > MakeWindowAssociation ( ( HWND ) g_platformData . nwh
, 0
| DXGI_MWA_NO_WINDOW_CHANGES
| DXGI_MWA_NO_ALT_ENTER
) ) ;
m_numWindows = 1 ;
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG ) )
{
hr = m_device - > QueryInterface ( __uuidof ( ID3D12InfoQueue ) , ( void * * ) & m_infoQueue ) ;
if ( SUCCEEDED ( hr ) )
{
m_infoQueue - > SetBreakOnSeverity ( D3D12_MESSAGE_SEVERITY_CORRUPTION , true ) ;
2015-07-29 21:02:41 -07:00
m_infoQueue - > SetBreakOnSeverity ( D3D12_MESSAGE_SEVERITY_ERROR , true ) ;
2015-07-29 19:38:17 -07:00
m_infoQueue - > SetBreakOnSeverity ( D3D12_MESSAGE_SEVERITY_WARNING , false ) ;
D3D12_INFO_QUEUE_FILTER filter ;
memset ( & filter , 0 , sizeof ( filter ) ) ;
D3D12_MESSAGE_CATEGORY catlist [ ] =
{
D3D12_MESSAGE_CATEGORY_STATE_SETTING ,
D3D12_MESSAGE_CATEGORY_EXECUTION ,
} ;
filter . DenyList . NumCategories = BX_COUNTOF ( catlist ) ;
filter . DenyList . pCategoryList = catlist ;
m_infoQueue - > PushStorageFilter ( & filter ) ;
DX_RELEASE ( m_infoQueue , 19 ) ;
}
}
D3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap ;
rtvDescHeap . NumDescriptors = 0
+ BX_COUNTOF ( m_backBufferColor )
+ BGFX_CONFIG_MAX_FRAME_BUFFERS * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS
;
rtvDescHeap . Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV ;
rtvDescHeap . Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE ;
rtvDescHeap . NodeMask = 0 ;
DX_CHECK ( m_device - > CreateDescriptorHeap ( & rtvDescHeap
, __uuidof ( ID3D12DescriptorHeap )
, ( void * * ) & m_rtvDescriptorHeap
) ) ;
D3D12_DESCRIPTOR_HEAP_DESC dsvDescHeap ;
dsvDescHeap . NumDescriptors = 0
+ 1 // reserved for depth backbuffer.
+ BGFX_CONFIG_MAX_FRAME_BUFFERS
;
dsvDescHeap . Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV ;
dsvDescHeap . Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE ;
dsvDescHeap . NodeMask = 0 ;
DX_CHECK ( m_device - > CreateDescriptorHeap ( & dsvDescHeap
, __uuidof ( ID3D12DescriptorHeap )
, ( void * * ) & m_dsvDescriptorHeap
) ) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_scratchBuffer ) ; + + ii )
{
m_scratchBuffer [ ii ] . create ( BGFX_CONFIG_MAX_DRAW_CALLS * 1024
, BGFX_CONFIG_MAX_TEXTURES + BGFX_CONFIG_MAX_SHADERS + BGFX_CONFIG_MAX_DRAW_CALLS
) ;
}
m_samplerAllocator . create ( D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
, 1024
, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS
) ;
D3D12_DESCRIPTOR_RANGE descRange [ ] =
{
{ D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER , BGFX_CONFIG_MAX_TEXTURE_SAMPLERS , 0 , 0 , D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND } ,
{ D3D12_DESCRIPTOR_RANGE_TYPE_SRV , BGFX_CONFIG_MAX_TEXTURE_SAMPLERS , 0 , 0 , D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND } ,
{ D3D12_DESCRIPTOR_RANGE_TYPE_CBV , 1 , 0 , 0 , D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND } ,
{ D3D12_DESCRIPTOR_RANGE_TYPE_UAV , BGFX_CONFIG_MAX_TEXTURE_SAMPLERS , 0 , 0 , D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND } ,
} ;
BX_STATIC_ASSERT ( BX_COUNTOF ( descRange ) = = Rdt : : Count ) ;
D3D12_ROOT_PARAMETER rootParameter [ ] =
{
{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE , { 1 , & descRange [ Rdt : : Sampler ] } , D3D12_SHADER_VISIBILITY_ALL } ,
{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE , { 1 , & descRange [ Rdt : : SRV ] } , D3D12_SHADER_VISIBILITY_ALL } ,
{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE , { 1 , & descRange [ Rdt : : CBV ] } , D3D12_SHADER_VISIBILITY_ALL } ,
// { D3D12_ROOT_PARAMETER_TYPE_CBV, { 0, 0 }, D3D12_SHADER_VISIBILITY_ALL },
{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE , { 1 , & descRange [ Rdt : : UAV ] } , D3D12_SHADER_VISIBILITY_ALL } ,
} ;
// rootParameter[Rdt::CBV].Constants.ShaderRegister = 0;
// rootParameter[Rdt::CBV].Constants.RegisterSpace = 100;
// rootParameter[Rdt::CBV].Constants.Num32BitValues = 0;
D3D12_ROOT_SIGNATURE_DESC descRootSignature ;
descRootSignature . NumParameters = BX_COUNTOF ( rootParameter ) ;
descRootSignature . pParameters = rootParameter ;
descRootSignature . NumStaticSamplers = 0 ;
descRootSignature . pStaticSamplers = NULL ;
descRootSignature . Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT ;
ID3DBlob * outBlob ;
ID3DBlob * errorBlob ;
DX_CHECK ( D3D12SerializeRootSignature ( & descRootSignature
, D3D_ROOT_SIGNATURE_VERSION_1
, & outBlob
, & errorBlob
) ) ;
DX_CHECK ( m_device - > CreateRootSignature ( 0
, outBlob - > GetBufferPointer ( )
, outBlob - > GetBufferSize ( )
, __uuidof ( ID3D12RootSignature )
, ( void * * ) & m_rootSignature
) ) ;
UniformHandle handle = BGFX_INVALID_HANDLE ;
for ( uint32_t ii = 0 ; ii < PredefinedUniform : : Count ; + + ii )
{
m_uniformReg . add ( handle , getPredefinedUniformName ( PredefinedUniform : : Enum ( ii ) ) , & m_predefinedUniforms [ ii ] ) ;
}
g_caps . supported | = ( 0
| BGFX_CAPS_TEXTURE_3D
| BGFX_CAPS_TEXTURE_COMPARE_ALL
| BGFX_CAPS_INSTANCING
| BGFX_CAPS_VERTEX_ATTRIB_HALF
| BGFX_CAPS_FRAGMENT_DEPTH
| BGFX_CAPS_BLEND_INDEPENDENT
| BGFX_CAPS_COMPUTE
| BGFX_CAPS_FRAGMENT_ORDERING
// | BGFX_CAPS_SWAP_CHAIN
) ;
g_caps . maxTextureSize = 16384 ;
g_caps . maxFBAttachments = bx : : uint32_min ( 16 , BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ) ;
for ( uint32_t ii = 0 ; ii < TextureFormat : : Count ; + + ii )
{
uint8_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE ;
const DXGI_FORMAT fmt = isDepth ( TextureFormat : : Enum ( ii ) )
? s_textureFormat [ ii ] . m_fmtDsv
: s_textureFormat [ ii ] . m_fmt
;
if ( DXGI_FORMAT_UNKNOWN ! = fmt )
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT data ;
data . Format = fmt ;
hr = m_device - > CheckFeatureSupport ( D3D12_FEATURE_FORMAT_SUPPORT , & data , sizeof ( data ) ) ;
if ( SUCCEEDED ( hr ) )
{
support | = 0 ! = ( data . Support1 & ( 0
| D3D12_FORMAT_SUPPORT1_TEXTURE2D
| D3D12_FORMAT_SUPPORT1_TEXTURE3D
| D3D12_FORMAT_SUPPORT1_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_COLOR
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support | = 0 ! = ( data . Support1 & ( 0
| D3D12_FORMAT_SUPPORT1_BUFFER
| D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER
| D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER
) )
? BGFX_CAPS_FORMAT_TEXTURE_VERTEX
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support | = 0 ! = ( data . Support1 & ( 0
| D3D12_FORMAT_SUPPORT1_SHADER_LOAD
) )
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support | = 0 ! = ( data . Support1 & ( 0
| D3D12_FORMAT_SUPPORT1_RENDER_TARGET
| D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL
) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
else
{
BX_TRACE ( " CheckFeatureSupport failed with %x for format %s. " , hr , getName ( TextureFormat : : Enum ( ii ) ) ) ;
}
}
g_caps . formats [ ii ] = support ;
}
postReset ( ) ;
}
~ RendererContextD3D12 ( )
{
preReset ( ) ;
m_samplerAllocator . destroy ( ) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_scratchBuffer ) ; + + ii )
{
m_scratchBuffer [ ii ] . destroy ( ) ;
}
m_pipelineStateCache . invalidate ( ) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_indexBuffers ) ; + + ii )
{
m_indexBuffers [ ii ] . destroy ( ) ;
}
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_vertexBuffers ) ; + + ii )
{
m_vertexBuffers [ ii ] . destroy ( ) ;
}
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_shaders ) ; + + ii )
{
m_shaders [ ii ] . destroy ( ) ;
}
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_textures ) ; + + ii )
{
m_textures [ ii ] . destroy ( ) ;
}
DX_RELEASE ( m_rtvDescriptorHeap , 0 ) ;
DX_RELEASE ( m_dsvDescriptorHeap , 0 ) ;
DX_RELEASE ( m_rootSignature , 0 ) ;
DX_RELEASE ( m_swapChain , 0 ) ;
m_cmd . shutdown ( ) ;
DX_RELEASE ( m_device , 0 ) ;
# if USE_D3D12_DYNAMIC_LIB
bx : : dlclose ( m_d3d12dll ) ;
bx : : dlclose ( m_dxgidll ) ;
# endif // USE_D3D12_DYNAMIC_LIB
}
RendererType : : Enum getRendererType ( ) const BX_OVERRIDE
{
return RendererType : : Direct3D12 ;
}
const char * getRendererName ( ) const BX_OVERRIDE
{
return BGFX_RENDERER_DIRECT3D12_NAME ;
}
static bool isLost ( HRESULT _hr )
{
return DXGI_ERROR_DEVICE_REMOVED = = _hr
| | DXGI_ERROR_DEVICE_HUNG = = _hr
| | DXGI_ERROR_DEVICE_RESET = = _hr
| | DXGI_ERROR_DRIVER_INTERNAL_ERROR = = _hr
| | DXGI_ERROR_NOT_CURRENTLY_AVAILABLE = = _hr
;
}
void flip ( HMD & /*_hmd*/ ) BX_OVERRIDE
{
if ( NULL ! = m_swapChain )
{
HRESULT hr = 0 ;
uint32_t syncInterval = ! ! ( m_flags & BGFX_RESET_VSYNC ) ;
for ( uint32_t ii = 1 , num = m_numWindows ; ii < num & & SUCCEEDED ( hr ) ; + + ii )
{
hr = m_frameBuffers [ m_windows [ ii ] . idx ] . m_swapChain - > Present ( syncInterval , 0 ) ;
}
if ( SUCCEEDED ( hr ) )
{
m_cmd . finish ( m_backBufferColorFence [ ( m_backBufferColorIdx - 1 ) % m_scd . BufferCount ] ) ;
hr = m_swapChain - > Present ( syncInterval , 0 ) ;
}
if ( FAILED ( hr )
& & isLost ( hr ) )
{
+ + m_lost ;
BGFX_FATAL ( 10 > m_lost , bgfx : : Fatal : : DeviceLost , " Device is lost. FAILED 0x%08x " , hr ) ;
}
else
{
m_lost = 0 ;
}
}
}
void createIndexBuffer ( IndexBufferHandle _handle , Memory * _mem , uint16_t _flags ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data , _flags , false ) ;
}
void destroyIndexBuffer ( IndexBufferHandle _handle ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createVertexDecl ( VertexDeclHandle _handle , const VertexDecl & _decl ) BX_OVERRIDE
{
VertexDecl & decl = m_vertexDecls [ _handle . idx ] ;
memcpy ( & decl , & _decl , sizeof ( VertexDecl ) ) ;
dump ( decl ) ;
}
void destroyVertexDecl ( VertexDeclHandle /*_handle*/ ) BX_OVERRIDE
{
}
void createVertexBuffer ( VertexBufferHandle _handle , Memory * _mem , VertexDeclHandle _declHandle , uint16_t _flags ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data , _declHandle , _flags ) ;
}
void destroyVertexBuffer ( VertexBufferHandle _handle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createDynamicIndexBuffer ( IndexBufferHandle _handle , uint32_t _size , uint16_t _flags ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . create ( _size , NULL , _flags , false ) ;
}
void updateDynamicIndexBuffer ( IndexBufferHandle _handle , uint32_t _offset , uint32_t _size , Memory * _mem ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . update ( m_commandList , _offset , bx : : uint32_min ( _size , _mem - > size ) , _mem - > data ) ;
}
void destroyDynamicIndexBuffer ( IndexBufferHandle _handle ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createDynamicVertexBuffer ( VertexBufferHandle _handle , uint32_t _size , uint16_t _flags ) BX_OVERRIDE
{
VertexDeclHandle decl = BGFX_INVALID_HANDLE ;
m_vertexBuffers [ _handle . idx ] . create ( _size , NULL , decl , _flags ) ;
}
void updateDynamicVertexBuffer ( VertexBufferHandle _handle , uint32_t _offset , uint32_t _size , Memory * _mem ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . update ( m_commandList , _offset , bx : : uint32_min ( _size , _mem - > size ) , _mem - > data ) ;
}
void destroyDynamicVertexBuffer ( VertexBufferHandle _handle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createShader ( ShaderHandle _handle , Memory * _mem ) BX_OVERRIDE
{
m_shaders [ _handle . idx ] . create ( _mem ) ;
}
void destroyShader ( ShaderHandle _handle ) BX_OVERRIDE
{
m_shaders [ _handle . idx ] . destroy ( ) ;
}
void createProgram ( ProgramHandle _handle , ShaderHandle _vsh , ShaderHandle _fsh ) BX_OVERRIDE
{
m_program [ _handle . idx ] . create ( & m_shaders [ _vsh . idx ] , isValid ( _fsh ) ? & m_shaders [ _fsh . idx ] : NULL ) ;
}
void destroyProgram ( ProgramHandle _handle ) BX_OVERRIDE
{
m_program [ _handle . idx ] . destroy ( ) ;
}
void createTexture ( TextureHandle _handle , Memory * _mem , uint32_t _flags , uint8_t _skip ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . create ( _mem , _flags , _skip ) ;
}
void updateTextureBegin ( TextureHandle /*_handle*/ , uint8_t /*_side*/ , uint8_t /*_mip*/ ) BX_OVERRIDE
{
}
void updateTexture ( TextureHandle _handle , uint8_t _side , uint8_t _mip , const Rect & _rect , uint16_t _z , uint16_t _depth , uint16_t _pitch , const Memory * _mem ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . update ( m_commandList , _side , _mip , _rect , _z , _depth , _pitch , _mem ) ;
}
void updateTextureEnd ( ) BX_OVERRIDE
{
}
void resizeTexture ( TextureHandle _handle , uint16_t _width , uint16_t _height ) BX_OVERRIDE
{
TextureD3D12 & texture = m_textures [ _handle . idx ] ;
uint32_t size = sizeof ( uint32_t ) + sizeof ( TextureCreate ) ;
const Memory * mem = alloc ( size ) ;
bx : : StaticMemoryBlockWriter writer ( mem - > data , mem - > size ) ;
uint32_t magic = BGFX_CHUNK_MAGIC_TEX ;
bx : : write ( & writer , magic ) ;
TextureCreate tc ;
tc . m_flags = texture . m_flags ;
tc . m_width = _width ;
tc . m_height = _height ;
tc . m_sides = 0 ;
tc . m_depth = 0 ;
tc . m_numMips = 1 ;
tc . m_format = texture . m_requestedFormat ;
tc . m_cubeMap = false ;
tc . m_mem = NULL ;
bx : : write ( & writer , tc ) ;
texture . destroy ( ) ;
texture . create ( mem , tc . m_flags , 0 ) ;
release ( mem ) ;
}
void destroyTexture ( TextureHandle _handle ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . destroy ( ) ;
}
void createFrameBuffer ( FrameBufferHandle _handle , uint8_t _num , const TextureHandle * _textureHandles ) BX_OVERRIDE
{
m_frameBuffers [ _handle . idx ] . create ( _num , _textureHandles ) ;
}
void createFrameBuffer ( FrameBufferHandle _handle , void * _nwh , uint32_t _width , uint32_t _height , TextureFormat : : Enum _depthFormat ) BX_OVERRIDE
{
uint16_t denseIdx = m_numWindows + + ;
m_windows [ denseIdx ] = _handle ;
m_frameBuffers [ _handle . idx ] . create ( denseIdx , _nwh , _width , _height , _depthFormat ) ;
}
void destroyFrameBuffer ( FrameBufferHandle _handle ) BX_OVERRIDE
{
uint16_t denseIdx = m_frameBuffers [ _handle . idx ] . destroy ( ) ;
if ( UINT16_MAX ! = denseIdx )
{
- - m_numWindows ;
if ( m_numWindows > 1 )
{
FrameBufferHandle handle = m_windows [ m_numWindows ] ;
m_windows [ denseIdx ] = handle ;
m_frameBuffers [ handle . idx ] . m_denseIdx = denseIdx ;
}
}
}
void createUniform ( UniformHandle _handle , UniformType : : Enum _type , uint16_t _num , const char * _name ) BX_OVERRIDE
{
if ( NULL ! = m_uniforms [ _handle . idx ] )
{
BX_FREE ( g_allocator , m_uniforms [ _handle . idx ] ) ;
}
uint32_t size = BX_ALIGN_16 ( g_uniformTypeSize [ _type ] * _num ) ;
void * data = BX_ALLOC ( g_allocator , size ) ;
memset ( data , 0 , size ) ;
m_uniforms [ _handle . idx ] = data ;
m_uniformReg . add ( _handle , _name , data ) ;
}
void destroyUniform ( UniformHandle _handle ) BX_OVERRIDE
{
BX_FREE ( g_allocator , m_uniforms [ _handle . idx ] ) ;
m_uniforms [ _handle . idx ] = NULL ;
}
void saveScreenShot ( const char * /*_filePath*/ ) BX_OVERRIDE
{
}
void updateViewName ( uint8_t /*_id*/ , const char * /*_name*/ ) BX_OVERRIDE
{
}
void updateUniform ( uint16_t _loc , const void * _data , uint32_t _size ) BX_OVERRIDE
{
memcpy ( m_uniforms [ _loc ] , _data , _size ) ;
}
void setMarker ( const char * /*_marker*/ , uint32_t /*_size*/ ) BX_OVERRIDE
{
}
void submit ( Frame * _render , ClearQuad & _clearQuad , TextVideoMemBlitter & _textVideoMemBlitter ) BX_OVERRIDE ;
void blitSetup ( TextVideoMemBlitter & _blitter ) BX_OVERRIDE
{
const uint32_t width = m_scd . BufferDesc . Width ;
const uint32_t height = m_scd . BufferDesc . Height ;
FrameBufferHandle fbh = BGFX_INVALID_HANDLE ;
setFrameBuffer ( fbh , false ) ;
D3D12_VIEWPORT vp ;
vp . TopLeftX = 0 ;
vp . TopLeftY = 0 ;
vp . Width = ( float ) width ;
vp . Height = ( float ) height ;
vp . MinDepth = 0.0f ;
vp . MaxDepth = 1.0f ;
m_commandList - > RSSetViewports ( 1 , & vp ) ;
const uint64_t state = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_TEST_ALWAYS
;
m_currentProgram = & m_program [ 0 ] ;
ID3D12PipelineState * pso = getPipelineState ( state
, packStencil ( BGFX_STENCIL_DEFAULT , BGFX_STENCIL_DEFAULT )
, _blitter . m_vb - > decl . idx
, _blitter . m_program . idx
, 0
) ;
m_commandList - > SetPipelineState ( pso ) ;
m_commandList - > SetGraphicsRootSignature ( m_rootSignature ) ;
float proj [ 16 ] ;
bx : : mtxOrtho ( proj , 0.0f , ( float ) width , ( float ) height , 0.0f , 0.0f , 1000.0f ) ;
PredefinedUniform & predefined = m_program [ _blitter . m_program . idx ] . m_predefined [ 0 ] ;
uint8_t flags = predefined . m_type ;
setShaderUniform ( flags , predefined . m_loc , proj , 4 ) ;
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle ;
commitShaderConstants ( gpuHandle ) ;
ID3D12DescriptorHeap * heaps [ ] =
{
m_samplerAllocator . getHeap ( ) ,
m_scratchBuffer [ m_backBufferColorIdx ] . getHeap ( ) ,
} ;
m_commandList - > SetDescriptorHeaps ( BX_COUNTOF ( heaps ) , heaps ) ;
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : CBV , gpuHandle ) ;
TextureD3D12 & texture = m_textures [ _blitter . m_texture . idx ] ;
uint32_t samplerFlags [ BGFX_CONFIG_MAX_TEXTURE_SAMPLERS ] = { texture . m_flags & BGFX_TEXTURE_SAMPLER_BITS_MASK } ;
uint16_t samplerStateIdx = getSamplerState ( samplerFlags ) ;
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : Sampler , m_samplerAllocator . get ( samplerStateIdx ) ) ;
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle ;
m_scratchBuffer [ m_backBufferColorIdx ] . alloc ( srvHandle , texture ) ;
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : SRV , srvHandle ) ;
VertexBufferD3D12 & vb = m_vertexBuffers [ _blitter . m_vb - > handle . idx ] ;
const VertexDecl & vertexDecl = m_vertexDecls [ _blitter . m_vb - > decl . idx ] ;
D3D12_VERTEX_BUFFER_VIEW viewDesc ;
viewDesc . BufferLocation = vb . m_ptr - > GetGPUVirtualAddress ( ) ;
viewDesc . StrideInBytes = vertexDecl . m_stride ;
viewDesc . SizeInBytes = vb . m_size ;
m_commandList - > IASetVertexBuffers ( 0 , 1 , & viewDesc ) ;
const BufferD3D12 & ib = m_indexBuffers [ _blitter . m_ib - > handle . idx ] ;
D3D12_INDEX_BUFFER_VIEW ibv ;
ibv . Format = DXGI_FORMAT_R16_UINT ;
ibv . BufferLocation = ib . m_ptr - > GetGPUVirtualAddress ( ) ;
ibv . SizeInBytes = ib . m_size ;
m_commandList - > IASetIndexBuffer ( & ibv ) ;
m_commandList - > IASetPrimitiveTopology ( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST ) ;
}
void blitRender ( TextVideoMemBlitter & _blitter , uint32_t _numIndices ) BX_OVERRIDE
{
const uint32_t numVertices = _numIndices * 4 / 6 ;
if ( 0 < numVertices )
{
m_indexBuffers [ _blitter . m_ib - > handle . idx ] . update ( m_commandList , 0 , _numIndices * 2 , _blitter . m_ib - > data ) ;
m_vertexBuffers [ _blitter . m_vb - > handle . idx ] . update ( m_commandList , 0 , numVertices * _blitter . m_decl . m_stride , _blitter . m_vb - > data , true ) ;
m_commandList - > DrawIndexedInstanced ( _numIndices
, 1
, 0
, 0
, 0
) ;
}
}
void preReset ( )
{
finish ( ) ;
for ( uint32_t ii = 0 , num = m_scd . BufferCount ; ii < num ; + + ii )
{
DX_RELEASE ( m_backBufferColor [ ii ] , num - 1 - ii ) ;
}
DX_RELEASE ( m_backBufferDepthStencil , 0 ) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_frameBuffers ) ; + + ii )
{
m_frameBuffers [ ii ] . preReset ( ) ;
}
invalidateCache ( ) ;
// capturePreReset();
}
void postReset ( )
{
uint32_t rtvDescriptorSize = m_device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) ;
for ( uint32_t ii = 0 , num = m_scd . BufferCount ; ii < num ; + + ii )
{
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_rtvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
handle . ptr + = ii * rtvDescriptorSize ;
DX_CHECK ( m_swapChain - > GetBuffer ( ii
, __uuidof ( ID3D12Resource )
, ( void * * ) & m_backBufferColor [ ii ]
) ) ;
m_device - > CreateRenderTargetView ( m_backBufferColor [ ii ] , NULL , handle ) ;
}
D3D12_RESOURCE_DESC resourceDesc ;
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
resourceDesc . Alignment = 0 ;
resourceDesc . Width = bx : : uint32_max ( m_resolution . m_width , 1 ) ;
resourceDesc . Height = bx : : uint32_max ( m_resolution . m_height , 1 ) ;
resourceDesc . DepthOrArraySize = 1 ;
resourceDesc . MipLevels = 0 ;
resourceDesc . Format = DXGI_FORMAT_D24_UNORM_S8_UINT ;
resourceDesc . SampleDesc . Count = 1 ;
resourceDesc . SampleDesc . Quality = 0 ;
resourceDesc . Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN ;
resourceDesc . Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL ;
D3D12_CLEAR_VALUE clearValue ;
clearValue . Format = resourceDesc . Format ;
clearValue . DepthStencil . Depth = 1.0f ;
clearValue . DepthStencil . Stencil = 0 ;
m_backBufferDepthStencil = createCommittedResource ( m_device , HeapProperty : : Default , & resourceDesc , & clearValue ) ;
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc ;
ZeroMemory ( & dsvDesc , sizeof ( dsvDesc ) ) ;
dsvDesc . Format = resourceDesc . Format ;
dsvDesc . ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D ;
dsvDesc . Flags = D3D12_DSV_FLAGS ( 0 )
// | D3D12_DSV_FLAG_READ_ONLY_DEPTH
// | D3D12_DSV_FLAG_READ_ONLY_DEPTH
;
m_device - > CreateDepthStencilView ( m_backBufferDepthStencil
, & dsvDesc
, m_dsvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( )
) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_frameBuffers ) ; + + ii )
{
m_frameBuffers [ ii ] . postReset ( ) ;
}
m_commandList = m_cmd . alloc ( ) ;
// capturePostReset();
}
void invalidateCache ( )
{
m_pipelineStateCache . invalidate ( ) ;
m_samplerStateCache . invalidate ( ) ;
}
void updateMsaa ( )
{
for ( uint32_t ii = 1 , last = 0 ; ii < BX_COUNTOF ( s_msaa ) ; + + ii )
{
uint32_t msaa = s_checkMsaa [ ii ] ;
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS data ;
memset ( & data , 0 , sizeof ( msaa ) ) ;
data . Format = m_scd . BufferDesc . Format ;
data . SampleCount = msaa ;
data . Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE ;
HRESULT hr = m_device - > CheckFeatureSupport ( D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS , & data , sizeof ( data ) ) ;
data . NumQualityLevels = 0 ;
if ( SUCCEEDED ( hr )
& & 0 < data . NumQualityLevels )
{
s_msaa [ ii ] . Count = data . SampleCount ;
s_msaa [ ii ] . Quality = data . NumQualityLevels - 1 ;
last = ii ;
}
else
{
s_msaa [ ii ] = s_msaa [ last ] ;
}
}
}
void updateResolution ( const Resolution & _resolution )
{
if ( ( uint32_t ) m_scd . BufferDesc . Width ! = _resolution . m_width
| | ( uint32_t ) m_scd . BufferDesc . Height ! = _resolution . m_height
| | m_flags ! = _resolution . m_flags )
{
bool resize = ( m_flags & BGFX_RESET_MSAA_MASK ) = = ( _resolution . m_flags & BGFX_RESET_MSAA_MASK ) ;
m_flags = _resolution . m_flags ;
m_textVideoMem . resize ( false , _resolution . m_width , _resolution . m_height ) ;
m_textVideoMem . clear ( ) ;
m_resolution = _resolution ;
m_scd . BufferDesc . Width = _resolution . m_width ;
m_scd . BufferDesc . Height = _resolution . m_height ;
preReset ( ) ;
if ( resize )
{
DX_CHECK ( m_swapChain - > ResizeBuffers ( m_scd . BufferCount
, m_scd . BufferDesc . Width
, m_scd . BufferDesc . Height
, m_scd . BufferDesc . Format
, m_scd . Flags
) ) ;
}
else
{
updateMsaa ( ) ;
m_scd . SampleDesc = s_msaa [ ( m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ] ;
DX_RELEASE ( m_swapChain , 0 ) ;
HRESULT hr ;
hr = m_factory - > CreateSwapChain ( m_cmd . m_commandQueue
, & m_scd
, & m_swapChain
) ;
BGFX_FATAL ( SUCCEEDED ( hr ) , bgfx : : Fatal : : UnableToInitialize , " Failed to create swap chain. " ) ;
}
postReset ( ) ;
}
}
void setShaderUniform ( uint8_t _flags , uint16_t _regIndex , const void * _val , uint16_t _numRegs )
{
if ( _flags & BGFX_UNIFORM_FRAGMENTBIT )
{
memcpy ( & m_fsScratch [ _regIndex ] , _val , _numRegs * 16 ) ;
m_fsChanges + = _numRegs ;
}
else
{
memcpy ( & m_vsScratch [ _regIndex ] , _val , _numRegs * 16 ) ;
m_vsChanges + = _numRegs ;
}
}
void setShaderUniform4f ( uint8_t _flags , uint16_t _regIndex , const void * _val , uint16_t _numRegs )
{
setShaderUniform ( _flags , _regIndex , _val , _numRegs ) ;
}
void setShaderUniform4x4f ( uint8_t _flags , uint16_t _regIndex , const void * _val , uint16_t _numRegs )
{
setShaderUniform ( _flags , _regIndex , _val , _numRegs ) ;
}
void commitShaderConstants ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle )
{
uint32_t total = bx : : strideAlign ( 0
+ m_currentProgram - > m_vsh - > m_size
+ ( NULL ! = m_currentProgram - > m_fsh ? m_currentProgram - > m_fsh - > m_size : 0 )
, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT
) ;
uint8_t * data = ( uint8_t * ) m_scratchBuffer [ m_backBufferColorIdx ] . alloc ( gpuHandle , total ) ;
{
uint32_t size = m_currentProgram - > m_vsh - > m_size ;
memcpy ( data , m_vsScratch , size ) ;
data + = size ;
m_vsChanges = 0 ;
}
if ( NULL ! = m_currentProgram - > m_fsh )
{
memcpy ( data , m_fsScratch , m_currentProgram - > m_fsh - > m_size ) ;
m_fsChanges = 0 ;
}
}
void setFrameBuffer ( FrameBufferHandle _fbh , bool _msaa = true )
{
if ( isValid ( m_fbh )
& & m_fbh . idx ! = _fbh . idx )
{
const FrameBufferD3D12 & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
for ( uint8_t ii = 0 , num = frameBuffer . m_num ; ii < num ; + + ii )
{
TextureD3D12 & texture = m_textures [ frameBuffer . m_texture [ ii ] . idx ] ;
texture . setState ( m_commandList , D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ) ;
}
if ( isValid ( frameBuffer . m_depth ) )
{
TextureD3D12 & texture = m_textures [ frameBuffer . m_depth . idx ] ;
const bool bufferOnly = 0 ! = ( texture . m_flags & BGFX_TEXTURE_RT_BUFFER_ONLY ) ;
if ( ! bufferOnly )
{
texture . setState ( m_commandList , D3D12_RESOURCE_STATES ( 0 )
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
// | D3D12_RESOURCE_STATE_DEPTH_READ
) ;
}
}
}
if ( ! isValid ( _fbh ) )
{
m_rtvHandle = m_rtvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t rtvDescriptorSize = m_device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) ;
m_rtvHandle . ptr + = m_backBufferColorIdx * rtvDescriptorSize ;
m_dsvHandle = m_dsvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
m_currentColor = & m_rtvHandle ;
m_currentDepthStencil = & m_dsvHandle ;
m_commandList - > OMSetRenderTargets ( 1 , m_currentColor , false , m_currentDepthStencil ) ;
}
else
{
const FrameBufferD3D12 & frameBuffer = m_frameBuffers [ _fbh . idx ] ;
if ( 0 < frameBuffer . m_num )
{
D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = m_rtvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t rtvDescriptorSize = m_device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) ;
m_rtvHandle . ptr = rtvDescriptor . ptr + ( BX_COUNTOF ( m_backBufferColor ) + _fbh . idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ) * rtvDescriptorSize ;
m_currentColor = & m_rtvHandle ;
}
else
{
m_currentColor = NULL ;
}
if ( isValid ( frameBuffer . m_depth ) )
{
D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = m_dsvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t dsvDescriptorSize = m_device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_DSV ) ;
m_dsvHandle . ptr = dsvDescriptor . ptr + ( 1 + _fbh . idx ) * dsvDescriptorSize ;
m_currentDepthStencil = & m_dsvHandle ;
}
else
{
m_currentDepthStencil = NULL ;
}
for ( uint8_t ii = 0 , num = frameBuffer . m_num ; ii < num ; + + ii )
{
TextureD3D12 & texture = m_textures [ frameBuffer . m_texture [ ii ] . idx ] ;
texture . setState ( m_commandList , D3D12_RESOURCE_STATE_RENDER_TARGET ) ;
}
if ( isValid ( frameBuffer . m_depth ) )
{
TextureD3D12 & texture = m_textures [ frameBuffer . m_depth . idx ] ;
texture . setState ( m_commandList , D3D12_RESOURCE_STATE_DEPTH_WRITE ) ;
}
m_commandList - > OMSetRenderTargets ( frameBuffer . m_num
, m_currentColor
, true //NULL == m_currentDepthStencil
, m_currentDepthStencil
) ;
}
m_fbh = _fbh ;
m_rtMsaa = _msaa ;
}
void setBlendState ( D3D12_BLEND_DESC & desc , uint64_t _state , uint32_t _rgba = 0 )
{
memset ( & desc , 0 , sizeof ( desc ) ) ;
desc . IndependentBlendEnable = ! ! ( BGFX_STATE_BLEND_INDEPENDENT & _state ) ;
D3D12_RENDER_TARGET_BLEND_DESC * drt = & desc . RenderTarget [ 0 ] ;
drt - > BlendEnable = ! ! ( BGFX_STATE_BLEND_MASK & _state ) ;
{
const uint32_t blend = uint32_t ( ( _state & BGFX_STATE_BLEND_MASK ) > > BGFX_STATE_BLEND_SHIFT ) ;
const uint32_t equation = uint32_t ( ( _state & BGFX_STATE_BLEND_EQUATION_MASK ) > > BGFX_STATE_BLEND_EQUATION_SHIFT ) ;
const uint32_t srcRGB = ( blend ) & 0xf ;
const uint32_t dstRGB = ( blend > > 4 ) & 0xf ;
const uint32_t srcA = ( blend > > 8 ) & 0xf ;
const uint32_t dstA = ( blend > > 12 ) & 0xf ;
const uint32_t equRGB = ( equation ) & 0x7 ;
const uint32_t equA = ( equation > > 3 ) & 0x7 ;
drt - > SrcBlend = s_blendFactor [ srcRGB ] [ 0 ] ;
drt - > DestBlend = s_blendFactor [ dstRGB ] [ 0 ] ;
drt - > BlendOp = s_blendEquation [ equRGB ] ;
drt - > SrcBlendAlpha = s_blendFactor [ srcA ] [ 1 ] ;
drt - > DestBlendAlpha = s_blendFactor [ dstA ] [ 1 ] ;
drt - > BlendOpAlpha = s_blendEquation [ equA ] ;
}
uint32_t writeMask = ( _state & BGFX_STATE_ALPHA_WRITE )
? D3D12_COLOR_WRITE_ENABLE_ALPHA
: 0
;
writeMask | = ( _state & BGFX_STATE_RGB_WRITE )
? D3D12_COLOR_WRITE_ENABLE_RED
| D3D12_COLOR_WRITE_ENABLE_GREEN
| D3D12_COLOR_WRITE_ENABLE_BLUE
: 0
;
drt - > RenderTargetWriteMask = writeMask ;
if ( desc . IndependentBlendEnable )
{
for ( uint32_t ii = 1 , rgba = _rgba ; ii < BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ; + + ii , rgba > > = 11 )
{
drt = & desc . RenderTarget [ ii ] ;
drt - > BlendEnable = 0 ! = ( rgba & 0x7ff ) ;
const uint32_t src = ( rgba ) & 0xf ;
const uint32_t dst = ( rgba > > 4 ) & 0xf ;
const uint32_t equation = ( rgba > > 8 ) & 0x7 ;
drt - > SrcBlend = s_blendFactor [ src ] [ 0 ] ;
drt - > DestBlend = s_blendFactor [ dst ] [ 0 ] ;
drt - > BlendOp = s_blendEquation [ equation ] ;
drt - > SrcBlendAlpha = s_blendFactor [ src ] [ 1 ] ;
drt - > DestBlendAlpha = s_blendFactor [ dst ] [ 1 ] ;
drt - > BlendOpAlpha = s_blendEquation [ equation ] ;
drt - > RenderTargetWriteMask = writeMask ;
}
}
else
{
for ( uint32_t ii = 1 ; ii < BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ; + + ii )
{
memcpy ( & desc . RenderTarget [ ii ] , drt , sizeof ( D3D12_RENDER_TARGET_BLEND_DESC ) ) ;
}
}
}
void setRasterizerState ( D3D12_RASTERIZER_DESC & desc , uint64_t _state , bool _wireframe = false )
{
const uint32_t cull = ( _state & BGFX_STATE_CULL_MASK ) > > BGFX_STATE_CULL_SHIFT ;
desc . FillMode = _wireframe
? D3D12_FILL_MODE_WIREFRAME
: D3D12_FILL_MODE_SOLID
;
desc . CullMode = s_cullMode [ cull ] ;
desc . FrontCounterClockwise = false ;
desc . DepthBias = 0 ;
desc . DepthBiasClamp = 0.0f ;
desc . SlopeScaledDepthBias = 0.0f ;
desc . DepthClipEnable = false ;
desc . MultisampleEnable = ! ! ( _state & BGFX_STATE_MSAA ) ;
desc . AntialiasedLineEnable = false ;
desc . ForcedSampleCount = 0 ;
desc . ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF ;
}
void setDepthStencilState ( D3D12_DEPTH_STENCIL_DESC & desc , uint64_t _state , uint64_t _stencil = 0 )
{
const uint32_t fstencil = unpackStencil ( 0 , _stencil ) ;
memset ( & desc , 0 , sizeof ( desc ) ) ;
uint32_t func = ( _state & BGFX_STATE_DEPTH_TEST_MASK ) > > BGFX_STATE_DEPTH_TEST_SHIFT ;
desc . DepthEnable = 0 ! = func ;
desc . DepthWriteMask = ! ! ( BGFX_STATE_DEPTH_WRITE & _state )
? D3D12_DEPTH_WRITE_MASK_ALL
: D3D12_DEPTH_WRITE_MASK_ZERO
;
desc . DepthFunc = s_cmpFunc [ func ] ;
uint32_t bstencil = unpackStencil ( 1 , _stencil ) ;
uint32_t frontAndBack = bstencil ! = BGFX_STENCIL_NONE & & bstencil ! = fstencil ;
bstencil = frontAndBack ? bstencil : fstencil ;
desc . StencilEnable = 0 ! = _stencil ;
desc . StencilReadMask = ( fstencil & BGFX_STENCIL_FUNC_RMASK_MASK ) > > BGFX_STENCIL_FUNC_RMASK_SHIFT ;
desc . StencilWriteMask = 0xff ;
desc . FrontFace . StencilFailOp = s_stencilOp [ ( fstencil & BGFX_STENCIL_OP_FAIL_S_MASK ) > > BGFX_STENCIL_OP_FAIL_S_SHIFT ] ;
desc . FrontFace . StencilDepthFailOp = s_stencilOp [ ( fstencil & BGFX_STENCIL_OP_FAIL_Z_MASK ) > > BGFX_STENCIL_OP_FAIL_Z_SHIFT ] ;
desc . FrontFace . StencilPassOp = s_stencilOp [ ( fstencil & BGFX_STENCIL_OP_PASS_Z_MASK ) > > BGFX_STENCIL_OP_PASS_Z_SHIFT ] ;
desc . FrontFace . StencilFunc = s_cmpFunc [ ( fstencil & BGFX_STENCIL_TEST_MASK ) > > BGFX_STENCIL_TEST_SHIFT ] ;
desc . BackFace . StencilFailOp = s_stencilOp [ ( bstencil & BGFX_STENCIL_OP_FAIL_S_MASK ) > > BGFX_STENCIL_OP_FAIL_S_SHIFT ] ;
desc . BackFace . StencilDepthFailOp = s_stencilOp [ ( bstencil & BGFX_STENCIL_OP_FAIL_Z_MASK ) > > BGFX_STENCIL_OP_FAIL_Z_SHIFT ] ;
desc . BackFace . StencilPassOp = s_stencilOp [ ( bstencil & BGFX_STENCIL_OP_PASS_Z_MASK ) > > BGFX_STENCIL_OP_PASS_Z_SHIFT ] ;
desc . BackFace . StencilFunc = s_cmpFunc [ ( bstencil & BGFX_STENCIL_TEST_MASK ) > > BGFX_STENCIL_TEST_SHIFT ] ;
}
uint32_t setInputLayout ( D3D12_INPUT_ELEMENT_DESC * _vertexElements , const VertexDecl & _vertexDecl , const ProgramD3D12 & _program , uint8_t _numInstanceData )
{
VertexDecl decl ;
memcpy ( & decl , & _vertexDecl , sizeof ( VertexDecl ) ) ;
const uint8_t * attrMask = _program . m_vsh - > m_attrMask ;
for ( uint32_t ii = 0 ; ii < Attrib : : Count ; + + ii )
{
uint8_t mask = attrMask [ ii ] ;
uint8_t attr = ( decl . m_attributes [ ii ] & mask ) ;
decl . m_attributes [ ii ] = attr = = 0 ? 0xff : attr = = 0xff ? 0 : attr ;
}
D3D12_INPUT_ELEMENT_DESC * elem = fillVertexDecl ( _vertexElements , decl ) ;
uint32_t num = uint32_t ( elem - _vertexElements ) ;
const D3D12_INPUT_ELEMENT_DESC inst = { " TEXCOORD " , 0 , DXGI_FORMAT_R32G32B32A32_FLOAT , 0 , D3D12_APPEND_ALIGNED_ELEMENT , D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA , 1 } ;
for ( uint32_t ii = 0 ; ii < _numInstanceData ; + + ii )
{
uint32_t index = 7 - ii ; // TEXCOORD7 = i_data0, TEXCOORD6 = i_data1, etc.
uint32_t jj ;
D3D12_INPUT_ELEMENT_DESC * curr = _vertexElements ;
for ( jj = 0 ; jj < num ; + + jj )
{
curr = & _vertexElements [ jj ] ;
if ( 0 = = strcmp ( curr - > SemanticName , " TEXCOORD " )
& & curr - > SemanticIndex = = index )
{
break ;
}
}
if ( jj = = num )
{
curr = elem ;
+ + elem ;
}
memcpy ( curr , & inst , sizeof ( D3D12_INPUT_ELEMENT_DESC ) ) ;
curr - > InputSlot = 1 ;
curr - > SemanticIndex = index ;
curr - > AlignedByteOffset = ii * 16 ;
}
return uint32_t ( elem - _vertexElements ) ;
}
static void patchCb0 ( DxbcInstruction & _instruction , void * _userData )
{
union { void * ptr ; uint32_t offset ; } cast = { _userData } ;
for ( uint32_t ii = 0 ; ii < _instruction . numOperands ; + + ii )
{
DxbcOperand & operand = _instruction . operand [ ii ] ;
if ( DxbcOperandType : : ConstantBuffer = = operand . type )
{
if ( DxbcOperandAddrMode : : Imm32 = = operand . addrMode [ 0 ]
& & 0 = = operand . regIndex [ 0 ]
& & DxbcOperandAddrMode : : Imm32 = = operand . addrMode [ 1 ] )
{
operand . regIndex [ 1 ] + = cast . offset ;
}
}
}
}
ID3D12PipelineState * getPipelineState ( uint16_t _programIdx )
{
ProgramD3D12 & program = m_program [ _programIdx ] ;
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
murmur . add ( program . m_vsh - > m_hash ) ;
const uint32_t hash = murmur . end ( ) ;
ID3D12PipelineState * pso = m_pipelineStateCache . find ( hash ) ;
if ( NULL ! = pso )
{
return pso ;
}
D3D12_COMPUTE_PIPELINE_STATE_DESC desc ;
memset ( & desc , 0 , sizeof ( desc ) ) ;
desc . pRootSignature = m_rootSignature ;
desc . CS . pShaderBytecode = program . m_vsh - > m_code - > data ;
desc . CS . BytecodeLength = program . m_vsh - > m_code - > size ;
DX_CHECK ( m_device - > CreateComputePipelineState ( & desc
, __uuidof ( ID3D12PipelineState )
, ( void * * ) & pso
) ) ;
m_pipelineStateCache . add ( hash , pso ) ;
return pso ;
}
ID3D12PipelineState * getPipelineState ( uint64_t _state , uint64_t _stencil , uint16_t _declIdx , uint16_t _programIdx , uint8_t _numInstanceData )
{
ProgramD3D12 & program = m_program [ _programIdx ] ;
_state & = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_MASK
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_BLEND_INDEPENDENT
| BGFX_STATE_CULL_MASK
| BGFX_STATE_MSAA
| BGFX_STATE_PT_MASK
;
_stencil & = packStencil ( ~ BGFX_STENCIL_FUNC_REF_MASK , BGFX_STENCIL_MASK ) ;
VertexDecl decl ;
memcpy ( & decl , & m_vertexDecls [ _declIdx ] , sizeof ( VertexDecl ) ) ;
const uint8_t * attrMask = program . m_vsh - > m_attrMask ;
for ( uint32_t ii = 0 ; ii < Attrib : : Count ; + + ii )
{
uint8_t mask = attrMask [ ii ] ;
uint8_t attr = ( decl . m_attributes [ ii ] & mask ) ;
decl . m_attributes [ ii ] = attr = = 0 ? 0xff : attr = = 0xff ? 0 : attr ;
}
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
murmur . add ( _state ) ;
murmur . add ( _stencil ) ;
murmur . add ( program . m_vsh - > m_hash ) ;
murmur . add ( program . m_vsh - > m_attrMask , sizeof ( program . m_vsh - > m_attrMask ) ) ;
murmur . add ( program . m_fsh - > m_hash ) ;
murmur . add ( m_vertexDecls [ _declIdx ] . m_hash ) ;
murmur . add ( decl . m_attributes , sizeof ( decl . m_attributes ) ) ;
murmur . add ( m_fbh . idx ) ;
murmur . add ( _numInstanceData ) ;
const uint32_t hash = murmur . end ( ) ;
ID3D12PipelineState * pso = m_pipelineStateCache . find ( hash ) ;
if ( NULL ! = pso )
{
return pso ;
}
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc ;
memset ( & desc , 0 , sizeof ( desc ) ) ;
desc . pRootSignature = m_rootSignature ;
desc . VS . pShaderBytecode = program . m_vsh - > m_code - > data ;
desc . VS . BytecodeLength = program . m_vsh - > m_code - > size ;
const Memory * temp = alloc ( program . m_fsh - > m_code - > size ) ;
memset ( temp - > data , 0 , temp - > size ) ;
bx : : MemoryReader rd ( program . m_fsh - > m_code - > data , program . m_fsh - > m_code - > size ) ;
bx : : StaticMemoryBlockWriter wr ( temp - > data , temp - > size ) ;
DxbcContext dxbc ;
read ( & rd , dxbc ) ;
bool patchShader = true ;
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG ) )
{
union { uint32_t offset ; void * ptr ; } cast = { 0 } ;
filter ( dxbc . shader , dxbc . shader , patchCb0 , cast . ptr ) ;
write ( & wr , dxbc ) ;
dxbcHash ( temp - > data + 20 , temp - > size - 20 , temp - > data + 4 ) ;
patchShader = 0 = = memcmp ( program . m_fsh - > m_code - > data , temp - > data , 16 ) ;
BX_CHECK ( patchShader , " DXBC fragment shader patching error (ShaderHandle: %d). " , program . m_fsh - m_shaders ) ;
if ( ! patchShader )
{
for ( uint32_t ii = 20 ; ii < temp - > size ; ii + = 16 )
{
if ( 0 ! = memcmp ( & program . m_fsh - > m_code - > data [ ii ] , & temp - > data [ ii ] , 16 ) )
{
// dbgPrintfData(&program.m_fsh->m_code->data[ii], temp->size-ii, "");
// dbgPrintfData(&temp->data[ii], temp->size-ii, "");
break ;
}
}
desc . PS . pShaderBytecode = program . m_fsh - > m_code - > data ;
desc . PS . BytecodeLength = program . m_fsh - > m_code - > size ;
}
}
if ( patchShader )
{
memcpy ( temp - > data , program . m_fsh - > m_code - > data , program . m_fsh - > m_code - > size ) ;
bx : : seek ( & wr , 0 , bx : : Whence : : Begin ) ;
union { uint32_t offset ; void * ptr ; } cast =
{
m_currentProgram - > m_vsh - > m_size / 16
} ;
filter ( dxbc . shader , dxbc . shader , patchCb0 , cast . ptr ) ;
write ( & wr , dxbc ) ;
dxbcHash ( temp - > data + 20 , temp - > size - 20 , temp - > data + 4 ) ;
desc . PS . pShaderBytecode = temp - > data ;
desc . PS . BytecodeLength = temp - > size ;
}
desc . DS . pShaderBytecode = NULL ;
desc . DS . BytecodeLength = 0 ;
desc . HS . pShaderBytecode = NULL ;
desc . HS . BytecodeLength = 0 ;
desc . GS . pShaderBytecode = NULL ;
desc . GS . BytecodeLength = 0 ;
desc . StreamOutput . pSODeclaration = NULL ;
desc . StreamOutput . NumEntries = 0 ;
desc . StreamOutput . pBufferStrides = NULL ;
desc . StreamOutput . NumStrides = 0 ;
desc . StreamOutput . RasterizedStream = 0 ;
setBlendState ( desc . BlendState , _state ) ;
desc . SampleMask = 1 ;
setRasterizerState ( desc . RasterizerState , _state ) ;
setDepthStencilState ( desc . DepthStencilState , _state , _stencil ) ;
D3D12_INPUT_ELEMENT_DESC vertexElements [ Attrib : : Count + 1 + BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT ] ;
desc . InputLayout . NumElements = setInputLayout ( vertexElements , m_vertexDecls [ _declIdx ] , program , _numInstanceData ) ;
desc . InputLayout . pInputElementDescs = vertexElements ;
uint8_t primIndex = uint8_t ( ( _state & BGFX_STATE_PT_MASK ) > > BGFX_STATE_PT_SHIFT ) ;
desc . PrimitiveTopologyType = s_primInfo [ primIndex ] . m_topologyType ;
if ( isValid ( m_fbh ) )
{
const FrameBufferD3D12 & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
desc . NumRenderTargets = frameBuffer . m_num ;
for ( uint8_t ii = 0 , num = frameBuffer . m_num ; ii < num ; + + ii )
{
desc . RTVFormats [ ii ] = m_textures [ frameBuffer . m_texture [ ii ] . idx ] . m_srvd . Format ;
}
if ( isValid ( frameBuffer . m_depth ) )
{
desc . DSVFormat = s_textureFormat [ m_textures [ frameBuffer . m_depth . idx ] . m_textureFormat ] . m_fmtDsv ;
}
else
{
desc . DSVFormat = DXGI_FORMAT_UNKNOWN ;
}
}
else
{
desc . NumRenderTargets = 1 ;
desc . RTVFormats [ 0 ] = DXGI_FORMAT_R8G8B8A8_UNORM ;
desc . DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT ;
}
desc . SampleDesc . Count = 1 ;
desc . SampleDesc . Quality = 0 ;
uint32_t length = g_callback - > cacheReadSize ( hash ) ;
bool cached = length > 0 ;
void * cachedData = NULL ;
if ( cached )
{
cachedData = BX_ALLOC ( g_allocator , length ) ;
if ( g_callback - > cacheRead ( hash , cachedData , length ) )
{
BX_TRACE ( " Loading chached PSO (size %d). " , length ) ;
bx : : MemoryReader reader ( cachedData , length ) ;
// uint32_t format;
// bx::read(&reader, format);
desc . CachedPSO . pCachedBlob = reader . getDataPtr ( ) ;
desc . CachedPSO . CachedBlobSizeInBytes = ( size_t ) reader . remaining ( ) ;
HRESULT hr = m_device - > CreateGraphicsPipelineState ( & desc
, __uuidof ( ID3D12PipelineState )
, ( void * * ) & pso
) ;
if ( FAILED ( hr ) )
{
BX_TRACE ( " Failed to load cached PSO (HRESULT 0x%08x). " , hr ) ;
memset ( & desc . CachedPSO , 0 , sizeof ( desc . CachedPSO ) ) ;
}
}
}
if ( NULL = = pso )
{
DX_CHECK ( m_device - > CreateGraphicsPipelineState ( & desc
, __uuidof ( ID3D12PipelineState )
, ( void * * ) & pso
) ) ;
}
m_pipelineStateCache . add ( hash , pso ) ;
release ( temp ) ;
ID3DBlob * blob ;
HRESULT hr = pso - > GetCachedBlob ( & blob ) ;
if ( SUCCEEDED ( hr ) )
{
void * data = blob - > GetBufferPointer ( ) ;
length = ( uint32_t ) blob - > GetBufferSize ( ) ;
g_callback - > cacheWrite ( hash , data , length ) ;
DX_RELEASE ( blob , 0 ) ;
}
if ( NULL ! = cachedData )
{
BX_FREE ( g_allocator , cachedData ) ;
}
return pso ;
}
uint16_t getSamplerState ( const uint32_t * _flags , uint32_t _num = BGFX_CONFIG_MAX_TEXTURE_SAMPLERS )
{
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
murmur . add ( _flags , _num * sizeof ( uint32_t ) ) ;
uint32_t hash = murmur . end ( ) ;
uint16_t sampler = m_samplerStateCache . find ( hash ) ;
if ( UINT16_MAX = = sampler )
{
sampler = m_samplerAllocator . alloc ( _flags , _num ) ;
m_samplerStateCache . add ( hash , sampler ) ;
}
return sampler ;
}
void commit ( ConstantBuffer & _constantBuffer )
{
_constantBuffer . reset ( ) ;
for ( ; ; )
{
uint32_t opcode = _constantBuffer . read ( ) ;
if ( UniformType : : End = = opcode )
{
break ;
}
UniformType : : Enum type ;
uint16_t loc ;
uint16_t num ;
uint16_t copy ;
ConstantBuffer : : decodeOpcode ( opcode , type , loc , num , copy ) ;
const char * data ;
if ( copy )
{
data = _constantBuffer . read ( g_uniformTypeSize [ type ] * num ) ;
}
else
{
UniformHandle handle ;
memcpy ( & handle , _constantBuffer . read ( sizeof ( UniformHandle ) ) , sizeof ( UniformHandle ) ) ;
data = ( const char * ) m_uniforms [ handle . idx ] ;
}
# define CASE_IMPLEMENT_UNIFORM(_uniform, _dxsuffix, _type) \
case UniformType : : _uniform : \
case UniformType : : _uniform | BGFX_UNIFORM_FRAGMENTBIT : \
{ \
setShaderUniform ( type , loc , data , num ) ; \
} \
break ;
switch ( ( int32_t ) type )
{
case UniformType : : Mat3 :
case UniformType : : Mat3 | BGFX_UNIFORM_FRAGMENTBIT :
{
float * value = ( float * ) data ;
for ( uint32_t ii = 0 , count = num / 3 ; ii < count ; + + ii , loc + = 3 * 16 , value + = 9 )
{
Matrix4 mtx ;
mtx . un . val [ 0 ] = value [ 0 ] ;
mtx . un . val [ 1 ] = value [ 1 ] ;
mtx . un . val [ 2 ] = value [ 2 ] ;
mtx . un . val [ 3 ] = 0.0f ;
mtx . un . val [ 4 ] = value [ 3 ] ;
mtx . un . val [ 5 ] = value [ 4 ] ;
mtx . un . val [ 6 ] = value [ 5 ] ;
mtx . un . val [ 7 ] = 0.0f ;
mtx . un . val [ 8 ] = value [ 6 ] ;
mtx . un . val [ 9 ] = value [ 7 ] ;
mtx . un . val [ 10 ] = value [ 8 ] ;
mtx . un . val [ 11 ] = 0.0f ;
setShaderUniform ( type , loc , & mtx . un . val [ 0 ] , 3 ) ;
}
}
break ;
CASE_IMPLEMENT_UNIFORM ( Int1 , I , int ) ;
CASE_IMPLEMENT_UNIFORM ( Vec4 , F , float ) ;
CASE_IMPLEMENT_UNIFORM ( Mat4 , F , float ) ;
case UniformType : : End :
break ;
default :
BX_TRACE ( " %4d: INVALID 0x%08x, t %d, l %d, n %d, c %d " , _constantBuffer . getPos ( ) , opcode , type , loc , num , copy ) ;
break ;
}
# undef CASE_IMPLEMENT_UNIFORM
}
}
void clear ( const Clear & _clear , const float _palette [ ] [ 4 ] , const D3D12_RECT * _rect = NULL , uint32_t _num = 0 )
{
if ( isValid ( m_fbh ) )
{
FrameBufferD3D12 & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
frameBuffer . clear ( m_commandList , _clear , _palette ) ;
}
else
{
if ( NULL ! = m_currentColor
& & BGFX_CLEAR_COLOR & _clear . m_flags )
{
if ( BGFX_CLEAR_COLOR_USE_PALETTE & _clear . m_flags )
{
uint8_t index = _clear . m_index [ 0 ] ;
if ( UINT8_MAX ! = index )
{
m_commandList - > ClearRenderTargetView ( * m_currentColor
, _palette [ index ]
, _num
, _rect
) ;
}
}
else
{
float frgba [ 4 ] =
{
_clear . m_index [ 0 ] * 1.0f / 255.0f ,
_clear . m_index [ 1 ] * 1.0f / 255.0f ,
_clear . m_index [ 2 ] * 1.0f / 255.0f ,
_clear . m_index [ 3 ] * 1.0f / 255.0f ,
} ;
m_commandList - > ClearRenderTargetView ( * m_currentColor
, frgba
, _num
, _rect
) ;
}
}
if ( NULL ! = m_currentDepthStencil
& & ( BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL ) & _clear . m_flags )
{
uint32_t flags = 0 ;
flags | = ( _clear . m_flags & BGFX_CLEAR_DEPTH ) ? D3D12_CLEAR_FLAG_DEPTH : 0 ;
flags | = ( _clear . m_flags & BGFX_CLEAR_STENCIL ) ? D3D12_CLEAR_FLAG_STENCIL : 0 ;
m_commandList - > ClearDepthStencilView ( * m_currentDepthStencil
, D3D12_CLEAR_FLAGS ( flags )
, _clear . m_depth
, _clear . m_stencil
, _num
, _rect
) ;
}
}
}
void clearQuad ( ClearQuad & _clearQuad , const Rect & _rect , const Clear & _clear , const float _palette [ ] [ 4 ] )
{
BX_UNUSED ( _clearQuad ) ;
uint32_t width = m_scd . BufferDesc . Width ;
uint32_t height = m_scd . BufferDesc . Height ;
if ( 0 = = _rect . m_x
& & 0 = = _rect . m_y
& & width = = _rect . m_width
& & height = = _rect . m_height )
{
clear ( _clear , _palette ) ;
}
else
{
D3D12_RECT rect ;
rect . left = _rect . m_x ;
rect . top = _rect . m_y ;
rect . right = _rect . m_x + _rect . m_width ;
rect . bottom = _rect . m_y + _rect . m_height ;
clear ( _clear , _palette , & rect ) ;
}
}
uint64_t kick ( )
{
uint64_t fence = m_cmd . kick ( ) ;
m_commandList = m_cmd . alloc ( ) ;
return fence ;
}
void finish ( )
{
m_cmd . kick ( ) ;
m_cmd . finish ( ) ;
m_commandList = NULL ;
}
void * m_d3d12dll ;
void * m_dxgidll ;
D3D_DRIVER_TYPE m_driverType ;
IDXGIAdapter * m_adapter ;
DXGI_ADAPTER_DESC m_adapterDesc ;
D3D12_FEATURE_DATA_ARCHITECTURE m_architecture ;
D3D12_FEATURE_DATA_D3D12_OPTIONS m_options ;
IDXGIFactory1 * m_factory ;
IDXGISwapChain * m_swapChain ;
uint16_t m_lost ;
uint16_t m_numWindows ;
FrameBufferHandle m_windows [ BGFX_CONFIG_MAX_FRAME_BUFFERS ] ;
ID3D12Device * m_device ;
ID3D12InfoQueue * m_infoQueue ;
ID3D12DescriptorHeap * m_rtvDescriptorHeap ;
ID3D12DescriptorHeap * m_dsvDescriptorHeap ;
D3D12_CPU_DESCRIPTOR_HANDLE m_rtvHandle ;
D3D12_CPU_DESCRIPTOR_HANDLE m_dsvHandle ;
D3D12_CPU_DESCRIPTOR_HANDLE * m_currentColor ;
D3D12_CPU_DESCRIPTOR_HANDLE * m_currentDepthStencil ;
ID3D12Resource * m_backBufferColor [ 4 ] ;
uint64_t m_backBufferColorFence [ 4 ] ;
ID3D12Resource * m_backBufferDepthStencil ;
ScratchBufferD3D12 m_scratchBuffer [ 4 ] ;
DescriptorAllocator m_samplerAllocator ;
ID3D12RootSignature * m_rootSignature ;
CommandQueue m_cmd ;
ID3D12GraphicsCommandList * m_commandList ;
Resolution m_resolution ;
bool m_wireframe ;
DXGI_SWAP_CHAIN_DESC m_scd ;
uint32_t m_flags ;
BufferD3D12 m_indexBuffers [ BGFX_CONFIG_MAX_INDEX_BUFFERS ] ;
VertexBufferD3D12 m_vertexBuffers [ BGFX_CONFIG_MAX_VERTEX_BUFFERS ] ;
ShaderD3D12 m_shaders [ BGFX_CONFIG_MAX_SHADERS ] ;
ProgramD3D12 m_program [ BGFX_CONFIG_MAX_PROGRAMS ] ;
TextureD3D12 m_textures [ BGFX_CONFIG_MAX_TEXTURES ] ;
VertexDecl m_vertexDecls [ BGFX_CONFIG_MAX_VERTEX_DECLS ] ;
FrameBufferD3D12 m_frameBuffers [ BGFX_CONFIG_MAX_FRAME_BUFFERS ] ;
void * m_uniforms [ BGFX_CONFIG_MAX_UNIFORMS ] ;
Matrix4 m_predefinedUniforms [ PredefinedUniform : : Count ] ;
UniformRegistry m_uniformReg ;
StateCacheT < ID3D12PipelineState > m_pipelineStateCache ;
StateCache m_samplerStateCache ;
TextVideoMem m_textVideoMem ;
ProgramD3D12 * m_currentProgram ;
uint8_t m_fsScratch [ 64 < < 10 ] ;
uint8_t m_vsScratch [ 64 < < 10 ] ;
uint32_t m_fsChanges ;
uint32_t m_vsChanges ;
FrameBufferHandle m_fbh ;
uint32_t m_frame ;
uint32_t m_backBufferColorIdx ;
bool m_rtMsaa ;
} ;
static RendererContextD3D12 * s_renderD3D12 ;
RendererContextI * rendererCreate ( )
{
s_renderD3D12 = BX_NEW ( g_allocator , RendererContextD3D12 ) ;
s_renderD3D12 - > init ( ) ;
return s_renderD3D12 ;
}
void rendererDestroy ( )
{
BX_DELETE ( g_allocator , s_renderD3D12 ) ;
s_renderD3D12 = NULL ;
}
void ScratchBufferD3D12 : : create ( uint32_t _size , uint32_t _maxDescriptors )
{
m_size = _size ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
m_incrementSize = device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ) ;
D3D12_DESCRIPTOR_HEAP_DESC desc ;
desc . NumDescriptors = _maxDescriptors ;
desc . Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ;
desc . Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE ;
desc . NodeMask = 0 ;
DX_CHECK ( device - > CreateDescriptorHeap ( & desc
, __uuidof ( ID3D12DescriptorHeap )
, ( void * * ) & m_heap
) ) ;
m_upload = createCommittedResource ( device , HeapProperty : : Upload , desc . NumDescriptors * 1024 ) ;
m_upload - > Map ( 0 , NULL , ( void * * ) & m_data ) ;
reset ( m_gpuHandle ) ;
}
void ScratchBufferD3D12 : : destroy ( )
{
m_upload - > Unmap ( 0 , NULL ) ;
DX_RELEASE ( m_upload , 0 ) ;
DX_RELEASE ( m_heap , 0 ) ;
}
void ScratchBufferD3D12 : : reset ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle )
{
m_pos = 0 ;
m_cpuHandle = m_heap - > GetCPUDescriptorHandleForHeapStart ( ) ;
m_gpuHandle = m_heap - > GetGPUDescriptorHandleForHeapStart ( ) ;
gpuHandle = m_gpuHandle ;
}
void * ScratchBufferD3D12 : : alloc ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle , uint32_t _size )
{
D3D12_CONSTANT_BUFFER_VIEW_DESC desc ;
desc . BufferLocation = m_upload - > GetGPUVirtualAddress ( ) + m_pos ;
desc . SizeInBytes = _size ;
void * data = & m_data [ m_pos ] ;
m_pos + = BX_ALIGN_256 ( _size ) ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateConstantBufferView ( & desc
, m_cpuHandle
) ;
m_cpuHandle . ptr + = m_incrementSize ;
gpuHandle = m_gpuHandle ;
m_gpuHandle . ptr + = m_incrementSize ;
return data ;
}
void ScratchBufferD3D12 : : alloc ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle , TextureD3D12 & _texture )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateShaderResourceView ( _texture . m_ptr
, & _texture . m_srvd
, m_cpuHandle
) ;
m_cpuHandle . ptr + = m_incrementSize ;
gpuHandle = m_gpuHandle ;
m_gpuHandle . ptr + = m_incrementSize ;
}
void ScratchBufferD3D12 : : allocUav ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle , TextureD3D12 & _texture )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateUnorderedAccessView ( _texture . m_ptr
, NULL
, & _texture . m_uavd
, m_cpuHandle
) ;
m_cpuHandle . ptr + = m_incrementSize ;
gpuHandle = m_gpuHandle ;
m_gpuHandle . ptr + = m_incrementSize ;
}
void ScratchBufferD3D12 : : alloc ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle , BufferD3D12 & _buffer )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateShaderResourceView ( _buffer . m_ptr
, & _buffer . m_srvd
, m_cpuHandle
) ;
m_cpuHandle . ptr + = m_incrementSize ;
gpuHandle = m_gpuHandle ;
m_gpuHandle . ptr + = m_incrementSize ;
}
void ScratchBufferD3D12 : : allocUav ( D3D12_GPU_DESCRIPTOR_HANDLE & gpuHandle , BufferD3D12 & _buffer )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateUnorderedAccessView ( _buffer . m_ptr
, NULL
, & _buffer . m_uavd
, m_cpuHandle
) ;
m_cpuHandle . ptr + = m_incrementSize ;
gpuHandle = m_gpuHandle ;
m_gpuHandle . ptr + = m_incrementSize ;
}
void DescriptorAllocator : : create ( D3D12_DESCRIPTOR_HEAP_TYPE _type , uint32_t _maxDescriptors , uint16_t _numDescriptorsPerBlock )
{
m_handleAlloc = bx : : createHandleAlloc ( g_allocator , _maxDescriptors ) ;
m_numDescriptorsPerBlock = _numDescriptorsPerBlock ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
m_incrementSize = device - > GetDescriptorHandleIncrementSize ( _type ) ;
D3D12_DESCRIPTOR_HEAP_DESC desc ;
desc . NumDescriptors = _maxDescriptors ;
desc . Type = _type ;
desc . Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE ;
desc . NodeMask = 0 ;
DX_CHECK ( device - > CreateDescriptorHeap ( & desc
, __uuidof ( ID3D12DescriptorHeap )
, ( void * * ) & m_heap
) ) ;
m_cpuHandle = m_heap - > GetCPUDescriptorHandleForHeapStart ( ) ;
m_gpuHandle = m_heap - > GetGPUDescriptorHandleForHeapStart ( ) ;
}
void DescriptorAllocator : : destroy ( )
{
bx : : destroyHandleAlloc ( g_allocator , m_handleAlloc ) ;
DX_RELEASE ( m_heap , 0 ) ;
}
uint16_t DescriptorAllocator : : alloc ( ID3D12Resource * _ptr , const D3D12_SHADER_RESOURCE_VIEW_DESC * _desc )
{
uint16_t idx = m_handleAlloc - > alloc ( ) ;
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = { m_cpuHandle . ptr + idx * m_incrementSize } ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
device - > CreateShaderResourceView ( _ptr
, _desc
, cpuHandle
) ;
return idx ;
}
uint16_t DescriptorAllocator : : alloc ( const uint32_t * _flags , uint32_t _num )
{
uint16_t idx = m_handleAlloc - > alloc ( ) ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
for ( uint32_t ii = 0 ; ii < _num ; + + ii )
{
uint32_t flags = _flags [ ii ] ;
const uint32_t cmpFunc = ( flags & BGFX_TEXTURE_COMPARE_MASK ) > > BGFX_TEXTURE_COMPARE_SHIFT ;
const uint8_t minFilter = s_textureFilter [ 0 ] [ ( flags & BGFX_TEXTURE_MIN_MASK ) > > BGFX_TEXTURE_MIN_SHIFT ] ;
const uint8_t magFilter = s_textureFilter [ 1 ] [ ( flags & BGFX_TEXTURE_MAG_MASK ) > > BGFX_TEXTURE_MAG_SHIFT ] ;
const uint8_t mipFilter = s_textureFilter [ 2 ] [ ( flags & BGFX_TEXTURE_MIP_MASK ) > > BGFX_TEXTURE_MIP_SHIFT ] ;
const uint8_t filter = 0 = = cmpFunc ? 0 : D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT ;
D3D12_SAMPLER_DESC sd ;
sd . Filter = ( D3D12_FILTER ) ( filter | minFilter | magFilter | mipFilter ) ;
sd . AddressU = s_textureAddress [ ( flags & BGFX_TEXTURE_U_MASK ) > > BGFX_TEXTURE_U_SHIFT ] ;
sd . AddressV = s_textureAddress [ ( flags & BGFX_TEXTURE_V_MASK ) > > BGFX_TEXTURE_V_SHIFT ] ;
sd . AddressW = s_textureAddress [ ( flags & BGFX_TEXTURE_W_MASK ) > > BGFX_TEXTURE_W_SHIFT ] ;
sd . MinLOD = 0 ;
sd . MaxLOD = D3D12_FLOAT32_MAX ;
sd . MipLODBias = 0.0f ;
sd . MaxAnisotropy = 1 ; //m_maxAnisotropy;
sd . ComparisonFunc = 0 = = cmpFunc ? D3D12_COMPARISON_FUNC_NEVER : s_cmpFunc [ cmpFunc ] ;
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle =
{
m_cpuHandle . ptr + ( idx * m_numDescriptorsPerBlock + ii ) * m_incrementSize
} ;
device - > CreateSampler ( & sd , cpuHandle ) ;
}
return idx ;
}
void DescriptorAllocator : : free ( uint16_t _idx )
{
m_handleAlloc - > free ( _idx ) ;
}
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorAllocator : : get ( uint16_t _idx )
{
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = { m_gpuHandle . ptr + _idx * m_numDescriptorsPerBlock * m_incrementSize } ;
return gpuHandle ;
}
struct UavFormat
{
DXGI_FORMAT format [ 3 ] ;
uint32_t stride ;
} ;
static const UavFormat s_uavFormat [ ] =
{ // BGFX_BUFFER_COMPUTE_TYPE_UINT, BGFX_BUFFER_COMPUTE_TYPE_INT, BGFX_BUFFER_COMPUTE_TYPE_FLOAT
{ { DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN , DXGI_FORMAT_UNKNOWN } , 0 } , // ignored
{ { DXGI_FORMAT_R8_SINT , DXGI_FORMAT_R8_UINT , DXGI_FORMAT_UNKNOWN } , 1 } , // BGFX_BUFFER_COMPUTE_FORMAT_8x1
{ { DXGI_FORMAT_R8G8_SINT , DXGI_FORMAT_R8G8_UINT , DXGI_FORMAT_UNKNOWN } , 2 } , // BGFX_BUFFER_COMPUTE_FORMAT_8x2
{ { DXGI_FORMAT_R8G8B8A8_SINT , DXGI_FORMAT_R8G8B8A8_UINT , DXGI_FORMAT_UNKNOWN } , 4 } , // BGFX_BUFFER_COMPUTE_FORMAT_8x4
{ { DXGI_FORMAT_R16_SINT , DXGI_FORMAT_R16_UINT , DXGI_FORMAT_R16_FLOAT } , 2 } , // BGFX_BUFFER_COMPUTE_FORMAT_16x1
{ { DXGI_FORMAT_R16G16_SINT , DXGI_FORMAT_R16G16_UINT , DXGI_FORMAT_R16G16_FLOAT } , 4 } , // BGFX_BUFFER_COMPUTE_FORMAT_16x2
{ { DXGI_FORMAT_R16G16B16A16_SINT , DXGI_FORMAT_R16G16B16A16_UINT , DXGI_FORMAT_R16G16B16A16_FLOAT } , 8 } , // BGFX_BUFFER_COMPUTE_FORMAT_16x4
{ { DXGI_FORMAT_R32_SINT , DXGI_FORMAT_R32_UINT , DXGI_FORMAT_R32_FLOAT } , 4 } , // BGFX_BUFFER_COMPUTE_FORMAT_32x1
{ { DXGI_FORMAT_R32G32_SINT , DXGI_FORMAT_R32G32_UINT , DXGI_FORMAT_R32G32_FLOAT } , 8 } , // BGFX_BUFFER_COMPUTE_FORMAT_32x2
{ { DXGI_FORMAT_R32G32B32A32_SINT , DXGI_FORMAT_R32G32B32A32_UINT , DXGI_FORMAT_R32G32B32A32_FLOAT } , 16 } , // BGFX_BUFFER_COMPUTE_FORMAT_32x4
} ;
void BufferD3D12 : : create ( uint32_t _size , void * _data , uint16_t _flags , bool _vertex )
{
m_size = _size ;
m_flags = _flags ;
const bool needUav = 0 ! = ( _flags & ( BGFX_BUFFER_COMPUTE_WRITE | BGFX_BUFFER_DRAW_INDIRECT ) ) ;
// const bool needSrv = 0 != (_flags & BGFX_BUFFER_COMPUTE_READ);
const bool drawIndirect = 0 ! = ( _flags & BGFX_BUFFER_DRAW_INDIRECT ) ;
m_dynamic = NULL = = _data | | needUav ;
DXGI_FORMAT format ;
uint32_t stride ;
D3D12_RESOURCE_FLAGS flags = needUav
? D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
: D3D12_RESOURCE_FLAG_NONE
;
if ( drawIndirect )
{
format = DXGI_FORMAT_R32G32B32A32_UINT ;
stride = 16 ;
}
else
{
uint32_t uavFormat = ( _flags & BGFX_BUFFER_COMPUTE_FORMAT_MASK ) > > BGFX_BUFFER_COMPUTE_FORMAT_SHIFT ;
if ( 0 = = uavFormat )
{
if ( _vertex )
{
format = DXGI_FORMAT_R32G32B32A32_FLOAT ;
stride = 16 ;
}
else
{
if ( 0 = = ( _flags & BGFX_BUFFER_INDEX32 ) )
{
format = DXGI_FORMAT_R16_UINT ;
stride = 2 ;
}
else
{
format = DXGI_FORMAT_R32_UINT ;
stride = 4 ;
}
}
}
else
{
const uint32_t uavType = bx : : uint32_satsub ( ( _flags & BGFX_BUFFER_COMPUTE_TYPE_MASK ) > > BGFX_BUFFER_COMPUTE_TYPE_SHIFT , 1 ) ;
format = s_uavFormat [ uavFormat ] . format [ uavType ] ;
stride = s_uavFormat [ uavFormat ] . stride ;
}
}
m_srvd . Format = format ;
m_srvd . ViewDimension = D3D12_SRV_DIMENSION_BUFFER ;
m_srvd . Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING ;
m_srvd . Buffer . FirstElement = 0 ;
m_srvd . Buffer . NumElements = m_size / stride ;
m_srvd . Buffer . StructureByteStride = 0 ;
m_srvd . Buffer . Flags = D3D12_BUFFER_SRV_FLAG_NONE ;
m_uavd . Format = format ;
m_uavd . ViewDimension = D3D12_UAV_DIMENSION_BUFFER ;
m_uavd . Buffer . FirstElement = 0 ;
m_uavd . Buffer . NumElements = m_size / stride ;
m_uavd . Buffer . StructureByteStride = 0 ;
m_uavd . Buffer . CounterOffsetInBytes = 0 ;
m_uavd . Buffer . Flags = D3D12_BUFFER_UAV_FLAG_NONE ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
ID3D12GraphicsCommandList * commandList = s_renderD3D12 - > m_commandList ;
m_ptr = createCommittedResource ( device , HeapProperty : : Default , _size , flags ) ;
if ( ! needUav )
{
m_staging = createCommittedResource ( device , HeapProperty : : Upload , _size ) ;
}
if ( m_dynamic )
{
setState ( commandList , D3D12_RESOURCE_STATE_GENERIC_READ ) ;
}
else
{
setState ( commandList , D3D12_RESOURCE_STATE_COPY_DEST ) ;
D3D12_SUBRESOURCE_DATA subresource ;
subresource . pData = _data ;
subresource . RowPitch = _size ;
subresource . SlicePitch = subresource . RowPitch ;
UpdateSubresources < 1 > ( commandList
, m_ptr
, m_staging
, 0
, 0
, 1
, & subresource
) ;
setState ( commandList , D3D12_RESOURCE_STATE_GENERIC_READ ) ;
}
}
void BufferD3D12 : : update ( ID3D12GraphicsCommandList * _commandList , uint32_t /*_offset*/ , uint32_t _size , void * _data , bool /*_discard*/ )
{
setState ( _commandList , D3D12_RESOURCE_STATE_COPY_DEST ) ;
D3D12_SUBRESOURCE_DATA subresource ;
subresource . pData = _data ;
subresource . RowPitch = _size ;
subresource . SlicePitch = subresource . RowPitch ;
UpdateSubresources < 1 > ( _commandList
, m_ptr
, m_staging
, 0
, 0
, 1
, & subresource
) ;
setState ( _commandList , D3D12_RESOURCE_STATE_GENERIC_READ ) ;
}
void BufferD3D12 : : setState ( ID3D12GraphicsCommandList * _commandList , D3D12_RESOURCE_STATES _state )
{
if ( m_state ! = _state )
{
setResourceBarrier ( _commandList
, m_ptr
, m_state
, _state
) ;
m_state = _state ;
}
}
void VertexBufferD3D12 : : create ( uint32_t _size , void * _data , VertexDeclHandle _declHandle , uint16_t _flags )
{
BufferD3D12 : : create ( _size , _data , _flags , true ) ;
m_decl = _declHandle ;
}
void ShaderD3D12 : : create ( const Memory * _mem )
{
bx : : MemoryReader reader ( _mem - > data , _mem - > size ) ;
uint32_t magic ;
bx : : read ( & reader , magic ) ;
switch ( magic )
{
case BGFX_CHUNK_MAGIC_CSH :
case BGFX_CHUNK_MAGIC_FSH :
case BGFX_CHUNK_MAGIC_VSH :
break ;
default :
BGFX_FATAL ( false , Fatal : : InvalidShader , " Unknown shader format %x. " , magic ) ;
break ;
}
bool fragment = BGFX_CHUNK_MAGIC_FSH = = magic ;
uint32_t iohash ;
bx : : read ( & reader , iohash ) ;
uint16_t count ;
bx : : read ( & reader , count ) ;
m_numPredefined = 0 ;
m_numUniforms = count ;
BX_TRACE ( " %s Shader consts %d "
, BGFX_CHUNK_MAGIC_FSH = = magic ? " Fragment " : BGFX_CHUNK_MAGIC_VSH = = magic ? " Vertex " : " Compute "
, count
) ;
uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0 ;
if ( 0 < count )
{
for ( uint32_t ii = 0 ; ii < count ; + + ii )
{
uint8_t nameSize ;
bx : : read ( & reader , nameSize ) ;
char name [ 256 ] ;
bx : : read ( & reader , & name , nameSize ) ;
name [ nameSize ] = ' \0 ' ;
uint8_t type ;
bx : : read ( & reader , type ) ;
uint8_t num ;
bx : : read ( & reader , num ) ;
uint16_t regIndex ;
bx : : read ( & reader , regIndex ) ;
uint16_t regCount ;
bx : : read ( & reader , regCount ) ;
const char * kind = " invalid " ;
PredefinedUniform : : Enum predefined = nameToPredefinedUniformEnum ( name ) ;
if ( PredefinedUniform : : Count ! = predefined )
{
kind = " predefined " ;
m_predefined [ m_numPredefined ] . m_loc = regIndex ;
m_predefined [ m_numPredefined ] . m_count = regCount ;
m_predefined [ m_numPredefined ] . m_type = predefined | fragmentBit ;
m_numPredefined + + ;
}
else
{
const UniformInfo * info = s_renderD3D12 - > m_uniformReg . find ( name ) ;
if ( NULL ! = info )
{
if ( NULL = = m_constantBuffer )
{
m_constantBuffer = ConstantBuffer : : create ( 1024 ) ;
}
kind = " user " ;
m_constantBuffer - > writeUniformHandle ( ( UniformType : : Enum ) ( type | fragmentBit ) , regIndex , info - > m_handle , regCount ) ;
}
}
BX_TRACE ( " \t %s: %s (%s), num %2d, r.index %3d, r.count %2d "
, kind
, name
, getUniformTypeName ( UniformType : : Enum ( type & ~ BGFX_UNIFORM_FRAGMENTBIT ) )
, num
, regIndex
, regCount
) ;
BX_UNUSED ( kind ) ;
}
if ( NULL ! = m_constantBuffer )
{
m_constantBuffer - > finish ( ) ;
}
}
uint16_t shaderSize ;
bx : : read ( & reader , shaderSize ) ;
const DWORD * code = ( const DWORD * ) reader . getDataPtr ( ) ;
bx : : skip ( & reader , shaderSize + 1 ) ;
m_code = copy ( code , shaderSize ) ;
uint8_t numAttrs ;
bx : : read ( & reader , numAttrs ) ;
memset ( m_attrMask , 0 , sizeof ( m_attrMask ) ) ;
for ( uint32_t ii = 0 ; ii < numAttrs ; + + ii )
{
uint16_t id ;
bx : : read ( & reader , id ) ;
Attrib : : Enum attr = idToAttrib ( id ) ;
if ( Attrib : : Count ! = attr )
{
m_attrMask [ attr ] = 0xff ;
}
}
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
murmur . add ( iohash ) ;
murmur . add ( code , shaderSize ) ;
murmur . add ( numAttrs ) ;
murmur . add ( m_attrMask , numAttrs ) ;
m_hash = murmur . end ( ) ;
bx : : read ( & reader , m_size ) ;
}
void TextureD3D12 : : create ( const Memory * _mem , uint32_t _flags , uint8_t _skip )
{
ImageContainer imageContainer ;
if ( imageParse ( imageContainer , _mem - > data , _mem - > size ) )
{
uint8_t numMips = imageContainer . m_numMips ;
const uint32_t startLod = bx : : uint32_min ( _skip , numMips - 1 ) ;
numMips - = startLod ;
const ImageBlockInfo & blockInfo = getBlockInfo ( TextureFormat : : Enum ( imageContainer . m_format ) ) ;
const uint32_t textureWidth = bx : : uint32_max ( blockInfo . blockWidth , imageContainer . m_width > > startLod ) ;
const uint32_t textureHeight = bx : : uint32_max ( blockInfo . blockHeight , imageContainer . m_height > > startLod ) ;
m_flags = _flags ;
m_requestedFormat = ( uint8_t ) imageContainer . m_format ;
m_textureFormat = ( uint8_t ) imageContainer . m_format ;
const TextureFormatInfo & tfi = s_textureFormat [ m_requestedFormat ] ;
const bool convert = DXGI_FORMAT_UNKNOWN = = tfi . m_fmt ;
uint8_t bpp = getBitsPerPixel ( TextureFormat : : Enum ( m_textureFormat ) ) ;
if ( convert )
{
m_textureFormat = ( uint8_t ) TextureFormat : : BGRA8 ;
bpp = 32 ;
}
if ( imageContainer . m_cubeMap )
{
m_type = TextureCube ;
}
else if ( imageContainer . m_depth > 1 )
{
m_type = Texture3D ;
}
else
{
m_type = Texture2D ;
}
m_numMips = numMips ;
const uint32_t numSides = imageContainer . m_cubeMap ? 6 : 1 ;
uint32_t numSrd = numMips * numSides ;
D3D12_SUBRESOURCE_DATA * srd = ( D3D12_SUBRESOURCE_DATA * ) alloca ( numSrd * sizeof ( D3D12_SUBRESOURCE_DATA ) ) ;
uint32_t kk = 0 ;
const bool compressed = isCompressed ( TextureFormat : : Enum ( m_textureFormat ) ) ;
const bool swizzle = TextureFormat : : BGRA8 = = m_textureFormat & & 0 ! = ( m_flags & BGFX_TEXTURE_COMPUTE_WRITE ) ;
uint32_t blockWidth = 1 ;
uint32_t blockHeight = 1 ;
if ( convert & & compressed )
{
blockWidth = blockInfo . blockWidth ;
blockHeight = blockInfo . blockHeight ;
}
const bool bufferOnly = 0 ! = ( m_flags & BGFX_TEXTURE_RT_BUFFER_ONLY ) ;
const bool computeWrite = 0 ! = ( m_flags & BGFX_TEXTURE_COMPUTE_WRITE ) ;
const bool renderTarget = 0 ! = ( m_flags & BGFX_TEXTURE_RT_MASK ) ;
BX_TRACE ( " Texture %3d: %s (requested: %s), %dx%d%s RT[%c], BO[%c], CW[%c]%s. "
, this - s_renderD3D12 - > m_textures
, getName ( ( TextureFormat : : Enum ) m_textureFormat )
, getName ( ( TextureFormat : : Enum ) m_requestedFormat )
, textureWidth
, textureHeight
, imageContainer . m_cubeMap ? " x6 " : " "
, renderTarget ? ' x ' : ' '
, bufferOnly ? ' x ' : ' '
, computeWrite ? ' x ' : ' '
, swizzle ? " (swizzle BGRA8 -> RGBA8) " : " "
) ;
uint32_t totalSize = 0 ;
for ( uint8_t side = 0 ; side < numSides ; + + side )
{
uint32_t width = textureWidth ;
uint32_t height = textureHeight ;
uint32_t depth = imageContainer . m_depth ;
for ( uint32_t lod = 0 ; lod < numMips ; + + lod )
{
width = bx : : uint32_max ( blockWidth , width ) ;
height = bx : : uint32_max ( blockHeight , height ) ;
depth = bx : : uint32_max ( 1 , depth ) ;
ImageMip mip ;
if ( imageGetRawData ( imageContainer , side , lod + startLod , _mem - > data , _mem - > size , mip ) )
{
if ( convert )
{
const uint32_t pitch = bx : : strideAlign ( width * bpp / 8 , D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ) ;
const uint32_t slice = bx : : strideAlign ( pitch * height , D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT ) ;
uint8_t * temp = ( uint8_t * ) BX_ALLOC ( g_allocator , slice ) ;
imageDecodeToBgra8 ( temp
, mip . m_data
, mip . m_width
, mip . m_height
, pitch , mip . m_format
) ;
srd [ kk ] . pData = temp ;
srd [ kk ] . RowPitch = pitch ;
srd [ kk ] . SlicePitch = slice ;
totalSize + = slice ;
}
else if ( compressed )
{
uint32_t pitch = bx : : strideAlign ( ( mip . m_width / blockInfo . blockWidth ) * mip . m_blockSize , D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ) ;
uint32_t slice = bx : : strideAlign ( ( mip . m_height / blockInfo . blockHeight ) * pitch , D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT ) ;
uint8_t * temp = ( uint8_t * ) BX_ALLOC ( g_allocator , slice ) ;
imageCopy ( mip . m_height / blockInfo . blockHeight
, ( mip . m_width / blockInfo . blockWidth ) * mip . m_blockSize
, mip . m_data
, pitch
, temp
) ;
srd [ kk ] . pData = temp ;
srd [ kk ] . RowPitch = pitch ;
srd [ kk ] . SlicePitch = slice ;
totalSize + = slice ;
}
else
{
const uint32_t pitch = bx : : strideAlign ( mip . m_width * mip . m_bpp / 8 , D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ) ;
const uint32_t slice = bx : : strideAlign ( pitch * mip . m_height , D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT ) ;
uint8_t * temp = ( uint8_t * ) BX_ALLOC ( g_allocator , slice ) ;
imageCopy ( mip . m_height
, mip . m_width * mip . m_bpp / 8
, mip . m_data
, pitch
, temp
) ;
srd [ kk ] . pData = temp ;
srd [ kk ] . RowPitch = pitch ;
srd [ kk ] . SlicePitch = slice ;
totalSize + = slice ;
}
if ( swizzle )
{
// imageSwizzleBgra8(width, height, mip.m_width*4, data, temp);
}
srd [ kk ] . SlicePitch = mip . m_height * srd [ kk ] . RowPitch ;
+ + kk ;
}
else
{
const uint32_t pitch = bx : : strideAlign ( width * bpp / 8 , D3D12_TEXTURE_DATA_PITCH_ALIGNMENT ) ;
const uint32_t slice = bx : : strideAlign ( pitch * height , D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT ) ;
totalSize + = slice ;
}
width > > = 1 ;
height > > = 1 ;
depth > > = 1 ;
}
}
BX_TRACE ( " texture total size: %d " , totalSize ) ;
const uint32_t msaaQuality = bx : : uint32_satsub ( ( m_flags & BGFX_TEXTURE_RT_MSAA_MASK ) > > BGFX_TEXTURE_RT_MSAA_SHIFT , 1 ) ;
const DXGI_SAMPLE_DESC & msaa = s_msaa [ msaaQuality ] ;
memset ( & m_srvd , 0 , sizeof ( m_srvd ) ) ;
m_srvd . Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING ;
m_srvd . Format = s_textureFormat [ m_textureFormat ] . m_fmtSrv ;
DXGI_FORMAT format = s_textureFormat [ m_textureFormat ] . m_fmt ;
if ( swizzle )
{
format = DXGI_FORMAT_R8G8B8A8_UNORM ;
m_srvd . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
}
m_uavd . Format = m_srvd . Format ;
ID3D12Device * device = s_renderD3D12 - > m_device ;
ID3D12GraphicsCommandList * commandList = s_renderD3D12 - > m_commandList ;
D3D12_RESOURCE_DESC resourceDesc ;
resourceDesc . Alignment = 0 ;
resourceDesc . Width = textureWidth ;
resourceDesc . Height = textureHeight ;
resourceDesc . MipLevels = numMips ;
resourceDesc . Format = format ;
resourceDesc . SampleDesc = msaa ;
resourceDesc . Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN ;
resourceDesc . Flags = D3D12_RESOURCE_FLAG_NONE ;
resourceDesc . DepthOrArraySize = numSides ;
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ;
D3D12_CLEAR_VALUE * clearValue = NULL ;
if ( isDepth ( TextureFormat : : Enum ( m_textureFormat ) ) )
{
resourceDesc . Format = s_textureFormat [ m_textureFormat ] . m_fmt ;
resourceDesc . Flags | = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL ;
state | = D3D12_RESOURCE_STATE_DEPTH_WRITE ;
state & = ~ D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ;
clearValue = ( D3D12_CLEAR_VALUE * ) alloca ( sizeof ( D3D12_CLEAR_VALUE ) ) ;
clearValue - > Format = s_textureFormat [ m_textureFormat ] . m_fmtDsv ;
clearValue - > DepthStencil . Depth = 1.0f ;
clearValue - > DepthStencil . Stencil = 0 ;
}
else if ( renderTarget )
{
clearValue = ( D3D12_CLEAR_VALUE * ) alloca ( sizeof ( D3D12_CLEAR_VALUE ) ) ;
clearValue - > Format = resourceDesc . Format ;
clearValue - > Color [ 0 ] = 0.0f ;
clearValue - > Color [ 1 ] = 0.0f ;
clearValue - > Color [ 2 ] = 0.0f ;
clearValue - > Color [ 3 ] = 0.0f ;
resourceDesc . Flags | = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET ;
}
if ( bufferOnly )
{
resourceDesc . Flags | = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE ;
state & = ~ D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ;
}
if ( computeWrite )
{
resourceDesc . Flags & = ~ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS ;
}
switch ( m_type )
{
case Texture2D :
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
m_srvd . ViewDimension = 1 < msaa . Count ? D3D12_SRV_DIMENSION_TEXTURE2DMS : D3D12_SRV_DIMENSION_TEXTURE2D ;
m_srvd . Texture2D . MostDetailedMip = 0 ;
m_srvd . Texture2D . MipLevels = numMips ;
m_srvd . Texture2D . ResourceMinLODClamp = 0.0f ;
m_uavd . ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D ;
m_uavd . Texture2D . MipSlice = 0 ;
m_uavd . Texture2D . PlaneSlice = 0 ;
break ;
case Texture3D :
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D ;
m_srvd . ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D ;
m_srvd . Texture3D . MostDetailedMip = 0 ;
m_srvd . Texture3D . MipLevels = numMips ;
m_srvd . Texture3D . ResourceMinLODClamp = 0.0f ;
m_uavd . ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D ;
m_uavd . Texture3D . MipSlice = 0 ;
m_uavd . Texture3D . FirstWSlice = 0 ;
m_uavd . Texture3D . WSize = 0 ;
break ;
case TextureCube :
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
m_srvd . ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE ;
m_srvd . TextureCube . MostDetailedMip = 0 ;
m_srvd . TextureCube . MipLevels = numMips ;
m_srvd . TextureCube . ResourceMinLODClamp = 0.0f ;
m_uavd . ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D ;
m_uavd . Texture2D . MipSlice = 0 ;
m_uavd . Texture2D . PlaneSlice = 0 ;
break ;
}
m_ptr = createCommittedResource ( device , HeapProperty : : Default , & resourceDesc , clearValue ) ;
{
uint64_t uploadBufferSize ;
uint32_t * numRows = ( uint32_t * ) alloca ( sizeof ( uint32_t ) * numSrd ) ;
uint64_t * rowSizeInBytes = ( uint64_t * ) alloca ( sizeof ( uint64_t ) * numSrd ) ;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT * layouts = ( D3D12_PLACED_SUBRESOURCE_FOOTPRINT * ) alloca ( sizeof ( D3D12_PLACED_SUBRESOURCE_FOOTPRINT ) * numSrd ) ;
device - > GetCopyableFootprints ( & resourceDesc
, 0
, numSrd
, 0
, layouts
, numRows
, rowSizeInBytes
, & uploadBufferSize
) ;
BX_WARN ( uploadBufferSize = = totalSize , " uploadBufferSize %d (totalSize %d), numRows %d, rowSizeInBytes %d "
, uploadBufferSize
, totalSize
, numRows [ 0 ]
, rowSizeInBytes [ 0 ]
) ;
}
if ( kk ! = 0 )
{
m_staging = createCommittedResource ( device , HeapProperty : : Upload , totalSize ) ;
setState ( commandList , D3D12_RESOURCE_STATE_COPY_DEST ) ;
uint64_t result = UpdateSubresources ( commandList
, m_ptr
, m_staging
, 0
, 0
, numSrd
, srd
) ;
BX_CHECK ( 0 ! = result , " Invalid size " ) ;
BX_TRACE ( " Update subresource % " PRId64 , result ) ;
setState ( commandList , state ) ;
}
else
{
m_staging = NULL ;
setState ( commandList , state ) ;
}
if ( 0 ! = kk )
{
kk = 0 ;
for ( uint8_t side = 0 ; side < numSides ; + + side )
{
for ( uint32_t lod = 0 , num = numMips ; lod < num ; + + lod )
{
BX_FREE ( g_allocator , const_cast < void * > ( srd [ kk ] . pData ) ) ;
+ + kk ;
}
}
}
}
}
void TextureD3D12 : : destroy ( )
{
if ( NULL ! = m_ptr )
{
DX_RELEASE ( m_ptr , 0 ) ;
m_ptr = NULL ;
DX_RELEASE ( m_staging , 0 ) ;
m_staging = NULL ;
}
}
void TextureD3D12 : : update ( ID3D12GraphicsCommandList * _commandList , uint8_t _side , uint8_t _mip , const Rect & _rect , uint16_t _z , uint16_t _depth , uint16_t _pitch , const Memory * _mem )
{
setState ( _commandList , D3D12_RESOURCE_STATE_COPY_DEST ) ;
const uint32_t subres = _mip + ( _side * m_numMips ) ;
const uint32_t bpp = getBitsPerPixel ( TextureFormat : : Enum ( m_textureFormat ) ) ;
const uint32_t rectpitch = _rect . m_width * bpp / 8 ;
const uint32_t srcpitch = UINT16_MAX = = _pitch ? rectpitch : _pitch ;
s_renderD3D12 - > m_cmd . finish ( s_renderD3D12 - > m_cmd . kick ( ) ) ;
s_renderD3D12 - > m_commandList = s_renderD3D12 - > m_cmd . alloc ( ) ;
_commandList = s_renderD3D12 - > m_commandList ;
DX_RELEASE ( m_staging , 0 ) ;
D3D12_RESOURCE_DESC desc = m_ptr - > GetDesc ( ) ;
desc . Height = _rect . m_height ;
uint32_t numRows ;
uint64_t rowPitch ;
uint64_t totalBytes ;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout ;
s_renderD3D12 - > m_device - > GetCopyableFootprints ( & desc
, subres
, 1
, 0
, & layout
, & numRows
, & rowPitch
, & totalBytes
) ;
m_staging = createCommittedResource ( s_renderD3D12 - > m_device , HeapProperty : : Upload , totalBytes ) ;
DX_NAME ( m_staging , " texture %4d: staging, update " , this - s_renderD3D12 - > m_textures ) ;
uint8_t * data ;
DX_CHECK ( m_staging - > Map ( 0 , NULL , ( void * * ) & data ) ) ;
for ( uint32_t ii = 0 , height = _rect . m_height ; ii < height ; + + ii )
{
memcpy ( & data [ ii * rowPitch ] , & _mem - > data [ ii * srcpitch ] , srcpitch ) ;
}
m_staging - > Unmap ( 0 , NULL ) ;
D3D12_BOX box ;
box . left = 0 ;
box . top = 0 ;
box . right = box . left + _rect . m_width ;
box . bottom = box . top + _rect . m_height ;
box . front = _z ;
box . back = _z + _depth ;
D3D12_TEXTURE_COPY_LOCATION dst = { m_ptr , D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX , { subres } } ;
D3D12_TEXTURE_COPY_LOCATION src = { m_staging , D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT , layout } ;
_commandList - > CopyTextureRegion ( & dst , _rect . m_x , _rect . m_y , 0 , & src , & box ) ;
setState ( _commandList , D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE ) ;
}
void TextureD3D12 : : commit ( uint8_t _stage , uint32_t _flags )
{
BX_UNUSED ( _stage , _flags ) ;
}
void TextureD3D12 : : resolve ( )
{
}
void TextureD3D12 : : setState ( ID3D12GraphicsCommandList * _commandList , D3D12_RESOURCE_STATES _state )
{
if ( m_state ! = _state )
{
setResourceBarrier ( _commandList
, m_ptr
, m_state
, _state
) ;
m_state = _state ;
}
}
void FrameBufferD3D12 : : create ( uint8_t _num , const TextureHandle * _handles )
{
m_numTh = _num ;
memcpy ( m_th , _handles , _num * sizeof ( TextureHandle ) ) ;
postReset ( ) ;
}
void FrameBufferD3D12 : : create ( uint16_t /*_denseIdx*/ , void * /*_nwh*/ , uint32_t /*_width*/ , uint32_t /*_height*/ , TextureFormat : : Enum /*_depthFormat*/ )
{
}
void FrameBufferD3D12 : : preReset ( )
{
}
void FrameBufferD3D12 : : postReset ( )
{
if ( m_numTh ! = 0 )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = s_renderD3D12 - > m_rtvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t rtvDescriptorSize = device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) ;
uint32_t fbhIdx = ( uint32_t ) ( this - s_renderD3D12 - > m_frameBuffers ) ;
rtvDescriptor . ptr + = ( BX_COUNTOF ( s_renderD3D12 - > m_backBufferColor ) + fbhIdx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ) * rtvDescriptorSize ;
m_depth . idx = bgfx : : invalidHandle ;
m_num = 0 ;
for ( uint32_t ii = 0 ; ii < m_numTh ; + + ii )
{
TextureHandle handle = m_th [ ii ] ;
if ( isValid ( handle ) )
{
const TextureD3D12 & texture = s_renderD3D12 - > m_textures [ handle . idx ] ;
if ( isDepth ( ( TextureFormat : : Enum ) texture . m_textureFormat ) )
{
BX_CHECK ( ! isValid ( m_depth ) , " " ) ;
m_depth = handle ;
D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = s_renderD3D12 - > m_dsvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t dsvDescriptorSize = device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_DSV ) ;
dsvDescriptor . ptr + = ( 1 + fbhIdx ) * dsvDescriptorSize ;
const ImageBlockInfo & blockInfo = getBlockInfo ( TextureFormat : : Enum ( texture . m_textureFormat ) ) ;
BX_UNUSED ( blockInfo ) ;
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc ;
ZeroMemory ( & dsvDesc , sizeof ( dsvDesc ) ) ;
dsvDesc . Format = s_textureFormat [ texture . m_textureFormat ] . m_fmtDsv ;
dsvDesc . ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D ;
dsvDesc . Flags = D3D12_DSV_FLAG_NONE
// | (blockInfo.depthBits > 0 ? D3D12_DSV_FLAG_READ_ONLY_DEPTH : D3D12_DSV_FLAG_NONE)
// | (blockInfo.stencilBits > 0 ? D3D12_DSV_FLAG_READ_ONLY_STENCIL : D3D12_DSV_FLAG_NONE)
;
device - > CreateDepthStencilView ( texture . m_ptr
, & dsvDesc
, dsvDescriptor
) ;
}
else
{
m_texture [ m_num ] = handle ;
D3D12_CPU_DESCRIPTOR_HANDLE rtv = { rtvDescriptor . ptr + m_num * rtvDescriptorSize } ;
device - > CreateRenderTargetView ( texture . m_ptr
, NULL
, rtv
) ;
m_num + + ;
}
}
}
}
}
uint16_t FrameBufferD3D12 : : destroy ( )
{
m_numTh = 0 ;
m_depth . idx = bgfx : : invalidHandle ;
uint16_t denseIdx = m_denseIdx ;
m_denseIdx = UINT16_MAX ;
return denseIdx ;
}
void FrameBufferD3D12 : : resolve ( )
{
}
void FrameBufferD3D12 : : clear ( ID3D12GraphicsCommandList * _commandList , const Clear & _clear , const float _palette [ ] [ 4 ] , const D3D12_RECT * _rect , uint32_t _num )
{
ID3D12Device * device = s_renderD3D12 - > m_device ;
const uint32_t fbhIdx = ( uint32_t ) ( this - s_renderD3D12 - > m_frameBuffers ) ;
if ( BGFX_CLEAR_COLOR & _clear . m_flags
& & 0 ! = m_num )
{
D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = s_renderD3D12 - > m_rtvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t rtvDescriptorSize = device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ) ;
rtvDescriptor . ptr + = ( BX_COUNTOF ( s_renderD3D12 - > m_backBufferColor ) + fbhIdx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ) * rtvDescriptorSize ;
if ( BGFX_CLEAR_COLOR_USE_PALETTE & _clear . m_flags )
{
for ( uint32_t ii = 0 , num = m_num ; ii < num ; + + ii )
{
uint8_t index = _clear . m_index [ ii ] ;
if ( UINT8_MAX ! = index )
{
D3D12_CPU_DESCRIPTOR_HANDLE rtv = { rtvDescriptor . ptr + ii * rtvDescriptorSize } ;
_commandList - > ClearRenderTargetView ( rtv
, _palette [ index ]
, _num
, _rect
) ;
}
}
}
else
{
float frgba [ 4 ] =
{
_clear . m_index [ 0 ] * 1.0f / 255.0f ,
_clear . m_index [ 1 ] * 1.0f / 255.0f ,
_clear . m_index [ 2 ] * 1.0f / 255.0f ,
_clear . m_index [ 3 ] * 1.0f / 255.0f ,
} ;
for ( uint32_t ii = 0 , num = m_num ; ii < num ; + + ii )
{
D3D12_CPU_DESCRIPTOR_HANDLE rtv = { rtvDescriptor . ptr + ii * rtvDescriptorSize } ;
_commandList - > ClearRenderTargetView ( rtv
, frgba
, _num
, _rect
) ;
}
}
}
if ( isValid ( m_depth )
& & ( BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL ) & _clear . m_flags )
{
D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = s_renderD3D12 - > m_dsvDescriptorHeap - > GetCPUDescriptorHandleForHeapStart ( ) ;
uint32_t dsvDescriptorSize = device - > GetDescriptorHandleIncrementSize ( D3D12_DESCRIPTOR_HEAP_TYPE_DSV ) ;
dsvDescriptor . ptr + = ( 1 + fbhIdx ) * dsvDescriptorSize ;
DWORD flags = 0 ;
flags | = ( _clear . m_flags & BGFX_CLEAR_DEPTH ) ? D3D12_CLEAR_FLAG_DEPTH : 0 ;
flags | = ( _clear . m_flags & BGFX_CLEAR_STENCIL ) ? D3D12_CLEAR_FLAG_STENCIL : 0 ;
_commandList - > ClearDepthStencilView ( dsvDescriptor
, D3D12_CLEAR_FLAGS ( flags )
, _clear . m_depth
, _clear . m_stencil
, _num
, _rect
) ;
}
}
void RendererContextD3D12 : : submit ( Frame * _render , ClearQuad & _clearQuad , TextVideoMemBlitter & _textVideoMemBlitter )
{
// PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), L"rendererSubmit");
updateResolution ( _render - > m_resolution ) ;
int64_t elapsed = - bx : : getHPCounter ( ) ;
int64_t captureElapsed = 0 ;
if ( 0 < _render - > m_iboffset )
{
TransientIndexBuffer * ib = _render - > m_transientIb ;
m_indexBuffers [ ib - > handle . idx ] . update ( m_commandList , 0 , _render - > m_iboffset , ib - > data ) ;
}
if ( 0 < _render - > m_vboffset )
{
TransientVertexBuffer * vb = _render - > m_transientVb ;
m_vertexBuffers [ vb - > handle . idx ] . update ( m_commandList , 0 , _render - > m_vboffset , vb - > data ) ;
}
_render - > sort ( ) ;
RenderDraw currentState ;
currentState . clear ( ) ;
currentState . m_flags = BGFX_STATE_NONE ;
currentState . m_stencil = packStencil ( BGFX_STENCIL_NONE , BGFX_STENCIL_NONE ) ;
_render - > m_hmdInitialized = false ;
const bool hmdEnabled = false ;
ViewState viewState ( _render , hmdEnabled ) ;
viewState . reset ( _render , hmdEnabled ) ;
// bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);
// bool scissorEnabled = false;
// setDebugWireframe(wireframe);
uint16_t programIdx = invalidHandle ;
ID3D12PipelineState * currentPso = NULL ;
SortKey key ;
uint8_t view = 0xff ;
FrameBufferHandle fbh = BGFX_INVALID_HANDLE ;
float alphaRef = 0.0f ;
// const uint64_t pt = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0;
// uint8_t primIndex = uint8_t(pt >> BGFX_STATE_PT_SHIFT);
// PrimInfo prim = s_primInfo[primIndex];
// deviceCtx->IASetPrimitiveTopology(prim.m_type);
bool wasCompute = false ;
bool viewHasScissor = false ;
Rect viewScissorRect ;
viewScissorRect . clear ( ) ;
BX_UNUSED ( alphaRef ) ;
uint32_t statsNumPrimsSubmitted [ BX_COUNTOF ( s_primInfo ) ] = { } ;
uint32_t statsNumPrimsRendered [ BX_COUNTOF ( s_primInfo ) ] = { } ;
uint32_t statsNumInstances [ BX_COUNTOF ( s_primInfo ) ] = { } ;
uint32_t statsNumIndices = 0 ;
uint32_t statsKeyType [ 2 ] = { } ;
m_backBufferColorIdx = m_frame % m_scd . BufferCount ;
m_frame + + ;
const uint64_t f0 = BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_FACTOR , BGFX_STATE_BLEND_FACTOR ) ;
const uint64_t f1 = BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_INV_FACTOR , BGFX_STATE_BLEND_INV_FACTOR ) ;
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle ;
m_scratchBuffer [ m_backBufferColorIdx ] . reset ( gpuHandle ) ;
setResourceBarrier ( m_commandList
, m_backBufferColor [ m_backBufferColorIdx ]
, D3D12_RESOURCE_STATE_PRESENT
, D3D12_RESOURCE_STATE_RENDER_TARGET
) ;
if ( 0 = = ( _render - > m_debug & BGFX_DEBUG_IFH ) )
{
// uint8_t eye = 0;
// uint8_t restartState = 0;
viewState . m_rect = _render - > m_rect [ 0 ] ;
int32_t numItems = _render - > m_num ;
for ( int32_t item = 0 , restartItem = numItems ; item < numItems | | restartItem < numItems ; )
{
const bool isCompute = key . decode ( _render - > m_sortKeys [ item ] , _render - > m_viewRemap ) ;
statsKeyType [ isCompute ] + + ;
const bool viewChanged = 0
| | key . m_view ! = view
| | item = = numItems
;
const RenderItem & renderItem = _render - > m_renderItem [ _render - > m_sortValues [ item ] ] ;
+ + item ;
if ( viewChanged )
{
kick ( ) ;
if ( isCompute )
{
m_commandList - > SetComputeRootSignature ( m_rootSignature ) ;
}
else
{
m_commandList - > SetGraphicsRootSignature ( m_rootSignature ) ;
}
ID3D12DescriptorHeap * heaps [ ] = {
m_samplerAllocator . getHeap ( ) ,
m_scratchBuffer [ m_backBufferColorIdx ] . getHeap ( ) ,
} ;
m_commandList - > SetDescriptorHeaps ( BX_COUNTOF ( heaps ) , heaps ) ;
view = key . m_view ;
programIdx = invalidHandle ;
currentPso = NULL ;
fbh = _render - > m_fb [ view ] ;
setFrameBuffer ( fbh ) ;
viewState . m_rect = _render - > m_rect [ view ] ;
const Rect & rect = _render - > m_rect [ view ] ;
const Rect & scissorRect = _render - > m_scissor [ view ] ;
viewHasScissor = ! scissorRect . isZero ( ) ;
viewScissorRect = viewHasScissor ? scissorRect : rect ;
D3D12_VIEWPORT vp ;
vp . TopLeftX = rect . m_x ;
vp . TopLeftY = rect . m_y ;
vp . Width = rect . m_width ;
vp . Height = rect . m_height ;
vp . MinDepth = 0.0f ;
vp . MaxDepth = 1.0f ;
m_commandList - > RSSetViewports ( 1 , & vp ) ;
D3D12_RECT rc ;
rc . left = viewScissorRect . m_x ;
rc . top = viewScissorRect . m_y ;
rc . right = viewScissorRect . m_x + viewScissorRect . m_width ;
rc . bottom = viewScissorRect . m_y + viewScissorRect . m_height ;
m_commandList - > RSSetScissorRects ( 1 , & rc ) ;
Clear & clear = _render - > m_clear [ view ] ;
if ( BGFX_CLEAR_NONE ! = clear . m_flags )
{
Rect clearRect = rect ;
clearRect . intersect ( rect , viewScissorRect ) ;
clearQuad ( _clearQuad , clearRect , clear , _render - > m_clearColor ) ;
}
}
if ( isCompute )
{
if ( ! wasCompute )
{
wasCompute = true ;
}
const RenderCompute & compute = renderItem . compute ;
bool programChanged = false ;
bool constantsChanged = compute . m_constBegin < compute . m_constEnd ;
rendererUpdateUniforms ( this , _render - > m_constantBuffer , compute . m_constBegin , compute . m_constEnd ) ;
if ( key . m_program ! = programIdx )
{
programIdx = key . m_program ;
ProgramD3D12 & program = m_program [ key . m_program ] ;
m_currentProgram = & program ;
programChanged =
constantsChanged = true ;
}
if ( invalidHandle ! = programIdx )
{
ProgramD3D12 & program = m_program [ programIdx ] ;
if ( constantsChanged )
{
ConstantBuffer * vcb = program . m_vsh - > m_constantBuffer ;
if ( NULL ! = vcb )
{
commit ( * vcb ) ;
}
}
viewState . setPredefined < 4 > ( this , view , 0 , program , _render , compute ) ;
if ( constantsChanged
| | program . m_numPredefined > 0 )
{
commitShaderConstants ( gpuHandle ) ;
}
}
if ( programChanged )
{
ID3D12PipelineState * pso = getPipelineState ( programIdx ) ;
m_commandList - > SetPipelineState ( pso ) ;
}
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle [ BGFX_MAX_COMPUTE_BINDINGS ] = { } ;
uint32_t samplerFlags [ BGFX_MAX_COMPUTE_BINDINGS ] = { } ;
for ( uint32_t ii = 0 ; ii < BGFX_MAX_COMPUTE_BINDINGS ; + + ii )
{
const Binding & bind = compute . m_bind [ ii ] ;
if ( invalidHandle ! = bind . m_idx )
{
switch ( bind . m_type )
{
case Binding : : Image :
{
TextureD3D12 & texture = m_textures [ bind . m_idx ] ;
if ( Access : : Read ! = bind . m_un . m_compute . m_access )
{
m_scratchBuffer [ m_backBufferColorIdx ] . allocUav ( srvHandle [ ii ] , texture ) ;
}
else
{
m_scratchBuffer [ m_backBufferColorIdx ] . alloc ( srvHandle [ ii ] , texture ) ;
}
}
break ;
case Binding : : IndexBuffer :
case Binding : : VertexBuffer :
{
BufferD3D12 & buffer = Binding : : IndexBuffer = = bind . m_type
? m_indexBuffers [ bind . m_idx ]
: m_vertexBuffers [ bind . m_idx ]
;
if ( Access : : Read ! = bind . m_un . m_compute . m_access )
{
m_scratchBuffer [ m_backBufferColorIdx ] . allocUav ( srvHandle [ ii ] , buffer ) ;
}
else
{
m_scratchBuffer [ m_backBufferColorIdx ] . alloc ( srvHandle [ ii ] , buffer ) ;
}
}
break ;
}
}
}
uint16_t samplerStateIdx = getSamplerState ( samplerFlags , BGFX_MAX_COMPUTE_BINDINGS ) ;
m_commandList - > SetComputeRootDescriptorTable ( Rdt : : Sampler , m_samplerAllocator . get ( samplerStateIdx ) ) ;
m_commandList - > SetComputeRootDescriptorTable ( Rdt : : SRV , srvHandle [ 0 ] ) ;
m_commandList - > SetComputeRootDescriptorTable ( Rdt : : CBV , gpuHandle ) ;
m_commandList - > SetComputeRootDescriptorTable ( Rdt : : UAV , srvHandle [ 0 ] ) ;
if ( isValid ( compute . m_indirectBuffer ) )
{
const VertexBufferD3D12 & vb = m_vertexBuffers [ compute . m_indirectBuffer . idx ] ;
uint32_t numDrawIndirect = UINT16_MAX = = compute . m_numIndirect
? vb . m_size / BGFX_CONFIG_DRAW_INDIRECT_STRIDE
: compute . m_numIndirect
;
uint32_t args = compute . m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
for ( uint32_t ii = 0 ; ii < numDrawIndirect ; + + ii )
{
// deviceCtx->DispatchIndirect(ptr, args);
args + = BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
}
}
else
{
m_commandList - > Dispatch ( compute . m_numX , compute . m_numY , compute . m_numZ ) ;
}
continue ;
}
// bool resetState = viewChanged || wasCompute;
if ( wasCompute )
{
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PIX ) )
{
// wchar_t* viewNameW = s_viewNameW[view];
// viewNameW[3] = L' ';
// PIX_ENDEVENT();
// PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), viewNameW);
}
wasCompute = false ;
programIdx = invalidHandle ;
m_currentProgram = NULL ;
m_commandList - > SetGraphicsRootSignature ( m_rootSignature ) ;
ID3D12DescriptorHeap * heaps [ ] = {
m_samplerAllocator . getHeap ( ) ,
m_scratchBuffer [ m_backBufferColorIdx ] . getHeap ( ) ,
} ;
m_commandList - > SetDescriptorHeaps ( BX_COUNTOF ( heaps ) , heaps ) ;
// invalidateCompute();
}
const RenderDraw & draw = renderItem . draw ;
bool constantsChanged = draw . m_constBegin < draw . m_constEnd ;
rendererUpdateUniforms ( this , _render - > m_constantBuffer , draw . m_constBegin , draw . m_constEnd ) ;
if ( isValid ( draw . m_vertexBuffer ) )
{
bool programChanged = false ;
if ( key . m_program ! = programIdx )
{
programIdx = key . m_program ;
if ( invalidHandle = = programIdx )
{
m_currentProgram = NULL ;
}
else
{
ProgramD3D12 & program = m_program [ programIdx ] ;
m_currentProgram = & program ;
}
programChanged =
constantsChanged = true ;
}
if ( invalidHandle ! = programIdx )
{
ProgramD3D12 & program = m_program [ programIdx ] ;
if ( constantsChanged )
{
ConstantBuffer * vcb = program . m_vsh - > m_constantBuffer ;
if ( NULL ! = vcb )
{
commit ( * vcb ) ;
}
ConstantBuffer * fcb = program . m_fsh - > m_constantBuffer ;
if ( NULL ! = fcb )
{
commit ( * fcb ) ;
}
}
viewState . setPredefined < 4 > ( this , view , 0 , program , _render , draw ) ;
if ( constantsChanged
| | program . m_numPredefined > 0 )
{
commitShaderConstants ( gpuHandle ) ;
}
}
const VertexBufferD3D12 & vb = m_vertexBuffers [ draw . m_vertexBuffer . idx ] ;
uint16_t declIdx = ! isValid ( vb . m_decl ) ? draw . m_vertexDecl . idx : vb . m_decl . idx ;
const VertexDecl & vertexDecl = m_vertexDecls [ declIdx ] ;
const uint64_t state = draw . m_flags ;
2015-07-29 19:50:25 -07:00
ID3D12PipelineState * pso =
2015-07-29 19:38:17 -07:00
getPipelineState ( state
, draw . m_stencil
, declIdx
, programIdx
, draw . m_instanceDataStride / 16
) ;
if ( pso ! = currentPso )
{
currentPso = pso ;
m_commandList - > SetPipelineState ( pso ) ;
}
const uint32_t fstencil = unpackStencil ( 0 , draw . m_stencil ) ;
const uint32_t ref = ( fstencil & BGFX_STENCIL_FUNC_REF_MASK ) > > BGFX_STENCIL_FUNC_REF_SHIFT ;
m_commandList - > OMSetStencilRef ( ref ) ;
bool hasFactor = 0
| | f0 = = ( state & f0 )
| | f1 = = ( state & f1 )
;
if ( hasFactor )
{
float blendFactor [ 4 ] = { 1.0f , 1.0f , 1.0f , 1.0f } ;
blendFactor [ 0 ] = ( ( draw . m_rgba > > 24 ) ) / 255.0f ;
blendFactor [ 1 ] = ( ( draw . m_rgba > > 16 ) & 0xff ) / 255.0f ;
blendFactor [ 2 ] = ( ( draw . m_rgba > > 8 ) & 0xff ) / 255.0f ;
blendFactor [ 3 ] = ( ( draw . m_rgba ) & 0xff ) / 255.0f ;
m_commandList - > OMSetBlendFactor ( blendFactor ) ;
}
D3D12_GPU_DESCRIPTOR_HANDLE srvHandle [ BGFX_CONFIG_MAX_TEXTURE_SAMPLERS ] ;
uint32_t samplerFlags [ BGFX_CONFIG_MAX_TEXTURE_SAMPLERS ] ;
{
srvHandle [ 0 ] . ptr = 0 ;
for ( uint32_t stage = 0 ; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS ; + + stage )
{
const Binding & sampler = draw . m_bind [ stage ] ;
if ( invalidHandle ! = sampler . m_idx )
{
TextureD3D12 & texture = m_textures [ sampler . m_idx ] ;
m_scratchBuffer [ m_backBufferColorIdx ] . alloc ( srvHandle [ stage ] , texture ) ;
samplerFlags [ stage ] = ( 0 = = ( BGFX_SAMPLER_DEFAULT_FLAGS & sampler . m_un . m_draw . m_flags )
? sampler . m_un . m_draw . m_flags
: texture . m_flags
) & BGFX_TEXTURE_SAMPLER_BITS_MASK
;
}
else
{
memcpy ( & srvHandle [ stage ] , & srvHandle [ 0 ] , sizeof ( D3D12_GPU_DESCRIPTOR_HANDLE ) ) ;
samplerFlags [ stage ] = 0 ;
}
}
}
uint16_t samplerStateIdx = getSamplerState ( samplerFlags ) ;
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : Sampler , m_samplerAllocator . get ( samplerStateIdx ) ) ;
if ( srvHandle [ 0 ] . ptr ! = 0 )
{
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : SRV , srvHandle [ 0 ] ) ;
}
m_commandList - > SetGraphicsRootDescriptorTable ( Rdt : : CBV , gpuHandle ) ;
uint32_t numVertices = draw . m_numVertices ;
if ( UINT32_MAX = = numVertices )
{
numVertices = vb . m_size / vertexDecl . m_stride ;
}
D3D12_VERTEX_BUFFER_VIEW vbView [ 2 ] ;
uint32_t numVertexBuffers = 1 ;
vbView [ 0 ] . BufferLocation = vb . m_ptr - > GetGPUVirtualAddress ( ) ;
vbView [ 0 ] . StrideInBytes = vertexDecl . m_stride ;
vbView [ 0 ] . SizeInBytes = vb . m_size ;
if ( isValid ( draw . m_instanceDataBuffer ) )
{
const VertexBufferD3D12 & inst = m_vertexBuffers [ draw . m_instanceDataBuffer . idx ] ;
vbView [ 1 ] . BufferLocation = inst . m_ptr - > GetGPUVirtualAddress ( ) + draw . m_instanceDataOffset ;
vbView [ 1 ] . StrideInBytes = draw . m_instanceDataStride ;
vbView [ 1 ] . SizeInBytes = draw . m_numInstances * draw . m_instanceDataStride ;
+ + numVertexBuffers ;
}
m_commandList - > IASetVertexBuffers ( 0 , numVertexBuffers , vbView ) ;
uint32_t numIndices = 0 ;
uint32_t numPrimsSubmitted = 0 ;
uint32_t numInstances = 0 ;
uint32_t numPrimsRendered = 0 ;
const uint64_t pt = draw . m_flags & BGFX_STATE_PT_MASK ;
uint8_t primIdx = uint8_t ( pt > > BGFX_STATE_PT_SHIFT ) ;
PrimInfo prim = s_primInfo [ primIdx ] ;
m_commandList - > IASetPrimitiveTopology ( prim . m_toplogy ) ;
if ( isValid ( draw . m_indexBuffer ) )
{
const BufferD3D12 & ib = m_indexBuffers [ draw . m_indexBuffer . idx ] ;
const bool hasIndex16 = 0 = = ( ib . m_flags & BGFX_BUFFER_INDEX32 ) ;
D3D12_INDEX_BUFFER_VIEW ibv ;
ibv . Format = hasIndex16
? DXGI_FORMAT_R16_UINT
: DXGI_FORMAT_R32_UINT
;
ibv . BufferLocation = ib . m_ptr - > GetGPUVirtualAddress ( ) ;
ibv . SizeInBytes = ib . m_size ;
m_commandList - > IASetIndexBuffer ( & ibv ) ;
if ( UINT32_MAX = = draw . m_numIndices )
{
const uint32_t indexSize = hasIndex16 ? 2 : 4 ;
numIndices = ib . m_size / indexSize ;
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
m_commandList - > DrawIndexedInstanced ( numIndices
, draw . m_numInstances
, draw . m_startIndex
, draw . m_startVertex
, 0
) ;
}
else if ( prim . m_min < = draw . m_numIndices )
{
numIndices = draw . m_numIndices ;
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
m_commandList - > DrawIndexedInstanced ( numIndices
, draw . m_numInstances
, draw . m_startIndex
, draw . m_startVertex
, 0
) ;
}
}
else
{
numPrimsSubmitted = numVertices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
m_commandList - > DrawInstanced ( numVertices
, draw . m_numInstances
, draw . m_startVertex
, 0
) ;
}
statsNumPrimsSubmitted [ primIdx ] + = numPrimsSubmitted ;
statsNumPrimsRendered [ primIdx ] + = numPrimsRendered ;
statsNumInstances [ primIdx ] + = numInstances ;
statsNumIndices + = numIndices ;
}
}
}
int64_t now = bx : : getHPCounter ( ) ;
elapsed + = now ;
static int64_t last = now ;
int64_t frameTime = now - last ;
last = now ;
static int64_t min = frameTime ;
static int64_t max = frameTime ;
min = min > frameTime ? frameTime : min ;
max = max < frameTime ? frameTime : max ;
if ( _render - > m_debug & ( BGFX_DEBUG_IFH | BGFX_DEBUG_STATS ) )
{
// PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugstats");
TextVideoMem & tvm = m_textVideoMem ;
static int64_t next = now ;
if ( now > = next )
{
next = now + bx : : getHPFrequency ( ) ;
double freq = double ( bx : : getHPFrequency ( ) ) ;
double toMs = 1000.0 / freq ;
tvm . clear ( ) ;
uint16_t pos = 0 ;
tvm . printf ( 0 , pos + + , BGFX_CONFIG_DEBUG ? 0x89 : 0x8f
, " %s / " BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME " "
, getRendererName ( )
) ;
const DXGI_ADAPTER_DESC & desc = m_adapterDesc ;
char description [ BX_COUNTOF ( desc . Description ) ] ;
wcstombs ( description , desc . Description , BX_COUNTOF ( desc . Description ) ) ;
tvm . printf ( 0 , pos + + , 0x0f , " Device: %s " , description ) ;
char dedicatedVideo [ 16 ] ;
bx : : prettify ( dedicatedVideo , BX_COUNTOF ( dedicatedVideo ) , desc . DedicatedVideoMemory ) ;
char dedicatedSystem [ 16 ] ;
bx : : prettify ( dedicatedSystem , BX_COUNTOF ( dedicatedSystem ) , desc . DedicatedSystemMemory ) ;
char sharedSystem [ 16 ] ;
bx : : prettify ( sharedSystem , BX_COUNTOF ( sharedSystem ) , desc . SharedSystemMemory ) ;
tvm . printf ( 0 , pos + + , 0x0f , " Memory: %s (video), %s (system), %s (shared) "
, dedicatedVideo
, dedicatedSystem
, sharedSystem
) ;
pos = 10 ;
tvm . printf ( 10 , pos + + , 0x8e , " Frame: %7.3f, % 7.3f \x1f , % 7.3f \x1e [ms] / % 6.2f FPS "
, double ( frameTime ) * toMs
, double ( min ) * toMs
, double ( max ) * toMs
, freq / frameTime
) ;
char hmd [ 16 ] ;
bx : : snprintf ( hmd , BX_COUNTOF ( hmd ) , " , [%c] HMD " , hmdEnabled ? ' \xfe ' : ' ' ) ;
const uint32_t msaa = ( m_resolution . m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ;
tvm . printf ( 10 , pos + + , 0x8e , " Reset flags: [%c] vsync, [%c] MSAAx%d%s, [%c] MaxAnisotropy "
, ! ! ( m_resolution . m_flags & BGFX_RESET_VSYNC ) ? ' \xfe ' : ' '
, 0 ! = msaa ? ' \xfe ' : ' '
, 1 < < msaa
, " , no-HMD "
, ! ! ( m_resolution . m_flags & BGFX_RESET_MAXANISOTROPY ) ? ' \xfe ' : ' '
) ;
double elapsedCpuMs = double ( elapsed ) * toMs ;
tvm . printf ( 10 , pos + + , 0x8e , " Submitted: %4d (draw %4d, compute %4d) / CPU %3.4f [ms] "
, _render - > m_num
, statsKeyType [ 0 ]
, statsKeyType [ 1 ]
, elapsedCpuMs
) ;
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( s_primName ) ; + + ii )
{
tvm . printf ( 10 , pos + + , 0x8e , " %9s: %7d (#inst: %5d), submitted: %7d "
, s_primName [ ii ]
, statsNumPrimsRendered [ ii ]
, statsNumInstances [ ii ]
, statsNumPrimsSubmitted [ ii ]
) ;
}
// if (NULL != m_renderdocdll)
// {
// tvm.printf(tvm.m_width-27, 0, 0x1f, " [F11 - RenderDoc capture] ");
// }
tvm . printf ( 10 , pos + + , 0x8e , " Indices: %7d " , statsNumIndices ) ;
tvm . printf ( 10 , pos + + , 0x8e , " DVB size: %7d " , _render - > m_vboffset ) ;
tvm . printf ( 10 , pos + + , 0x8e , " DIB size: %7d " , _render - > m_iboffset ) ;
pos + + ;
tvm . printf ( 10 , pos + + , 0x8e , " State cache: " ) ;
tvm . printf ( 10 , pos + + , 0x8e , " PSO | Sampler | Queued " ) ;
tvm . printf ( 10 , pos + + , 0x8e , " %6d | %6d | %6d "
, m_pipelineStateCache . getCount ( )
, m_samplerStateCache . getCount ( )
, m_cmd . m_control . available ( )
) ;
pos + + ;
double captureMs = double ( captureElapsed ) * toMs ;
tvm . printf ( 10 , pos + + , 0x8e , " Capture: %3.4f [ms] " , captureMs ) ;
uint8_t attr [ 2 ] = { 0x89 , 0x8a } ;
uint8_t attrIndex = _render - > m_waitSubmit < _render - > m_waitRender ;
tvm . printf ( 10 , pos + + , attr [ attrIndex & 1 ] , " Submit wait: %3.4f [ms] " , _render - > m_waitSubmit * toMs ) ;
tvm . printf ( 10 , pos + + , attr [ ( attrIndex + 1 ) & 1 ] , " Render wait: %3.4f [ms] " , _render - > m_waitRender * toMs ) ;
min = frameTime ;
max = frameTime ;
}
blit ( this , _textVideoMemBlitter , tvm ) ;
// PIX_ENDEVENT();
}
else if ( _render - > m_debug & BGFX_DEBUG_TEXT )
{
// PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugtext");
blit ( this , _textVideoMemBlitter , _render - > m_textVideoMem ) ;
// PIX_ENDEVENT();
}
setResourceBarrier ( m_commandList
, m_backBufferColor [ m_backBufferColorIdx ]
, D3D12_RESOURCE_STATE_RENDER_TARGET
, D3D12_RESOURCE_STATE_PRESENT
) ;
m_backBufferColorFence [ m_backBufferColorIdx ] = kick ( ) ;
}
} /* namespace d3d12 */ } // namespace bgfx
2015-02-08 11:02:39 -08:00
# else
2015-07-29 19:50:25 -07:00
namespace bgfx { namespace d3d12
2015-01-24 22:19:42 -08:00
{
2015-03-21 22:11:59 -07:00
RendererContextI * rendererCreate ( )
2015-01-24 22:19:42 -08:00
{
return NULL ;
}
2015-03-21 22:11:59 -07:00
void rendererDestroy ( )
2015-01-24 22:19:42 -08:00
{
}
2015-03-21 22:11:59 -07:00
} /* namespace d3d12 */ } // namespace bgfx
2015-02-08 11:02:39 -08:00
# endif // BGFX_CONFIG_RENDERER_DIRECT3D12