<NME> renderer_d3d12.cpp <BEF> /* * Copyright 2011-2022 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "bgfx_p.h" #if BGFX_CONFIG_RENDERER_DIRECT3D12 # include "renderer_d3d12.h" #if !BX_PLATFORM_WINDOWS && !BX_PLATFORM_LINUX # include <inspectable.h> # if BX_PLATFORM_WINRT # include <windows.ui.xaml.media.dxinterop.h> # endif // BX_PLATFORM_WINRT #endif // !BX_PLATFORM_WINDOWS #if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) PFN_PIX_GET_THREAD_INFO bgfx_PIXGetThreadInfo; PFN_PIX_EVENTS_REPLACE_BLOCK bgfx_PIXEventsReplaceBlock; #endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) namespace bgfx { namespace d3d12 { static char s_viewName[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME]; inline void setViewType(ViewId _view, const bx::StringView _str) { if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION || BGFX_CONFIG_PROFILER) ) { bx::memCopy(&s_viewName[_view][3], _str.getPtr(), _str.getLength() ); } } struct PrimInfo { D3D_PRIMITIVE_TOPOLOGY m_topology; D3D12_PRIMITIVE_TOPOLOGY_TYPE m_topologyType; uint32_t m_min; uint32_t m_div; uint32_t m_sub; }; 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_LINESTRIP, D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, 2, 1, 1 }, { D3D_PRIMITIVE_TOPOLOGY_POINTLIST, D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, 1, 1, 0 }, { D3D_PRIMITIVE_TOPOLOGY_UNDEFINED, D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED, 0, 0, 0 }, }; BX_STATIC_ASSERT(Topology::Count == BX_COUNTOF(s_primInfo)-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, D3D12_TEXTURE_ADDRESS_MODE_BORDER, }; /* * 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; DXGI_FORMAT m_fmtSrgb; uint32_t m_mapping; }; static const TextureFormatInfo s_textureFormat[] = { #define $0 D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0 #define $1 D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1 #define $R D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0 #define $G D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1 #define $B D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2 #define $A D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3 { DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC1_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC1 { DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC2_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC2 { DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC3_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC3 { DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC4 { DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC5 { DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC6H { DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC7_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BC7 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ETC1 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ETC2 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ETC2A { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ETC2A1 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC12 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC14 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC12A { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC14A { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC22 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // PTC24 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ATC { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ATCE { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ATCI { DXGI_FORMAT_ASTC_4X4_UNORM, DXGI_FORMAT_ASTC_4X4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_4X4_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC4x4 { DXGI_FORMAT_ASTC_5X4_UNORM, DXGI_FORMAT_ASTC_5X4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_5X4_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC5x4 { DXGI_FORMAT_ASTC_5X5_UNORM, DXGI_FORMAT_ASTC_5X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_5X5_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC5x5 { DXGI_FORMAT_ASTC_6X5_UNORM, DXGI_FORMAT_ASTC_6X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_6X5_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC6x5 { DXGI_FORMAT_ASTC_6X6_UNORM, DXGI_FORMAT_ASTC_6X6_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_6X6_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC6x6 { DXGI_FORMAT_ASTC_8X5_UNORM, DXGI_FORMAT_ASTC_8X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X5_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC8x5 { DXGI_FORMAT_ASTC_8X6_UNORM, DXGI_FORMAT_ASTC_8X6_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X6_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC8x6 { DXGI_FORMAT_ASTC_8X8_UNORM, DXGI_FORMAT_ASTC_8X8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC8x8 { DXGI_FORMAT_ASTC_10X5_UNORM, DXGI_FORMAT_ASTC_10X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_10X5_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC10x5 { DXGI_FORMAT_ASTC_10X6_UNORM, DXGI_FORMAT_ASTC_10X6_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_10X6_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC10x6 { DXGI_FORMAT_ASTC_10X8_UNORM, DXGI_FORMAT_ASTC_10X8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_10X8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC10x8 { DXGI_FORMAT_ASTC_10X10_UNORM, DXGI_FORMAT_ASTC_10X10_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_10X10_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC10x10 { DXGI_FORMAT_ASTC_12X10_UNORM, DXGI_FORMAT_ASTC_12X10_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_12X10_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC12x10 { DXGI_FORMAT_ASTC_12X12_UNORM, DXGI_FORMAT_ASTC_12X12_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_12X12_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // ASTC12x12 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // Unknown { DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R1 { DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // A8 { DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R8 { DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R8I { DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R8U { DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R8S { DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R16 { DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R16I { DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R16U { DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R16F { DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R16S { DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R32I { DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R32U { DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // R32F { DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG8 { DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG8I { DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG8U { DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG8S { DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG16 { DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG16I { DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG16U { DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG16F { DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG16S { DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG32I { DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG32U { DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG32F { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB8 { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB8I { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB8U { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB8S { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB9E5F { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BGRA8 { DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA8 { DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA8I { DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA8U { DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA8S { DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA16 { DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA16I { DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA16U { DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA16F { DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA16S { DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA32I { DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA32U { DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGBA32F { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // B5G6R5 { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $1) }, // R5G6B5 { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BGRA4 { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $A) }, // RGBA4 { DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // BGR5A1 { DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $A) }, // RGB5A1 { DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RGB10A2 { DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // RG11B10F { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // UnknownDepth { DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D16 { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D24 { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D24S8 { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D32 { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D16F { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D24F { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D32F { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING }, // D0S8 #undef $0 #undef $1 #undef $R #undef $G #undef $B #undef $A }; 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 }, { "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UINT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 3, 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] = { { // Uint8 { 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 }, }, { // Uint10 { DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UNORM }, { DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UNORM }, { DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UNORM }, { DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UNORM }, }, { // Int16 { 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 }, }, { // Half { 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 }, }, { // 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* fillVertexLayout(uint8_t _stream, D3D12_INPUT_ELEMENT_DESC* _out, const VertexLayout& _layout) { D3D12_INPUT_ELEMENT_DESC* elem = _out; for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { if (UINT16_MAX != _layout.m_attributes[attr]) { bx::memCopy(elem, &s_attrib[attr], sizeof(D3D12_INPUT_ELEMENT_DESC) ); elem->InputSlot = _stream; if (0 == _layout.m_attributes[attr]) { elem->AlignedByteOffset = 0; } else { uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _layout.decode(Attrib::Enum(attr), num, type, normalized, asInt); elem->Format = s_attribType[type][num-1][normalized]; elem->AlignedByteOffset = _layout.m_offset[attr]; } ++elem; } } return elem; } void setResourceBarrier(ID3D12GraphicsCommandList* _commandList, const 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 = const_cast<ID3D12Resource*>(_resource); barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Transition.StateBefore = _stateBefore; barrier.Transition.StateAfter = _stateAfter; _commandList->ResourceBarrier(1, &barrier); } BX_PRAGMA_DIAGNOSTIC_PUSH(); BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunused-const-variable"); BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration"); static const GUID IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } }; static const GUID IID_ID3D12CommandQueue = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } }; static const GUID IID_ID3D12CommandSignature = { 0xc36a797c, 0xec80, 0x4f0a, { 0x89, 0x85, 0xa7, 0xb2, 0x47, 0x50, 0x82, 0xd1 } }; static const GUID IID_ID3D12Debug = { 0x344488b7, 0x6846, 0x474b, { 0xb9, 0x89, 0xf0, 0x27, 0x44, 0x82, 0x45, 0xe0 } }; static const GUID IID_ID3D12Debug1 = { 0xaffaa4ca, 0x63fe, 0x4d8e, { 0xb8, 0xad, 0x15, 0x90, 0x00, 0xaf, 0x43, 0x04 } }; static const GUID IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { 0x90, 0xf7, 0x12, 0x7b, 0xb7, 0x63, 0xfa, 0x51 } }; static const GUID IID_ID3D12Device = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } }; static const GUID IID_ID3D12Device1 = { 0x77acce80, 0x638e, 0x4e65, { 0x88, 0x95, 0xc1, 0xf2, 0x33, 0x86, 0x86, 0x3e } }; static const GUID IID_ID3D12Device2 = { 0x30baa41e, 0xb15b, 0x475c, { 0xa0, 0xbb, 0x1a, 0xf5, 0xc5, 0xb6, 0x43, 0x28 } }; static const GUID IID_ID3D12Device3 = { 0x81dadc15, 0x2bad, 0x4392, { 0x93, 0xc5, 0x10, 0x13, 0x45, 0xc4, 0xaa, 0x98 } }; static const GUID IID_ID3D12Device4 = { 0xe865df17, 0xa9ee, 0x46f9, { 0xa4, 0x63, 0x30, 0x98, 0x31, 0x5a, 0xa2, 0xe5 } }; static const GUID IID_ID3D12Device5 = { 0x8b4f173b, 0x2fea, 0x4b80, { 0x8f, 0x58, 0x43, 0x07, 0x19, 0x1a, 0xb9, 0x5d } }; static const GUID IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } }; static const GUID IID_ID3D12GraphicsCommandList = { 0x5b160d0f, 0xac1b, 0x4185, { 0x8b, 0xa8, 0xb3, 0xae, 0x42, 0xa5, 0xa4, 0x55 } }; static const GUID IID_ID3D12GraphicsCommandList1 = { 0x553103fb, 0x1fe7, 0x4557, { 0xbb, 0x38, 0x94, 0x6d, 0x7d, 0x0e, 0x7c, 0xa7 } }; static const GUID IID_ID3D12GraphicsCommandList2 = { 0x38C3E585, 0xFF17, 0x412C, { 0x91, 0x50, 0x4F, 0xC6, 0xF9, 0xD7, 0x2A, 0x28 } }; static const GUID IID_ID3D12GraphicsCommandList3 = { 0x6FDA83A7, 0xB84C, 0x4E38, { 0x9A, 0xC8, 0xC7, 0xBD, 0x22, 0x01, 0x6B, 0x3D } }; static const GUID IID_ID3D12GraphicsCommandList4 = { 0x8754318e, 0xd3a9, 0x4541, { 0x98, 0xcf, 0x64, 0x5b, 0x50, 0xdc, 0x48, 0x74 } }; static const GUID IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } }; static const GUID IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } }; static const GUID IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } }; static const GUID IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } }; static const GUID IID_ID3D12QueryHeap = { 0x0d9658ae, 0xed45, 0x469e, { 0xa6, 0x1d, 0x97, 0x0e, 0xc5, 0x83, 0xca, 0xb4 } }; BX_PRAGMA_DIAGNOSTIC_POP(); static const GUID s_d3dDeviceIIDs[] = { IID_ID3D12Device5, IID_ID3D12Device4, IID_ID3D12Device3, IID_ID3D12Device2, IID_ID3D12Device1, }; struct HeapProperty { enum Enum { Default, Texture, Upload, ReadBack, Count }; D3D12_HEAP_PROPERTIES m_properties; D3D12_RESOURCE_STATES m_state; }; static HeapProperty s_heapProperties[] = { { { D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COMMON }, { { D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COMMON }, { { D3D12_HEAP_TYPE_UPLOAD, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_GENERIC_READ }, { { D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COPY_DEST }, }; BX_STATIC_ASSERT(BX_COUNTOF(s_heapProperties) == HeapProperty::Count); static inline D3D12_HEAP_PROPERTIES ID3D12DeviceGetCustomHeapProperties(ID3D12Device *device, uint32_t nodeMask, D3D12_HEAP_TYPE heapType) { #if BX_COMPILER_MSVC return device->GetCustomHeapProperties(nodeMask, heapType); #else D3D12_HEAP_PROPERTIES ret; device->GetCustomHeapProperties(&ret, nodeMask, heapType); return ret; #endif // BX_COMPILER_MSVC } static void initHeapProperties(ID3D12Device* _device, D3D12_HEAP_PROPERTIES& _properties) { if (D3D12_HEAP_TYPE_CUSTOM != _properties.Type) { _properties = ID3D12DeviceGetCustomHeapProperties(_device, 1, _properties.Type); } } static void initHeapProperties(ID3D12Device* _device) { #if BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS initHeapProperties(_device, s_heapProperties[HeapProperty::Default ].m_properties); initHeapProperties(_device, s_heapProperties[HeapProperty::Texture ].m_properties); initHeapProperties(_device, s_heapProperties[HeapProperty::Upload ].m_properties); initHeapProperties(_device, s_heapProperties[HeapProperty::ReadBack].m_properties); #else BX_UNUSED(_device); #endif // BX_PLATFORM_WINDOWS } ID3D12Resource* createCommittedResource(ID3D12Device* _device, HeapProperty::Enum _heapProperty, const D3D12_RESOURCE_DESC* _resourceDesc, const D3D12_CLEAR_VALUE* _clearValue, bool _memSet = false) { const HeapProperty& heapProperty = s_heapProperties[_heapProperty]; ID3D12Resource* resource; DX_CHECK(_device->CreateCommittedResource(&heapProperty.m_properties , D3D12_HEAP_FLAG_NONE , _resourceDesc , heapProperty.m_state , _clearValue , IID_ID3D12Resource , (void**)&resource ) ); BX_WARN(NULL != resource, "CreateCommittedResource failed (size: %d). Out of memory?" , _resourceDesc->Width ); if (BX_ENABLED(BX_PLATFORM_XBOXONE) && _memSet) { void* ptr; DX_CHECK(resource->Map(0, NULL, &ptr) ); D3D12_RESOURCE_ALLOCATION_INFO rai; #if BX_COMPILER_MSVC rai = _device->GetResourceAllocationInfo(1, 1, _resourceDesc); #else _device->GetResourceAllocationInfo(&rai, 1, 1, _resourceDesc); #endif // BX_COMPILER_MSVC bx::memSet(ptr, 0, size_t(rai.SizeInBytes) ); resource->Unmap(0, NULL); } 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); } inline bool isLost(HRESULT _hr) { return false || _hr == 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 ; } static const char* getLostReason(HRESULT _hr) { switch (_hr) { // The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action. case DXGI_ERROR_DEVICE_REMOVED: return "DXGI_ERROR_DEVICE_REMOVED"; // The GPU will not respond to more commands, most likely because of an invalid command passed by the calling application. case DXGI_ERROR_DEVICE_HUNG: return "DXGI_ERROR_DEVICE_HUNG"; // The GPU will not respond to more commands, most likely because some other application submitted invalid commands. // The calling application should re-create the device and continue. case DXGI_ERROR_DEVICE_RESET: return "DXGI_ERROR_DEVICE_RESET"; // An internal issue prevented the driver from carrying out the specified operation. The driver's state is probably // suspect, and the application should not continue. case DXGI_ERROR_DRIVER_INTERNAL_ERROR: return "DXGI_ERROR_DRIVER_INTERNAL_ERROR"; // A resource is not available at the time of the call, but may become available later. case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE"; case S_OK: return "S_OK"; default: break; } return "Unknown HRESULT?"; } 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, bx::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_ENABLE_EXPERIMENTAL_FEATURES D3D12EnableExperimentalFeatures; static PFN_D3D12_CREATE_DEVICE D3D12CreateDevice; static PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface; static PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignature; # if !BX_PLATFORM_LINUX typedef HANDLE (WINAPI* PFN_CREATE_EVENT_EX_A)(LPSECURITY_ATTRIBUTES _attrs, LPCSTR _name, DWORD _flags, DWORD _access); static PFN_CREATE_EVENT_EX_A CreateEventExA; # endif // !BX_PLATFORM_LINUX #endif // USE_D3D12_DYNAMIC_LIB inline D3D12_CPU_DESCRIPTOR_HANDLE getCPUHandleHeapStart(ID3D12DescriptorHeap* _heap) { #if BX_COMPILER_MSVC return _heap->GetCPUDescriptorHandleForHeapStart(); #else D3D12_CPU_DESCRIPTOR_HANDLE handle; _heap->GetCPUDescriptorHandleForHeapStart(&handle); return handle; #endif // BX_COMPILER_MSVC } inline D3D12_GPU_DESCRIPTOR_HANDLE getGPUHandleHeapStart(ID3D12DescriptorHeap* _heap) { #if BX_COMPILER_MSVC return _heap->GetGPUDescriptorHandleForHeapStart(); #else D3D12_GPU_DESCRIPTOR_HANDLE handle; _heap->GetGPUDescriptorHandleForHeapStart(&handle); return handle; #endif // BX_COMPILER_MSVC } inline D3D12_RESOURCE_DESC getResourceDesc(ID3D12Resource* _resource) { #if BX_COMPILER_MSVC return _resource->GetDesc(); #else D3D12_RESOURCE_DESC desc; _resource->GetDesc(&desc); return desc; #endif // BX_COMPILER_MSVC } #if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) static PIXEventsThreadInfo s_pixEventsThreadInfo; PIXEventsThreadInfo* WINAPI stubPIXGetThreadInfo() { return &s_pixEventsThreadInfo; } uint64_t WINAPI stubPIXEventsReplaceBlock(bool _getEarliestTime) { BX_UNUSED(_getEarliestTime); return 0; } #endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) struct RendererContextD3D12 : public RendererContextI { RendererContextD3D12() : m_d3d12Dll(NULL) , m_renderDocDll(NULL) , m_winPixEvent(NULL) , m_featureLevel(D3D_FEATURE_LEVEL(0) ) , m_swapChain(NULL) , m_wireframe(false) , m_lost(false) , m_maxAnisotropy(1) , m_depthClamp(false) , m_backBufferColorIdx(0) , m_rtMsaa(false) , m_directAccessSupport(false) { } ~RendererContextD3D12() { } bool init(const Init& _init) { struct ErrorState { enum Enum { Default, LoadedKernel32, LoadedD3D12, LoadedDXGI, CreatedDXGIFactory, CreatedCommandQueue, }; }; ErrorState::Enum errorState = ErrorState::Default; // LUID luid; #if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) m_winPixEvent = bx::dlopen("WinPixEventRuntime.dll"); if (NULL != m_winPixEvent) { bgfx_PIXGetThreadInfo = (PFN_PIX_GET_THREAD_INFO )bx::dlsym(m_winPixEvent, "PIXGetThreadInfo"); bgfx_PIXEventsReplaceBlock = (PFN_PIX_EVENTS_REPLACE_BLOCK)bx::dlsym(m_winPixEvent, "PIXEventsReplaceBlock"); } if (NULL == bgfx_PIXGetThreadInfo || NULL == bgfx_PIXEventsReplaceBlock) { bgfx_PIXGetThreadInfo = stubPIXGetThreadInfo; bgfx_PIXEventsReplaceBlock = stubPIXEventsReplaceBlock; } #endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) if (_init.debug || _init.profile) { m_renderDocDll = loadRenderDoc(); } setGraphicsDebuggerPresent(NULL != m_renderDocDll || NULL != m_winPixEvent); m_fbh.idx = kInvalidHandle; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); #if USE_D3D12_DYNAMIC_LIB # if !BX_PLATFORM_LINUX m_kernel32Dll = bx::dlopen("kernel32.dll"); if (NULL == m_kernel32Dll) { BX_TRACE("Init error: Failed to load kernel32.dll."); goto error; } CreateEventExA = (PFN_CREATE_EVENT_EX_A)bx::dlsym(m_kernel32Dll, "CreateEventExA"); if (NULL == CreateEventExA) { BX_TRACE("Init error: Function CreateEventExA not found."); goto error; } errorState = ErrorState::LoadedKernel32; # endif // !BX_PLATFORM_LINUX m_nvapi.init(); { const char* d3d12DllName = #if BX_PLATFORM_LINUX "libd3d12.so" #else "d3d12.dll" #endif // BX_PLATFORM_LINUX ; m_d3d12Dll = bx::dlopen(d3d12DllName); if (NULL == m_d3d12Dll) { BX_TRACE("Init error: Failed to load %s.", d3d12DllName); goto error; } } errorState = ErrorState::LoadedD3D12; D3D12EnableExperimentalFeatures = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)bx::dlsym(m_d3d12Dll, "D3D12EnableExperimentalFeatures"); BX_WARN(NULL != D3D12EnableExperimentalFeatures, "Function D3D12EnableExperimentalFeatures not found."); D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)bx::dlsym(m_d3d12Dll, "D3D12CreateDevice"); BX_WARN(NULL != D3D12CreateDevice, "Function D3D12CreateDevice not found."); D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)bx::dlsym(m_d3d12Dll, "D3D12GetDebugInterface"); BX_WARN(NULL != D3D12GetDebugInterface, "Function D3D12GetDebugInterface not found."); D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)bx::dlsym(m_d3d12Dll, "D3D12SerializeRootSignature"); BX_WARN(NULL != D3D12SerializeRootSignature, "Function D3D12SerializeRootSignature not found."); if (NULL == D3D12CreateDevice || NULL == D3D12GetDebugInterface || NULL == D3D12SerializeRootSignature) { BX_TRACE("Init error: Function not found."); goto error; } #endif // USE_D3D12_DYNAMIC_LIB #if !BX_PLATFORM_LINUX if (!m_dxgi.init(g_caps) ) { goto error; } errorState = ErrorState::LoadedDXGI; #endif // !BX_PLATFORM_LINUX HRESULT hr; { #if BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT if (_init.debug || _init.profile) { ID3D12Debug* debug0; hr = D3D12GetDebugInterface(IID_ID3D12Debug, (void**)&debug0); if (SUCCEEDED(hr) ) { if (_init.debug) { #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT debug0->EnableDebugLayer(); { ID3D12Debug1* debug1; hr = debug0->QueryInterface(IID_ID3D12Debug1, (void**)&debug1); if (SUCCEEDED(hr)) { // debug1->SetEnableGPUBasedValidation(true); // https://discordapp.com/channels/590611987420020747/593519198995742733/703642988345032804 // D3D12 Bug Number: 26131261 // There is a bug in the D3D12 validation that causes example-21 to fail when using UAV // Setting this function below to false avoids the bug debug1->SetEnableSynchronizedCommandQueueValidation(false); } DX_RELEASE(debug1, 1); } #endif // BX_PLATFORM_WINDOWS } DX_RELEASE(debug0, 0); } } D3D_FEATURE_LEVEL featureLevel[] = { D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, }; hr = E_FAIL; for (uint32_t ii = 0; ii < BX_COUNTOF(featureLevel) && FAILED(hr); ++ii) { hr = D3D12CreateDevice( #if BX_PLATFORM_LINUX NULL #else m_dxgi.m_adapter #endif // BX_PLATFORM_LINUX , featureLevel[ii] , IID_ID3D12Device , (void**)&m_device ); BX_WARN(FAILED(hr), "Direct3D12 device feature level %d.%d." , (featureLevel[ii] >> 12) & 0xf , (featureLevel[ii] >> 8) & 0xf ); m_featureLevel = featureLevel[ii]; } #else // Reference(s): // - https://github.com/Microsoft/Xbox-ATG-Samples/blob/1271bfd61b4883c775f395b6f13aeabea70290ca/XDKSamples/Graphics/AdvancedESRAM12/DeviceResources.cpp#L64 D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; params.Version = D3D12_SDK_VERSION; params.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAGS(0 | (_init.debug ? D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG : 0) | (_init.profile ? D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED : 0) ); params.GraphicsCommandQueueRingSizeBytes = UINT32_MAX; params.GraphicsScratchMemorySizeBytes = UINT32_MAX; params.ComputeScratchMemorySizeBytes = UINT32_MAX; params.DisableGeometryShaderAllocations = true; params.DisableTessellationShaderAllocations = true; hr = D3D12XboxCreateDevice( m_dxgi.m_adapter , &params , IID_ID3D12Device , (void**)&m_device ); m_featureLevel = D3D_FEATURE_LEVEL_12_1; if (SUCCEEDED(hr) ) { m_device->SetDebugErrorFilterX(0x73EC9EAF, D3D12XBOX_DEBUG_FILTER_FLAG_DISABLE_BREAKS); m_device->SetDebugErrorFilterX(0x8EC9B15C, D3D12XBOX_DEBUG_FILTER_FLAG_DISABLE_OUTPUT); } #endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT } if (FAILED(hr) ) { BX_TRACE("Init error: Unable to create Direct3D12 device."); if (BX_ENABLED(BX_PLATFORM_WINRT) ) { BX_TRACE("Hint: Change UWP app to game?"); } goto error; } #if !BX_PLATFORM_LINUX m_dxgi.update(m_device); #endif // !BX_PLATFORM_LINUX { m_deviceInterfaceVersion = 0; for (uint32_t ii = 0; ii < BX_COUNTOF(s_d3dDeviceIIDs); ++ii) { ID3D12Device* device; hr = m_device->QueryInterface(s_d3dDeviceIIDs[ii], (void**)&device); if (SUCCEEDED(hr) ) { device->Release(); // BK - ignore ref count. m_deviceInterfaceVersion = BX_COUNTOF(s_d3dDeviceIIDs) - ii; break; } } } #if !BX_PLATFORM_LINUX if (BGFX_PCI_ID_NVIDIA != m_dxgi.m_adapterDesc.VendorId) { m_nvapi.shutdown(); } #endif // !BX_PLATFORM_LINUX { uint32_t numNodes = m_device->GetNodeCount(); BX_TRACE("D3D12 GPU Architecture (num nodes: %d):", numNodes); for (uint32_t ii = 0; ii < numNodes; ++ii) { D3D12_FEATURE_DATA_ARCHITECTURE architecture; architecture.NodeIndex = ii; DX_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &architecture, sizeof(architecture) ) ); BX_TRACE("\tNode % 2d: TileBasedRenderer %d, UMA %d, CacheCoherentUMA %d" , ii , architecture.TileBasedRenderer , architecture.UMA , architecture.CacheCoherentUMA ); if (0 == ii) { bx::memCopy(&m_architecture, &architecture, sizeof(architecture) ); } } } DX_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &m_options, sizeof(m_options) ) ); BX_TRACE("D3D12 options:"); BX_TRACE("\tTiledResourcesTier %d", m_options.TiledResourcesTier); BX_TRACE("\tResourceBindingTier %d", m_options.ResourceBindingTier); BX_TRACE("\tROVsSupported %d", m_options.ROVsSupported); BX_TRACE("\tConservativeRasterizationTier %d", m_options.ConservativeRasterizationTier); BX_TRACE("\tCrossNodeSharingTier %d", m_options.CrossNodeSharingTier); BX_TRACE("\tResourceHeapTier %d", m_options.ResourceHeapTier); initHeapProperties(m_device); m_cmd.init(m_device); m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, m_cmd.m_commandQueue); errorState = ErrorState::CreatedCommandQueue; if (NULL == g_platformData.backBuffer) { bx::memSet(&m_scd, 0, sizeof(m_scd) ); m_scd.width = _init.resolution.width; m_scd.height = _init.resolution.height; m_scd.format = s_textureFormat[_init.resolution.format].m_fmt; m_scd.stereo = false; updateMsaa(m_scd.format); m_scd.sampleDesc = s_msaa[(_init.resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; m_scd.bufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; m_scd.bufferCount = bx::clamp<uint8_t>(_init.resolution.numBackBuffers, 2, BX_COUNTOF(m_backBufferColor) ); m_scd.scaling = 0 == g_platformData.ndt ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH ; m_scd.swapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; m_scd.alphaMode = DXGI_ALPHA_MODE_IGNORE; m_scd.flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; m_scd.maxFrameLatency = bx::min<uint8_t>(_init.resolution.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); m_scd.nwh = g_platformData.nwh; m_scd.ndt = g_platformData.ndt; m_scd.windowed = true; m_backBufferColorIdx = m_scd.bufferCount-1; m_msaaRt = NULL; if (NULL != m_scd.nwh) { #if BX_PLATFORM_LINUX hr = E_FAIL; #else hr = m_dxgi.createSwapChain( getDeviceForSwapChain() , m_scd , &m_swapChain ); #endif // BX_PLATFORM_LINUX if (FAILED(hr) ) { BX_TRACE("Init error: Unable to create Direct3D12 swap chain."); goto error; } else { m_resolution = _init.resolution; m_resolution.reset = _init.resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); m_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height); m_textVideoMem.clear(); } if (1 < m_scd.sampleDesc.Count) { D3D12_RESOURCE_DESC resourceDesc; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resourceDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; resourceDesc.Width = m_scd.width; resourceDesc.Height = m_scd.height; resourceDesc.MipLevels = 1; resourceDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) ? s_textureFormat[m_resolution.format].m_fmtSrgb : s_textureFormat[m_resolution.format].m_fmt; resourceDesc.SampleDesc = m_scd.sampleDesc; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; resourceDesc.DepthOrArraySize = 1; D3D12_CLEAR_VALUE clearValue; clearValue.Format = resourceDesc.Format; clearValue.Color[0] = 0.0f; clearValue.Color[1] = 0.0f; clearValue.Color[2] = 0.0f; clearValue.Color[3] = 0.0f; m_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true); setDebugObjectName(m_msaaRt, "MSAA Backbuffer"); } } } m_presentElapsed = 0; { m_resolution.width = _init.resolution.width; m_resolution.height = _init.resolution.height; m_windows[0] = BGFX_INVALID_HANDLE; m_numWindows = 1; #if BX_PLATFORM_WINDOWS m_infoQueue = NULL; DX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh , 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER ) ); if (_init.debug) { hr = m_device->QueryInterface(IID_ID3D12InfoQueue, (void**)&m_infoQueue); if (SUCCEEDED(hr) ) { m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, false); D3D12_INFO_QUEUE_FILTER filter; bx::memSet(&filter, 0, sizeof(filter) ); D3D12_MESSAGE_CATEGORY catlist[] = { D3D12_MESSAGE_CATEGORY_STATE_CREATION, D3D12_MESSAGE_CATEGORY_EXECUTION, }; filter.DenyList.NumCategories = BX_COUNTOF(catlist); filter.DenyList.pCategoryList = catlist; m_infoQueue->PushStorageFilter(&filter); } } #endif // BX_PLATFORM_WINDOWS 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 = 1; DX_CHECK(m_device->CreateDescriptorHeap(&rtvDescHeap , IID_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 = 1; DX_CHECK(m_device->CreateDescriptorHeap(&dsvDescHeap , IID_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_CBV, { { 0, 0 } }, D3D12_SHADER_VISIBILITY_ALL }, { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::UAV] } }, D3D12_SHADER_VISIBILITY_ALL }, }; rootParameter[Rdt::CBV].Descriptor.RegisterSpace = 0; rootParameter[Rdt::CBV].Descriptor.ShaderRegister = 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() , IID_ID3D12RootSignature , (void**)&m_rootSignature ) ); /// m_directAccessSupport = true && BX_ENABLED(BX_PLATFORM_XBOXONE) && m_architecture.UMA ; g_caps.supported |= ( 0 | BGFX_CAPS_TEXTURE_3D | BGFX_CAPS_TEXTURE_COMPARE_ALL | BGFX_CAPS_INDEX32 | BGFX_CAPS_INSTANCING | BGFX_CAPS_DRAW_INDIRECT | BGFX_CAPS_VERTEX_ATTRIB_HALF | BGFX_CAPS_VERTEX_ATTRIB_UINT10 | BGFX_CAPS_VERTEX_ID | BGFX_CAPS_FRAGMENT_DEPTH | BGFX_CAPS_BLEND_INDEPENDENT | BGFX_CAPS_COMPUTE | (m_options.ROVsSupported ? BGFX_CAPS_FRAGMENT_ORDERING : 0) | (m_directAccessSupport ? BGFX_CAPS_TEXTURE_DIRECT_ACCESS : 0) | (BX_ENABLED(BX_PLATFORM_WINDOWS) ? BGFX_CAPS_SWAP_CHAIN : 0) | BGFX_CAPS_TEXTURE_BLIT | BGFX_CAPS_TEXTURE_READ_BACK | BGFX_CAPS_OCCLUSION_QUERY | BGFX_CAPS_ALPHA_TO_COVERAGE | BGFX_CAPS_TEXTURE_2D_ARRAY | BGFX_CAPS_TEXTURE_CUBE_ARRAY | BGFX_CAPS_IMAGE_RW | BGFX_CAPS_VIEWPORT_LAYER_ARRAY | BGFX_CAPS_DRAW_INDIRECT_COUNT ); g_caps.limits.maxTextureSize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION; g_caps.limits.maxTextureLayers = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; g_caps.limits.maxFBAttachments = bx::min<uint8_t>(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); g_caps.limits.maxComputeBindings = bx::min(D3D12_UAV_SLOT_COUNT, BGFX_MAX_COMPUTE_BINDINGS); g_caps.limits.maxVertexStreams = BGFX_CONFIG_MAX_VERTEX_STREAMS; for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) { uint16_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE; const DXGI_FORMAT fmt = bimg::isDepth(bimg::TextureFormat::Enum(ii) ) ? s_textureFormat[ii].m_fmtDsv : s_textureFormat[ii].m_fmt ; const DXGI_FORMAT fmtSrgb = s_textureFormat[ii].m_fmtSrgb; 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 ) ) ? BGFX_CAPS_FORMAT_TEXTURE_2D : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_TEXTURE3D ) ) ? BGFX_CAPS_FORMAT_TEXTURE_3D : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_TEXTURECUBE ) ) ? BGFX_CAPS_FORMAT_TEXTURE_CUBE : 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_READ : 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 ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET ) ) ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD ) ) ? BGFX_CAPS_FORMAT_TEXTURE_MSAA : BGFX_CAPS_FORMAT_TEXTURE_NONE ; } else { BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) ); } if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ) ) { // clear image flag for additional testing support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ; data.Format = s_textureFormat[ii].m_fmt; hr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); if (SUCCEEDED(hr) ) { support |= 0 != (data.Support2 & (0 | D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD ) ) ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support2 & (0 | D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE ) ) ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE : BGFX_CAPS_FORMAT_TEXTURE_NONE ; } } } if (DXGI_FORMAT_UNKNOWN != fmtSrgb) { struct D3D11_FEATURE_DATA_FORMAT_SUPPORT { DXGI_FORMAT InFormat; uint32_t OutFormatSupport; }; D3D12_FEATURE_DATA_FORMAT_SUPPORT data; data.Format = fmtSrgb; hr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); if (SUCCEEDED(hr) ) { support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_TEXTURE2D ) ) ? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_TEXTURE3D ) ) ? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB : BGFX_CAPS_FORMAT_TEXTURE_NONE ; support |= 0 != (data.Support1 & (0 | D3D12_FORMAT_SUPPORT1_TEXTURECUBE ) ) ? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB : BGFX_CAPS_FORMAT_TEXTURE_NONE ; } else { BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) ); } } g_caps.formats[ii] = support; } // Init reserved part of view name. for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) { bx::snprintf(s_viewName[ii], BGFX_CONFIG_MAX_VIEW_NAME_RESERVED + 1, "%3d ", ii); } postReset(); m_batch.create(4<<10); #if !BX_PLATFORM_LINUX m_batch.setIndirectMode(BGFX_PCI_ID_NVIDIA != m_dxgi.m_adapterDesc.VendorId && BGFX_PCI_ID_MICROSOFT != m_dxgi.m_adapterDesc.VendorId); #endif // !BX_PLATFORM_LINUX m_gpuTimer.init(); m_occlusionQuery.init(); { D3D12_INDIRECT_ARGUMENT_TYPE argType[] = { D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED, }; D3D12_INDIRECT_ARGUMENT_DESC argDesc; bx::memSet(&argDesc, 0, sizeof(argDesc) ); for (uint32_t ii = 0; ii < BX_COUNTOF(m_commandSignature); ++ii) { argDesc.Type = argType[ii]; D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = { BGFX_CONFIG_DRAW_INDIRECT_STRIDE, 1, &argDesc, 1 }; m_commandSignature[ii] = NULL; DX_CHECK(m_device->CreateCommandSignature(&commandSignatureDesc , NULL , IID_ID3D12CommandSignature , (void**)&m_commandSignature[ii] ) ); } } } if (m_nvapi.isInitialized() ) { finish(); m_commandList = m_cmd.alloc(); m_nvapi.initAftermath(m_device, m_commandList); } g_internalData.context = m_device; return true; error: switch (errorState) { case ErrorState::CreatedCommandQueue: m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL); m_cmd.shutdown(); BX_FALLTHROUGH; case ErrorState::CreatedDXGIFactory: DX_RELEASE(m_device, 0); #if !BX_PLATFORM_LINUX m_dxgi.shutdown(); #endif // !BX_PLATFORM_LINUX BX_FALLTHROUGH; #if USE_D3D12_DYNAMIC_LIB case ErrorState::LoadedDXGI: case ErrorState::LoadedD3D12: bx::dlclose(m_d3d12Dll); BX_FALLTHROUGH; case ErrorState::LoadedKernel32: bx::dlclose(m_kernel32Dll); BX_FALLTHROUGH; #endif // USE_D3D12_DYNAMIC_LIB case ErrorState::Default: default: m_nvapi.shutdown(); unloadRenderDoc(m_renderDocDll); bx::dlclose(m_winPixEvent); m_winPixEvent = NULL; break; } return false; } void shutdown() { m_cmd.finish(); m_batch.destroy(); preReset(); m_gpuTimer.shutdown(); m_occlusionQuery.shutdown(); 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(); } #if BX_PLATFORM_WINDOWS DX_RELEASE_W(m_infoQueue, 0); #endif // BX_PLATFORM_WINDOWS DX_RELEASE(m_rtvDescriptorHeap, 0); DX_RELEASE(m_dsvDescriptorHeap, 0); for (uint32_t ii = 0; ii < BX_COUNTOF(m_commandSignature); ++ii) { DX_RELEASE(m_commandSignature[ii], 0); } DX_RELEASE(m_rootSignature, 0); DX_RELEASE(m_msaaRt, 0); DX_RELEASE(m_swapChain, 0); m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL); m_cmd.shutdown(); DX_RELEASE(m_device, 0); m_nvapi.shutdown(); #if !BX_PLATFORM_LINUX m_dxgi.shutdown(); #endif // !BX_PLATFORM_LINUX unloadRenderDoc(m_renderDocDll); bx::dlclose(m_winPixEvent); m_winPixEvent = NULL; #if USE_D3D12_DYNAMIC_LIB bx::dlclose(m_d3d12Dll); bx::dlclose(m_kernel32Dll); #endif // USE_D3D12_DYNAMIC_LIB } RendererType::Enum getRendererType() const override { return RendererType::Direct3D12; } const char* getRendererName() const override { return BGFX_RENDERER_DIRECT3D12_NAME; } bool isDeviceRemoved() override { return m_lost; } void flip() override { if (!m_lost) { int64_t start = bx::getHPCounter(); m_cmd.finish(m_backBufferColorFence[(m_backBufferColorIdx-1) % m_scd.bufferCount]); HRESULT hr = S_OK; uint32_t syncInterval = !!(m_resolution.reset & BGFX_RESET_VSYNC); uint32_t presentFlags = 0; if (syncInterval) { presentFlags |= DXGI_PRESENT_RESTART; } #if !BX_PLATFORM_LINUX else if (m_dxgi.tearingSupported() ) { presentFlags |= DXGI_PRESENT_ALLOW_TEARING; } #endif // !BX_PLATFORM_LINUX for (uint32_t ii = 1, num = m_numWindows; ii < num && SUCCEEDED(hr); ++ii) { FrameBufferD3D12& frameBuffer = m_frameBuffers[m_windows[ii].idx]; hr = frameBuffer.present(syncInterval, presentFlags); } if (SUCCEEDED(hr) && NULL != m_swapChain) { hr = m_swapChain->Present(syncInterval, presentFlags); } int64_t now = bx::getHPCounter(); m_presentElapsed = now - start; m_lost = isLost(hr); BGFX_FATAL(!m_lost , bgfx::Fatal::DeviceLost , "Device is lost. FAILED 0x%08x %s (%s)" , hr , getLostReason(hr) , DXGI_ERROR_DEVICE_REMOVED == hr ? getLostReason(m_device->GetDeviceRemovedReason() ) : "no info" ); } } void createIndexBuffer(IndexBufferHandle _handle, const Memory* _mem, uint16_t _flags) override { m_indexBuffers[_handle.idx].create(_mem->size, _mem->data, _flags, false); } void destroyIndexBuffer(IndexBufferHandle _handle) override { m_indexBuffers[_handle.idx].destroy(); } void createVertexLayout(VertexLayoutHandle _handle, const VertexLayout& _layout) override { VertexLayout& layout = m_vertexLayouts[_handle.idx]; bx::memCopy(&layout, &_layout, sizeof(VertexLayout) ); dump(layout); } void destroyVertexLayout(VertexLayoutHandle /*_handle*/) override { } void createVertexBuffer(VertexBufferHandle _handle, const Memory* _mem, VertexLayoutHandle _layoutHandle, uint16_t _flags) override { m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _layoutHandle, _flags); } void destroyVertexBuffer(VertexBufferHandle _handle) override { m_vertexBuffers[_handle.idx].destroy(); } void createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint16_t _flags) override { m_indexBuffers[_handle.idx].create(_size, NULL, _flags, false); } void updateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override { m_indexBuffers[_handle.idx].update(m_commandList, _offset, bx::uint32_min(_size, _mem->size), _mem->data); } void destroyDynamicIndexBuffer(IndexBufferHandle _handle) override { m_indexBuffers[_handle.idx].destroy(); } void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint16_t _flags) override { VertexLayoutHandle layoutHandle = BGFX_INVALID_HANDLE; m_vertexBuffers[_handle.idx].create(_size, NULL, layoutHandle, _flags); } void updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override { m_vertexBuffers[_handle.idx].update(m_commandList, _offset, bx::uint32_min(_size, _mem->size), _mem->data); } void destroyDynamicVertexBuffer(VertexBufferHandle _handle) override { m_vertexBuffers[_handle.idx].destroy(); } void createShader(ShaderHandle _handle, const Memory* _mem) override { m_shaders[_handle.idx].create(_mem); } void destroyShader(ShaderHandle _handle) override { m_shaders[_handle.idx].destroy(); } void createProgram(ProgramHandle _handle, ShaderHandle _vsh, ShaderHandle _fsh) override { m_program[_handle.idx].create(&m_shaders[_vsh.idx], isValid(_fsh) ? &m_shaders[_fsh.idx] : NULL); } void destroyProgram(ProgramHandle _handle) override { m_program[_handle.idx].destroy(); } void* createTexture(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip) override { return m_textures[_handle.idx].create(_mem, _flags, _skip); } void updateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/) 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) override { m_textures[_handle.idx].update(m_commandList, _side, _mip, _rect, _z, _depth, _pitch, _mem); } void updateTextureEnd() override { } void readTexture(TextureHandle _handle, void* _data, uint8_t _mip ) override { const TextureD3D12& texture = m_textures[_handle.idx]; D3D12_RESOURCE_DESC desc = getResourceDesc(texture.m_ptr); D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout; uint32_t numRows; uint64_t total; m_device->GetCopyableFootprints(&desc , _mip , 1 , 0 , &layout , &numRows , NULL , &total ); uint32_t srcPitch = layout.Footprint.RowPitch; ID3D12Resource* readback = createCommittedResource(m_device, HeapProperty::ReadBack, total); uint32_t srcWidth = bx::uint32_max(1, texture.m_width >>_mip); uint32_t srcHeight = bx::uint32_max(1, texture.m_height>>_mip); D3D12_BOX box; box.left = 0; box.top = 0; box.right = srcWidth; box.bottom = srcHeight; box.front = 0; box.back = 1; D3D12_TEXTURE_COPY_LOCATION dstLocation = { readback, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, { layout } }; D3D12_TEXTURE_COPY_LOCATION srcLocation = { texture.m_ptr, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { } }; srcLocation.SubresourceIndex = _mip; m_commandList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &box); finish(); m_commandList = m_cmd.alloc(); const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat) ); uint8_t* dst = (uint8_t*)_data; uint32_t dstPitch = srcWidth*bpp/8; uint32_t pitch = bx::uint32_min(srcPitch, dstPitch); uint8_t* src; readback->Map(0, NULL, (void**)&src); for (uint32_t yy = 0, height = srcHeight; yy < height; ++yy) { bx::memCopy(dst, src, pitch); src += srcPitch; dst += dstPitch; } D3D12_RANGE writeRange = { 0, 0 }; readback->Unmap(0, &writeRange); DX_RELEASE(readback, 0); } void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) 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, bx::ErrorAssert{}); TextureCreate tc; tc.m_width = _width; tc.m_height = _height; tc.m_depth = 0; tc.m_numLayers = _numLayers; tc.m_numMips = _numMips; tc.m_format = TextureFormat::Enum(texture.m_requestedFormat); tc.m_cubeMap = false; tc.m_mem = NULL; bx::write(&writer, tc, bx::ErrorAssert{}); texture.destroy(); texture.create(mem, texture.m_flags, 0); release(mem); } void overrideInternal(TextureHandle _handle, uintptr_t _ptr) override { // Resource ref. counts might be messed up outside of bgfx. // Disabling ref. count check once texture is overridden. setGraphicsDebuggerPresent(true); m_textures[_handle.idx].overrideInternal(_ptr); } uintptr_t getInternal(TextureHandle _handle) override { setGraphicsDebuggerPresent(true); return uintptr_t(m_textures[_handle.idx].m_ptr); } void destroyTexture(TextureHandle _handle) override { m_textures[_handle.idx].destroy(); } void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) override { m_frameBuffers[_handle.idx].create(_num, _attachment); } void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override { finishAll(true); for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) && m_frameBuffers[handle.idx].m_nwh == _nwh) { destroyFrameBuffer(handle); } } uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat); } void destroyFrameBuffer(FrameBufferHandle _handle) override { FrameBufferD3D12& frameBuffer = m_frameBuffers[_handle.idx]; if (NULL != frameBuffer.m_swapChain) { finishAll(true); } uint16_t denseIdx = frameBuffer.destroy(); if (UINT16_MAX != denseIdx) { --m_numWindows; if (m_numWindows > 1) { FrameBufferHandle handle = m_windows[m_numWindows]; m_windows[m_numWindows] = {kInvalidHandle}; if (m_numWindows != denseIdx) { m_windows[denseIdx] = handle; m_frameBuffers[handle.idx].m_denseIdx = denseIdx; } } } } void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) override { if (NULL != m_uniforms[_handle.idx]) { BX_FREE(g_allocator, m_uniforms[_handle.idx]); } const uint32_t size = bx::alignUp(g_uniformTypeSize[_type] * _num, 16); void* data = BX_ALLOC(g_allocator, size); bx::memSet(data, 0, size); m_uniforms[_handle.idx] = data; m_uniformReg.add(_handle, _name); } void destroyUniform(UniformHandle _handle) override { BX_FREE(g_allocator, m_uniforms[_handle.idx]); m_uniforms[_handle.idx] = NULL; m_uniformReg.remove(_handle); } void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override { BX_UNUSED(_handle); uint32_t idx = (m_backBufferColorIdx-1) % m_scd.bufferCount; m_cmd.finish(m_backBufferColorFence[idx]); ID3D12Resource* backBuffer = m_backBufferColor[idx]; D3D12_RESOURCE_DESC desc = getResourceDesc(backBuffer); const uint32_t width = (uint32_t)desc.Width; const uint32_t height = (uint32_t)desc.Height; D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout; uint32_t numRows; uint64_t total; uint64_t pitch; m_device->GetCopyableFootprints(&desc , 0 , 1 , 0 , &layout , &numRows , &pitch , &total ); ID3D12Resource* readback = createCommittedResource(m_device, HeapProperty::ReadBack, total); D3D12_BOX box; box.left = 0; box.top = 0; box.right = width; box.bottom = height; box.front = 0; box.back = 1; setResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_SOURCE); D3D12_TEXTURE_COPY_LOCATION dst = { readback, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, { layout } }; D3D12_TEXTURE_COPY_LOCATION src = { backBuffer, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, {} }; m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &box); setResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT); finish(); m_commandList = m_cmd.alloc(); void* data; readback->Map(0, NULL, (void**)&data); bimg::imageSwizzleBgra8( data , layout.Footprint.RowPitch , width , height , data , layout.Footprint.RowPitch ); g_callback->screenShot(_filePath , width , height , layout.Footprint.RowPitch , data , (uint32_t)total , false ); D3D12_RANGE writeRange = { 0, 0 }; readback->Unmap(0, &writeRange); DX_RELEASE(readback, 0); } void updateViewName(ViewId _id, const char* _name) override { bx::strCopy(&s_viewName[_id][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED] , BX_COUNTOF(s_viewName[0]) - BGFX_CONFIG_MAX_VIEW_NAME_RESERVED , _name ); } void updateUniform(uint16_t _loc, const void* _data, uint32_t _size) override { bx::memCopy(m_uniforms[_loc], _data, _size); } void invalidateOcclusionQuery(OcclusionQueryHandle _handle) override { m_occlusionQuery.invalidate(_handle); } void setMarker(const char* _marker, uint16_t _len) override { BX_UNUSED(_len); if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) { PIX3_SETMARKER(m_commandList, kColorMarker, _marker); } } virtual void setName(Handle _handle, const char* _name, uint16_t _len) override { switch (_handle.type) { case Handle::IndexBuffer: setDebugObjectName(m_indexBuffers[_handle.idx].m_ptr, "%.*s", _len, _name); break; case Handle::Shader: // setDebugObjectName(m_shaders[_handle.idx].m_ptr, "%.*s", _len, _name); break; case Handle::Texture: setDebugObjectName(m_textures[_handle.idx].m_ptr, "%.*s", _len, _name); break; case Handle::VertexBuffer: setDebugObjectName(m_vertexBuffers[_handle.idx].m_ptr, "%.*s", _len, _name); break; default: BX_ASSERT(false, "Invalid handle type?! %d", _handle.type); break; } } void submitBlit(BlitState& _bs, uint16_t _view); void submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) override; void blitSetup(TextVideoMemBlitter& _blitter) override { const uint32_t width = m_scd.width; const uint32_t height = m_scd.height; setFrameBuffer(BGFX_INVALID_HANDLE, 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); D3D12_RECT rc; rc.left = 0; rc.top = 0; rc.right = width; rc.bottom = height; m_commandList->RSSetScissorRects(1, &rc); const uint64_t state = 0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS ; const VertexLayout* layouts[1] = { &m_vertexLayouts[_blitter.m_vb->layoutHandle.idx] }; ID3D12PipelineState* pso = getPipelineState(state , packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) , 1 , layouts , _blitter.m_program , 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, 0.0f, false); 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_VIRTUAL_ADDRESS gpuAddress; commitShaderConstants(_blitter.m_program, gpuAddress); ScratchBufferD3D12& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx]; ID3D12DescriptorHeap* heaps[] = { m_samplerAllocator.getHeap(), scratchBuffer.getHeap(), }; m_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps); m_commandList->SetGraphicsRootConstantBufferView(Rdt::CBV, gpuAddress); TextureD3D12& texture = m_textures[_blitter.m_texture.idx]; uint32_t samplerFlags[] = { uint32_t(texture.m_flags & BGFX_SAMPLER_BITS_MASK) }; uint16_t samplerStateIdx = getSamplerState(samplerFlags, BX_COUNTOF(samplerFlags), NULL); m_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) ); D3D12_GPU_DESCRIPTOR_HANDLE srvHandle; scratchBuffer.allocSrv(srvHandle, texture); m_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle); VertexBufferD3D12& vb = m_vertexBuffers[_blitter.m_vb->handle.idx]; const VertexLayout& layout = m_vertexLayouts[_blitter.m_vb->layoutHandle.idx]; D3D12_VERTEX_BUFFER_VIEW viewDesc; viewDesc.BufferLocation = vb.m_gpuVA; viewDesc.StrideInBytes = layout.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_gpuVA; ibv.SizeInBytes = ib.m_size; m_commandList->IASetIndexBuffer(&ibv); m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) 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_layout.m_stride, _blitter.m_vb->data, true); m_commandList->DrawIndexedInstanced(_numIndices , 1 , 0 , 0 , 0 ); } } void preReset() { finishAll(); if (NULL != m_swapChain) { for (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii) { #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT DX_RELEASE(m_backBufferColor[ii], num-1-ii); #else DX_RELEASE(m_backBufferColor[ii], 1); #endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT } DX_RELEASE(m_backBufferDepthStencil, 0); } for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].preReset(); } invalidateCache(); // capturePreReset(); } void postReset() { bx::memSet(m_backBufferColorFence, 0, sizeof(m_backBufferColorFence) ); uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); if (NULL != m_swapChain) { for (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii) { D3D12_CPU_DESCRIPTOR_HANDLE handle = getCPUHandleHeapStart(m_rtvDescriptorHeap); handle.ptr += ii * rtvDescriptorSize; DX_CHECK(m_swapChain->GetBuffer(ii , IID_ID3D12Resource , (void**)&m_backBufferColor[ii] ) ); D3D12_RENDER_TARGET_VIEW_DESC rtvDesc; rtvDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) ? s_textureFormat[m_resolution.format].m_fmtSrgb : s_textureFormat[m_resolution.format].m_fmt; if (1 < getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize) { rtvDesc.ViewDimension = (NULL == m_msaaRt) ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; rtvDesc.Texture2DArray.FirstArraySlice = 0; rtvDesc.Texture2DArray.ArraySize = getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize; rtvDesc.Texture2DArray.MipSlice = 0; rtvDesc.Texture2DArray.PlaneSlice = 0; } else { rtvDesc.ViewDimension = (NULL == m_msaaRt) ? D3D12_RTV_DIMENSION_TEXTURE2D : D3D12_RTV_DIMENSION_TEXTURE2DMS; rtvDesc.Texture2D.MipSlice = 0; rtvDesc.Texture2D.PlaneSlice = 0; } m_device->CreateRenderTargetView( NULL == m_msaaRt ? m_backBufferColor[ii] : m_msaaRt , &rtvDesc , handle ); if (BX_ENABLED(BX_PLATFORM_XBOXONE) ) { ID3D12Resource* resource = m_backBufferColor[ii]; BX_ASSERT(DXGI_FORMAT_R8G8B8A8_UNORM == m_scd.format, ""); const uint32_t size = m_scd.width*m_scd.height*4; void* ptr; DX_CHECK(resource->Map(0, NULL, &ptr) ); bx::memSet(ptr, 0, size); resource->Unmap(0, NULL); } } } D3D12_RESOURCE_DESC resourceDesc; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resourceDesc.Alignment = 1 < m_scd.sampleDesc.Count ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : 0; resourceDesc.Width = bx::uint32_max(m_resolution.width, 1); resourceDesc.Height = bx::uint32_max(m_resolution.height, 1); resourceDesc.DepthOrArraySize = 1; resourceDesc.MipLevels = 1; resourceDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; resourceDesc.SampleDesc = m_scd.sampleDesc; 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_commandList = m_cmd.alloc(); m_backBufferDepthStencil = createCommittedResource(m_device, HeapProperty::Default, &resourceDesc, &clearValue); m_device->CreateDepthStencilView(m_backBufferDepthStencil, NULL, getCPUHandleHeapStart(m_dsvDescriptorHeap)); setResourceBarrier(m_commandList , m_backBufferDepthStencil , D3D12_RESOURCE_STATE_COMMON , D3D12_RESOURCE_STATE_DEPTH_WRITE ); for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].postReset(); } if (NULL != m_msaaRt) { setResourceBarrier(m_commandList , m_msaaRt , D3D12_RESOURCE_STATE_COMMON , D3D12_RESOURCE_STATE_RESOLVE_SOURCE ); } // capturePostReset(); } void invalidateCache() { m_pipelineStateCache.invalidate(); m_samplerStateCache.invalidate(); m_samplerAllocator.reset(); } void updateMsaa(DXGI_FORMAT _format) const { 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; bx::memSet(&data, 0, sizeof(msaa) ); data.Format = _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) ); 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]; } } } IUnknown* getDeviceForSwapChain() const { # if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT return m_cmd.m_commandQueue; # else return m_device; # endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT } bool updateResolution(const Resolution& _resolution) { if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) ) { m_maxAnisotropy = D3D12_REQ_MAXANISOTROPY; } else { m_maxAnisotropy = 1; } bool depthClamp = !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP); if (m_depthClamp != depthClamp) { m_depthClamp = depthClamp; m_pipelineStateCache.invalidate(); } const uint32_t maskFlags = ~(0 | BGFX_RESET_MAXANISOTROPY | BGFX_RESET_DEPTH_CLAMP | BGFX_RESET_SUSPEND ); if (m_resolution.width != _resolution.width || m_resolution.height != _resolution.height || m_resolution.format != _resolution.format || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) ) { uint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); bool resize = true && BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) && (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (_resolution.reset&BGFX_RESET_MSAA_MASK) ; m_resolution = _resolution; m_resolution.reset = flags; m_textVideoMem.resize(false, _resolution.width, _resolution.height); m_textVideoMem.clear(); m_scd.width = _resolution.width; m_scd.height = _resolution.height; m_scd.format = s_textureFormat[_resolution.format].m_fmt; preReset(); DX_RELEASE(m_msaaRt, 0); if (NULL == m_swapChain) { } else { if (resize) { #if BX_PLATFORM_WINDOWS uint32_t nodeMask[] = { 1, 1, 1, 1 }; BX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(nodeMask) ); IUnknown* presentQueue[] ={ m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue }; BX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(presentQueue) ); DX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd, nodeMask, presentQueue) ); #elif BX_PLATFORM_WINRT DX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd)); m_backBufferColorIdx = m_scd.bufferCount-1; #endif // BX_PLATFORM_WINDOWS } else { updateMsaa(m_scd.format); m_scd.sampleDesc = s_msaa[(m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; DX_RELEASE(m_swapChain, 0); HRESULT hr; #if BX_PLATFORM_LINUX hr = E_FAIL; #else hr = m_dxgi.createSwapChain( getDeviceForSwapChain() , m_scd , &m_swapChain ); #endif // BX_PLATFORM_LINUX BGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain."); } if (1 < m_scd.sampleDesc.Count) { D3D12_RESOURCE_DESC resourceDesc; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resourceDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; resourceDesc.Width = m_scd.width; resourceDesc.Height = m_scd.height; resourceDesc.MipLevels = 1; resourceDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) ? s_textureFormat[m_resolution.format].m_fmtSrgb : s_textureFormat[m_resolution.format].m_fmt; resourceDesc.SampleDesc = m_scd.sampleDesc; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; resourceDesc.DepthOrArraySize = 1; D3D12_CLEAR_VALUE clearValue; clearValue.Format = resourceDesc.Format; clearValue.Color[0] = 0.0f; clearValue.Color[1] = 0.0f; clearValue.Color[2] = 0.0f; clearValue.Color[3] = 0.0f; m_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true); setDebugObjectName(m_msaaRt, "MSAA Backbuffer"); } } postReset(); } return false; } void setShaderUniform(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs) { if (_flags&kUniformFragmentBit) { bx::memCopy(&m_fsScratch[_regIndex], _val, _numRegs*16); } else { bx::memCopy(&m_vsScratch[_regIndex], _val, _numRegs*16); } } void setShaderUniform4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs) { setShaderUniform(_flags, _regIndex, _val, _numRegs); } void setShaderUniform4x4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs) { setShaderUniform(_flags, _regIndex, _val, _numRegs); } void commitShaderConstants(ProgramHandle _program, D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress) { const ProgramD3D12& program = m_program[_program.idx]; uint32_t total = bx::strideAlign(0 + program.m_vsh->m_size + (NULL != program.m_fsh ? program.m_fsh->m_size : 0) , D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT ); uint8_t* data = (uint8_t*)m_scratchBuffer[m_backBufferColorIdx].allocCbv(_gpuAddress, total); { uint32_t size = program.m_vsh->m_size; bx::memCopy(data, m_vsScratch, size); data += size; } if (NULL != program.m_fsh) { bx::memCopy(data, m_fsScratch, program.m_fsh->m_size); } } D3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh) { FrameBufferD3D12& frameBuffer = m_frameBuffers[_fbh.idx]; if (NULL != frameBuffer.m_swapChain) { #if BX_PLATFORM_WINDOWS uint8_t idx = uint8_t(frameBuffer.m_swapChain->GetCurrentBackBufferIndex() ); frameBuffer.setState(m_commandList, idx, D3D12_RESOURCE_STATE_RENDER_TARGET); return getRtv(_fbh, idx); #endif // BX_PLATFORM_WINDOWS } return getRtv(_fbh, 0); } D3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh, uint8_t _attachment) { D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = getCPUHandleHeapStart(m_rtvDescriptorHeap); uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_CPU_DESCRIPTOR_HANDLE result = { rtvDescriptor.ptr + (BX_COUNTOF(m_backBufferColor) + _fbh.idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + _attachment) * rtvDescriptorSize }; return result; } D3D12_CPU_DESCRIPTOR_HANDLE getDsv(FrameBufferHandle _fbh) const { D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(m_dsvDescriptorHeap); uint32_t dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); D3D12_CPU_DESCRIPTOR_HANDLE result = { dsvDescriptor.ptr + (1 + _fbh.idx) * dsvDescriptorSize }; return result; } void setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true) { if (isValid(m_fbh) && m_fbh.idx != _fbh.idx) { FrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx]; if (m_rtMsaa) frameBuffer.resolve(); if (NULL == frameBuffer.m_swapChain) { 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 writeOnly = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY); if (!writeOnly) { texture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_READ); } } } } if (!isValid(_fbh) ) { if (NULL != m_swapChain) { m_rtvHandle = getCPUHandleHeapStart(m_rtvDescriptorHeap); uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize; m_dsvHandle = getCPUHandleHeapStart(m_dsvDescriptorHeap); m_currentColor = &m_rtvHandle; m_currentDepthStencil = &m_dsvHandle; m_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil); } } else { FrameBufferD3D12& frameBuffer = m_frameBuffers[_fbh.idx]; if (0 < frameBuffer.m_num) { m_rtvHandle = getRtv(_fbh); m_currentColor = &m_rtvHandle; } else { m_currentColor = NULL; } if (isValid(frameBuffer.m_depth) ) { m_dsvHandle = getDsv(_fbh); m_currentDepthStencil = &m_dsvHandle; } else { m_currentDepthStencil = NULL; } if (NULL != frameBuffer.m_swapChain) { frameBuffer.m_needPresent = true; } else { 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 , m_currentDepthStencil ); } { default: case D3D12_UAV_DIMENSION_TEXTURE2D: uavd->Texture2D.MipSlice = _mip; break; case D3D12_UAV_DIMENSION_TEXTURE3D: _desc.IndependentBlendEnable = !!(BGFX_STATE_BLEND_INDEPENDENT & _state); D3D12_RENDER_TARGET_BLEND_DESC* drt = &_desc.RenderTarget[0]; drt->BlendEnable = !!(BGFX_STATE_BLEND_MASK & _state); drt->LogicOpEnable = false; { 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]; } uint8_t writeMask = 0; writeMask |= (_state & BGFX_STATE_WRITE_R) ? D3D12_COLOR_WRITE_ENABLE_RED : 0; writeMask |= (_state & BGFX_STATE_WRITE_G) ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0; writeMask |= (_state & BGFX_STATE_WRITE_B) ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0; writeMask |= (_state & BGFX_STATE_WRITE_A) ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0; drt->LogicOp = D3D12_LOGIC_OP_CLEAR; 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); drt->LogicOpEnable = false; 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->LogicOp = D3D12_LOGIC_OP_CLEAR; drt->RenderTargetWriteMask = writeMask; } } else { for (uint32_t ii = 1; ii < BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS; ++ii) { bx::memCopy(&_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 = !!(_state&BGFX_STATE_FRONT_CCW);; _desc.DepthBias = 0; _desc.DepthBiasClamp = 0.0f; _desc.SlopeScaledDepthBias = 0.0f; _desc.DepthClipEnable = !m_depthClamp; _desc.MultisampleEnable = !!(_state&BGFX_STATE_MSAA); _desc.AntialiasedLineEnable = !!(_state&BGFX_STATE_LINEAA); _desc.ForcedSampleCount = 0; _desc.ConservativeRaster = !!(_state&BGFX_STATE_CONSERVATIVE_RASTER) ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON : 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); bx::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_WRITE_Z & _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, uint8_t _numStreams, const VertexLayout** _layouts, const ProgramD3D12& _program, uint16_t _numInstanceData) { uint16_t attrMask[Attrib::Count]; bx::memCopy(attrMask, _program.m_vsh->m_attrMask, sizeof(attrMask)); D3D12_INPUT_ELEMENT_DESC* elem = _vertexElements; for (uint8_t stream = 0; stream < _numStreams; ++stream) { VertexLayout layout; bx::memCopy(&layout, _layouts[stream], sizeof(VertexLayout)); const bool last = stream == _numStreams-1; for (uint32_t ii = 0; ii < Attrib::Count; ++ii) { uint16_t mask = attrMask[ii]; uint16_t attr = (layout.m_attributes[ii] & mask); if (0 == attr || UINT16_MAX == attr) { layout.m_attributes[ii] = last ? ~attr : UINT16_MAX; } else { attrMask[ii] = 0; } } elem = fillVertexLayout(stream, elem, layout); } 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 == bx::strCmp(curr->SemanticName, "TEXCOORD") && curr->SemanticIndex == index) { break; } } if (jj == num) { curr = elem; ++elem; } bx::memCopy(curr, &inst, sizeof(D3D12_INPUT_ELEMENT_DESC) ); curr->InputSlot = _numStreams; curr->SemanticIndex = index; curr->AlignedByteOffset = ii*16; } return uint32_t(elem-_vertexElements); } uint32_t setInputLayout(D3D12_INPUT_ELEMENT_DESC* _vertexElements, const VertexLayout& _layout, const ProgramD3D12& _program, uint16_t _numInstanceData) { const VertexLayout* layouts[1] = { &_layout }; return setInputLayout(_vertexElements, BX_COUNTOF(layouts), layouts, _program, _numInstanceData); } 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]) { for (uint32_t jj = 1; jj < operand.numAddrModes; ++jj) { if (DxbcOperandAddrMode::Imm32 == operand.addrMode[jj] || DxbcOperandAddrMode::RegImm32 == operand.addrMode[jj]) { operand.regIndex[jj] += cast.offset; } else if (0 != cast.offset) { operand.subOperand[jj].regIndex = operand.regIndex[jj]; operand.addrMode[jj] = DxbcOperandAddrMode::RegImm32; operand.regIndex[jj] = cast.offset; } } } } } } ID3D12PipelineState* getPipelineState(ProgramHandle _program) { ProgramD3D12& program = m_program[_program.idx]; const uint32_t hash = program.m_vsh->m_hash; ID3D12PipelineState* pso = m_pipelineStateCache.find(hash); if (BX_LIKELY(NULL != pso) ) { return pso; } D3D12_COMPUTE_PIPELINE_STATE_DESC desc; bx::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; desc.NodeMask = 1; desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; uint32_t length = g_callback->cacheReadSize(hash); const 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 cached compute PSO (size %d).", length); bx::MemoryReader reader(cachedData, length); desc.CachedPSO.pCachedBlob = reader.getDataPtr(); desc.CachedPSO.CachedBlobSizeInBytes = (size_t)reader.remaining(); HRESULT hr = m_device->CreateComputePipelineState(&desc , IID_ID3D12PipelineState , (void**)&pso ); if (FAILED(hr) ) { BX_TRACE("Failed to load cached compute PSO (HRESULT 0x%08x).", hr); bx::memSet(&desc.CachedPSO, 0, sizeof(desc.CachedPSO) ); } } } if
{'commit': 'diff --git a/examples/common/bgfx_utils.cpp b/examples/common/bgfx_utils.cpp\nindex b874e6a0b..e9c56ea5e 100644\n--- a/examples/common/bgfx_utils.cpp\n+++ b/examples/common/bgfx_utils.cpp\n@@ -131,7 +131,11 @@ bgfx::ShaderHandle loadShader(const char* _name)\n bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName)\n {\n \tbgfx::ShaderHandle vsh = loadShader(_reader, _vsName);\n-\tbgfx::ShaderHandle fsh = loadShader(_reader, _fsName);\n+\tbgfx::ShaderHandle fsh = BGFX_INVALID_HANDLE;\n+\tif (NULL != _fsName)\n+\t{\n+\t\tfsh = loadShader(_reader, _fsName);\n+\t}\n \n \treturn bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */);\n }\ndiff --git a/src/bgfx.cpp b/src/bgfx.cpp\nindex 072f43393..f0332bc20 100644\n--- a/src/bgfx.cpp\n+++ b/src/bgfx.cpp\n@@ -2507,28 +2507,18 @@ again:\n \tProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh, bool _destroyShaders)\n \t{\n \t\tBGFX_CHECK_MAIN_THREAD();\n-\t\tProgramHandle handle = s_ctx->createProgram(_vsh, _fsh);\n-\n-\t\tif (_destroyShaders)\n+\t\tif (!isValid(_fsh) )\n \t\t{\n-\t\t\tdestroyShader(_vsh);\n-\t\t\tdestroyShader(_fsh);\n+\t\t\treturn createProgram(_vsh, _destroyShaders);\n \t\t}\n \n-\t\treturn handle;\n+\t\treturn s_ctx->createProgram(_vsh, _fsh, _destroyShaders);\n \t}\n \n \tProgramHandle createProgram(ShaderHandle _csh, bool _destroyShader)\n \t{\n \t\tBGFX_CHECK_MAIN_THREAD();\n-\t\tProgramHandle handle = s_ctx->createProgram(_csh);\n-\n-\t\tif (_destroyShader)\n-\t\t{\n-\t\t\tdestroyShader(_csh);\n-\t\t}\n-\n-\t\treturn handle;\n+\t\treturn s_ctx->createProgram(_csh, _destroyShader);\n \t}\n \n \tvoid destroyProgram(ProgramHandle _handle)\ndiff --git a/src/bgfx_p.h b/src/bgfx_p.h\nindex 60029d1c8..1d75ef873 100644\n--- a/src/bgfx_p.h\n+++ b/src/bgfx_p.h\n@@ -2603,6 +2603,7 @@ namespace bgfx\n \t\t\t\tsr.m_refCount = 1;\n \t\t\t\tsr.m_hash     = iohash;\n \t\t\t\tsr.m_num      = 0;\n+\t\t\t\tsr.m_owned    = false;\n \t\t\t\tsr.m_uniforms = NULL;\n \n \t\t\t\tUniformHandle* uniforms = (UniformHandle*)alloca(count*sizeof(UniformHandle) );\n@@ -2682,6 +2683,16 @@ namespace bgfx\n \t\t\tshaderDecRef(_handle);\n \t\t}\n \n+\t\tvoid shaderTakeOwnership(ShaderHandle _handle)\n+\t\t{\n+\t\t\tShaderRef& sr = m_shaderRef[_handle.idx];\n+\t\t\tif (!sr.m_owned)\n+\t\t\t{\n+\t\t\t\tsr.m_owned = true;\n+\t\t\t\tshaderDecRef(_handle);\n+\t\t\t}\n+\t\t}\n+\n \t\tvoid shaderIncRef(ShaderHandle _handle)\n \t\t{\n \t\t\tShaderRef& sr = m_shaderRef[_handle.idx];\n@@ -2712,7 +2723,7 @@ namespace bgfx\n \t\t\t}\n \t\t}\n \n-\t\tBGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh) )\n+\t\tBGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, ShaderHandle _fsh, bool _destroyShaders) )\n \t\t{\n \t\t\tif (!isValid(_vsh)\n \t\t\t||  !isValid(_fsh) )\n@@ -2749,10 +2760,16 @@ namespace bgfx\n \t\t\t\tcmdbuf.write(_fsh);\n \t\t\t}\n \n+\t\t\tif (_destroyShaders)\n+\t\t\t{\n+\t\t\t\tshaderTakeOwnership(_vsh);\n+\t\t\t\tshaderTakeOwnership(_fsh);\n+\t\t\t}\n+\n \t\t\treturn handle;\n \t\t}\n \n-\t\tBGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh) )\n+\t\tBGFX_API_FUNC(ProgramHandle createProgram(ShaderHandle _vsh, bool _destroyShader) )\n \t\t{\n \t\t\tif (!isValid(_vsh) )\n \t\t\t{\n@@ -2779,6 +2796,11 @@ namespace bgfx\n \t\t\t\tcmdbuf.write(fsh);\n \t\t\t}\n \n+\t\t\tif (_destroyShader)\n+\t\t\t{\n+\t\t\t\tshaderTakeOwnership(_vsh);\n+\t\t\t}\n+\n \t\t\treturn handle;\n \t\t}\n \n@@ -3564,6 +3586,7 @@ namespace bgfx\n \t\t\tuint32_t m_hash;\n \t\t\tint16_t  m_refCount;\n \t\t\tuint16_t m_num;\n+\t\t\tbool     m_owned;\n \t\t};\n \n \t\tstruct ProgramRef\ndiff --git a/src/renderer_d3d.h b/src/renderer_d3d.h\nindex 99f50babd..d2882ae38 100644\n--- a/src/renderer_d3d.h\n+++ b/src/renderer_d3d.h\n@@ -100,15 +100,15 @@ namespace bgfx\n \tclass StateCacheT\n \t{\n \tpublic:\n-\t\tvoid add(uint64_t _id, Ty* _item)\n+\t\tvoid add(uint64_t _key, Ty* _value)\n \t\t{\n-\t\t\tinvalidate(_id);\n-\t\t\tm_hashMap.insert(stl::make_pair(_id, _item) );\n+\t\t\tinvalidate(_key);\n+\t\t\tm_hashMap.insert(stl::make_pair(_key, _value) );\n \t\t}\n \n-\t\tTy* find(uint64_t _id)\n+\t\tTy* find(uint64_t _key)\n \t\t{\n-\t\t\ttypename HashMap::iterator it = m_hashMap.find(_id);\n+\t\t\ttypename HashMap::iterator it = m_hashMap.find(_key);\n \t\t\tif (it != m_hashMap.end() )\n \t\t\t{\n \t\t\t\treturn it->second;\n@@ -117,9 +117,9 @@ namespace bgfx\n \t\t\treturn NULL;\n \t\t}\n \n-\t\tvoid invalidate(uint64_t _id)\n+\t\tvoid invalidate(uint64_t _key)\n \t\t{\n-\t\t\ttypename HashMap::iterator it = m_hashMap.find(_id);\n+\t\t\ttypename HashMap::iterator it = m_hashMap.find(_key);\n \t\t\tif (it != m_hashMap.end() )\n \t\t\t{\n \t\t\t\tDX_RELEASE_WARNONLY(it->second, 0);\n@@ -151,15 +151,15 @@ namespace bgfx\n \tclass StateCache\n \t{\n \tpublic:\n-\t\tvoid add(uint64_t _id, uint16_t _item)\n+\t\tvoid add(uint64_t _key, uint16_t _value)\n \t\t{\n-\t\t\tinvalidate(_id);\n-\t\t\tm_hashMap.insert(stl::make_pair(_id, _item) );\n+\t\t\tinvalidate(_key);\n+\t\t\tm_hashMap.insert(stl::make_pair(_key, _value) );\n \t\t}\n \n-\t\tuint16_t find(uint64_t _id)\n+\t\tuint16_t find(uint64_t _key)\n \t\t{\n-\t\t\tHashMap::iterator it = m_hashMap.find(_id);\n+\t\t\tHashMap::iterator it = m_hashMap.find(_key);\n \t\t\tif (it != m_hashMap.end() )\n \t\t\t{\n \t\t\t\treturn it->second;\n@@ -168,9 +168,9 @@ namespace bgfx\n \t\t\treturn UINT16_MAX;\n \t\t}\n \n-\t\tvoid invalidate(uint64_t _id)\n+\t\tvoid invalidate(uint64_t _key)\n \t\t{\n-\t\t\tHashMap::iterator it = m_hashMap.find(_id);\n+\t\t\tHashMap::iterator it = m_hashMap.find(_key);\n \t\t\tif (it != m_hashMap.end() )\n \t\t\t{\n \t\t\t\tm_hashMap.erase(it);\n@@ -196,33 +196,28 @@ namespace bgfx\n \tclass StateCacheLru\n \t{\n \tpublic:\n-\t\tvoid add(uint64_t _hash, Ty _value)\n+\t\tvoid add(uint64_t _key, Ty _value, uint16_t _parent)\n \t\t{\n \t\t\tuint16_t handle = m_alloc.alloc();\n \t\t\tif (UINT16_MAX == handle)\n \t\t\t{\n \t\t\t\tuint16_t back = m_alloc.getBack();\n-\t\t\t\tm_alloc.free(back);\n-\t\t\t\tHashMap::iterator it = m_hashMap.find(m_data[back].m_hash);\n-\t\t\t\tif (it != m_hashMap.end() )\n-\t\t\t\t{\n-\t\t\t\t\tm_hashMap.erase(it);\n-\t\t\t\t}\n-\n+\t\t\t\tinvalidate(back);\n \t\t\t\thandle = m_alloc.alloc();\n \t\t\t}\n \n \t\t\tBX_CHECK(UINT16_MAX != handle, "Failed to find handle.");\n \n \t\t\tData& data = m_data[handle];\n-\t\t\tdata.m_hash  = _hash;\n-\t\t\tdata.m_value = _value;\n-\t\t\tm_hashMap.insert(stl::make_pair(_hash, handle) );\n+\t\t\tdata.m_hash   = _key;\n+\t\t\tdata.m_value  = _value;\n+\t\t\tdata.m_parent = _parent;\n+\t\t\tm_hashMap.insert(stl::make_pair(_key, handle) );\n \t\t}\n \n-\t\tTy* find(uint64_t _hash)\n+\t\tTy* find(uint64_t _key)\n \t\t{\n-\t\t\tHashMap::iterator it = m_hashMap.find(_hash);\n+\t\t\tHashMap::iterator it = m_hashMap.find(_key);\n \t\t\tif (it != m_hashMap.end() )\n \t\t\t{\n \t\t\t\tuint16_t handle = it->second;\n@@ -233,8 +228,59 @@ namespace bgfx\n \t\t\treturn NULL;\n \t\t}\n \n+\t\tvoid invalidate(uint64_t _key)\n+\t\t{\n+\t\t\tHashMap::iterator it = m_hashMap.find(_key);\n+\t\t\tif (it != m_hashMap.end() )\n+\t\t\t{\n+\t\t\t\tuint16_t handle = it->second;\n+\t\t\t\tm_alloc.free(_handle);\n+\t\t\t\tm_hashMap.erase(it);\n+\t\t\t\trelease(m_data[handle].m_value);\n+\t\t\t}\n+\t\t}\n+\n+\t\tvoid invalidate(uint16_t _handle)\n+\t\t{\n+\t\t\tif (m_alloc.isValid(_handle) )\n+\t\t\t{\n+\t\t\t\tm_alloc.free(_handle);\n+\t\t\t\tData& data = m_data[_handle];\n+\t\t\t\tm_hashMap.erase(m_hashMap.find(data.m_hash) );\n+\t\t\t\trelease(data.m_value);\n+\t\t\t}\n+\t\t}\n+\n+\t\tvoid invalidateWithParent(uint16_t _parent)\n+\t\t{\n+\t\t\tfor (uint32_t ii = 0; ii < m_alloc.getNumHandles();)\n+\t\t\t{\n+\t\t\t\tuint16_t handle = m_alloc.getHandleAt(ii);\n+\t\t\t\tData& data = m_data[handle];\n+\n+\t\t\t\tif (data.m_parent == _parent)\n+\t\t\t\t{\n+\t\t\t\t\tm_alloc.free(handle);\n+\t\t\t\t\tData& data = m_data[handle];\n+\t\t\t\t\tm_hashMap.erase(m_hashMap.find(data.m_hash) );\n+\t\t\t\t\trelease(data.m_value);\n+\t\t\t\t}\n+\t\t\t\telse\n+\t\t\t\t{\n+\t\t\t\t\t++ii;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n \t\tvoid invalidate()\n \t\t{\n+\t\t\tfor (uint32_t ii = 0, num =  m_alloc.getNumHandles(); ii < num; ++ii)\n+\t\t\t{\n+\t\t\t\tuint16_t handle = m_alloc.getHandleAt(ii);\n+\t\t\t\tData& data = m_data[handle];\n+\t\t\t\trelease(data.m_value);\n+\t\t\t}\n+\n \t\t\tm_hashMap.clear();\n \t\t\tm_alloc.reset();\n \t\t}\n@@ -244,6 +290,17 @@ namespace bgfx\n \t\t\treturn uint32_t(m_hashMap.size() );\n \t\t}\n \n+\t\ttemplate<typename Ty>\n+\t\tvoid release(Ty)\n+\t\t{\n+\t\t}\n+\n+\t\ttemplate<>\n+\t\tvoid release<IUnknown*>(IUnknown* _ptr)\n+\t\t{\n+\t\t\tDX_RELEASE(_ptr, 0);\n+\t\t}\n+\n \tprivate:\n \t\ttypedef stl::unordered_map<uint64_t, uint16_t> HashMap;\n \t\tHashMap m_hashMap;\n@@ -252,6 +309,7 @@ namespace bgfx\n \t\t{\n \t\t\tuint64_t m_hash;\n \t\t\tTy m_value;\n+\t\t\tuint16_t m_parent;\n \t\t};\n \n \t\tData m_data[MaxHandleT];\ndiff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp\nindex 0d3b7ca81..718e7f87d 100644\n--- a/src/renderer_d3d11.cpp\n+++ b/src/renderer_d3d11.cpp\n@@ -680,7 +680,7 @@ namespace bgfx { namespace d3d11\n \t\t\t\t\tuint32_t flags = 0\n \t\t\t\t\t\t| D3D11_CREATE_DEVICE_SINGLETHREADED\n \t\t\t\t\t\t| D3D11_CREATE_DEVICE_BGRA_SUPPORT\n-//\t\t\t\t\t\t| D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS\n+\t\t\t\t\t\t| D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS\n \t\t\t\t\t\t| (BX_ENABLED(BGFX_CONFIG_DEBUG) ? D3D11_CREATE_DEVICE_DEBUG : 0)\n \t\t\t\t\t\t;\n \n@@ -1777,6 +1777,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t\t\tm_depthStencilStateCache.invalidate();\n \t\t\tm_rasterizerStateCache.invalidate();\n \t\t\tm_samplerStateCache.invalidate();\n+\t\t\tm_srvUavLru.invalidate();\n \t\t}\n \n \t\tvoid invalidateCompute()\n@@ -2394,6 +2395,101 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t\t\tcommitTextureStage();\n \t\t}\n \n+\t\tID3D11UnorderedAccessView* getCachedUav(TextureHandle _handle, uint8_t _mip)\n+\t\t{\n+\t\t\tbx::HashMurmur2A murmur;\n+\t\t\tmurmur.begin();\n+\t\t\tmurmur.add(_handle);\n+\t\t\tmurmur.add(_mip);\n+\t\t\tmurmur.add(0);\n+\t\t\tuint32_t hash = murmur.end();\n+\n+\t\t\tIUnknown** ptr = m_srvUavLru.find(hash);\n+\t\t\tID3D11UnorderedAccessView* uav;\n+\t\t\tif (NULL == ptr)\n+\t\t\t{\n+\t\t\t\tTextureD3D11& texture = m_textures[_handle.idx];\n+\n+\t\t\t\tD3D11_UNORDERED_ACCESS_VIEW_DESC desc;\n+\t\t\t\tdesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtSrv;\n+\t\t\t\tswitch (texture.m_type)\n+\t\t\t\t{\n+\t\t\t\tcase TextureD3D11::Texture2D:\n+\t\t\t\tcase TextureD3D11::TextureCube:\n+\t\t\t\t\tdesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;\n+\t\t\t\t\tdesc.Texture2D.MipSlice = _mip;\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tcase TextureD3D11::Texture3D:\n+\t\t\t\t\tdesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;\n+\t\t\t\t\tdesc.Texture3D.MipSlice    = _mip;\n+\t\t\t\t\tdesc.Texture3D.FirstWSlice = 0;\n+\t\t\t\t\tdesc.Texture3D.WSize       = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\t\tDX_CHECK(m_device->CreateUnorderedAccessView(texture.m_ptr, &desc, &uav) );\n+\n+\t\t\t\tm_srvUavLru.add(hash, uav, _handle.idx);\n+\t\t\t}\n+\t\t\telse\n+\t\t\t{\n+\t\t\t\tuav = static_cast<ID3D11UnorderedAccessView*>(*ptr);\n+\t\t\t}\n+\n+\t\t\treturn uav;\n+\t\t}\n+\n+\t\tID3D11ShaderResourceView* getCachedSrv(TextureHandle _handle, uint8_t _mip)\n+\t\t{\n+\t\t\tbx::HashMurmur2A murmur;\n+\t\t\tmurmur.begin();\n+\t\t\tmurmur.add(_handle);\n+\t\t\tmurmur.add(_mip);\n+\t\t\tmurmur.add(0);\n+\t\t\tuint32_t hash = murmur.end();\n+\n+\t\t\tIUnknown** ptr = m_srvUavLru.find(hash);\n+\t\t\tID3D11ShaderResourceView* srv;\n+\t\t\tif (NULL == ptr)\n+\t\t\t{\n+\t\t\t\tTextureD3D11& texture = m_textures[_handle.idx];\n+\n+\t\t\t\tD3D11_SHADER_RESOURCE_VIEW_DESC desc;\n+\t\t\t\tdesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtSrv;\n+\t\t\t\tswitch (texture.m_type)\n+\t\t\t\t{\n+\t\t\t\tcase TextureD3D11::Texture2D:\n+\t\t\t\t\tdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;\n+\t\t\t\t\tdesc.Texture2D.MostDetailedMip = _mip;\n+\t\t\t\t\tdesc.Texture2D.MipLevels       = 1;\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tcase TextureD3D11::TextureCube:\n+\t\t\t\t\tdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;\n+\t\t\t\t\tdesc.TextureCube.MostDetailedMip = _mip;\n+\t\t\t\t\tdesc.TextureCube.MipLevels       = 1;\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tcase TextureD3D11::Texture3D:\n+\t\t\t\t\tdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;\n+\t\t\t\t\tdesc.Texture3D.MostDetailedMip = _mip;\n+\t\t\t\t\tdesc.Texture3D.MipLevels       = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\t\tDX_CHECK(m_device->CreateShaderResourceView(texture.m_ptr, &desc, &srv) );\n+\n+\t\t\t\tm_srvUavLru.add(hash, srv, _handle.idx);\n+\t\t\t}\n+\t\t\telse\n+\t\t\t{\n+\t\t\t\tsrv = static_cast<ID3D11ShaderResourceView*>(*ptr);\n+\t\t\t}\n+\n+\t\t\treturn srv;\n+\t\t}\n+\n \t\tvoid ovrPostReset()\n \t\t{\n #if BGFX_CONFIG_USE_OVR\n@@ -2838,6 +2934,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t\tStateCacheT<ID3D11InputLayout> m_inputLayoutCache;\n \t\tStateCacheT<ID3D11RasterizerState> m_rasterizerStateCache;\n \t\tStateCacheT<ID3D11SamplerState> m_samplerStateCache;\n+\t\tStateCacheLru<IUnknown*, 1024> m_srvUavLru;\n \n \t\tTextVideoMem m_textVideoMem;\n \n@@ -3307,7 +3404,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t\t\tconst bool swizzle    = TextureFormat::BGRA8 == m_textureFormat && 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE);\n \n \t\t\tBX_TRACE("Texture %3d: %s (requested: %s), %dx%d%s%s%s."\n-\t\t\t\t, this - s_renderD3D11->m_textures\n+\t\t\t\t, getHandle()\n \t\t\t\t, getName( (TextureFormat::Enum)m_textureFormat)\n \t\t\t\t, getName( (TextureFormat::Enum)m_requestedFormat)\n \t\t\t\t, textureWidth\n@@ -3504,6 +3601,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \n \tvoid TextureD3D11::destroy()\n \t{\n+\t\ts_renderD3D11->m_srvUavLru.invalidateWithParent(getHandle().idx);\n \t\tDX_RELEASE(m_srv, 0);\n \t\tDX_RELEASE(m_uav, 0);\n \t\tDX_RELEASE(m_ptr, 0);\n@@ -3560,6 +3658,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t{\n \t}\n \n+\tTextureHandle TextureD3D11::getHandle() const\n+\t{\n+\t\tTextureHandle handle = { (uint16_t)(this - s_renderD3D11->m_textures) };\n+\t\treturn handle;\n+\t}\n+\n \tvoid FrameBufferD3D11::create(uint8_t _num, const TextureHandle* _handles)\n \t{\n \t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_rtv); ++ii)\n@@ -4074,14 +4178,20 @@ BX_PRAGMA_DIAGNOSTIC_POP();\n \t\t\t\t\t\t\t{\n \t\t\t\t\t\t\tcase Binding::Image:\n \t\t\t\t\t\t\t\t{\n-\t\t\t\t\t\t\t\t\tconst TextureD3D11& texture = m_textures[bind.m_idx];\n+\t\t\t\t\t\t\t\t\tTextureD3D11& texture = m_textures[bind.m_idx];\n \t\t\t\t\t\t\t\t\tif (Access::Read != bind.m_un.m_compute.m_access)\n \t\t\t\t\t\t\t\t\t{\n-\t\t\t\t\t\t\t\t\t\tuav[ii] = texture.m_uav;\n+\t\t\t\t\t\t\t\t\t\tuav[ii] = 0 == bind.m_un.m_compute.m_mip\n+\t\t\t\t\t\t\t\t\t\t\t? texture.m_uav\n+\t\t\t\t\t\t\t\t\t\t\t: s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_un.m_compute.m_mip)\n+\t\t\t\t\t\t\t\t\t\t\t;\n \t\t\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\t\telse\n \t\t\t\t\t\t\t\t\t{\n-\t\t\t\t\t\t\t\t\t\tsrv[ii]     = texture.m_srv;\n+\t\t\t\t\t\t\t\t\t\tsrv[ii] = 0 == bind.m_un.m_compute.m_mip\n+\t\t\t\t\t\t\t\t\t\t\t? texture.m_srv\n+\t\t\t\t\t\t\t\t\t\t\t: s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_un.m_compute.m_mip)\n+\t\t\t\t\t\t\t\t\t\t\t;\n \t\t\t\t\t\t\t\t\t\tsampler[ii] = texture.m_sampler;\n \t\t\t\t\t\t\t\t\t}\n \t\t\t\t\t\t\t\t}\ndiff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h\nindex d8ced4a63..fec302a62 100644\n--- a/src/renderer_d3d11.h\n+++ b/src/renderer_d3d11.h\n@@ -284,6 +284,7 @@ namespace bgfx { namespace d3d11\n \t\tvoid update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);\n \t\tvoid commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS);\n \t\tvoid resolve();\n+\t\tTextureHandle getHandle() const;\n \n \t\tunion\n \t\t{\ndiff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp\nindex 438dff26d..4e533f61a 100644\n--- a/src/renderer_d3d12.cpp\n+++ b/src/renderer_d3d12.cpp\n@@ -2589,7 +2589,8 @@ data.NumQualityLevels = 0;\n \t\t\t{\n \t\t\tdefault:\n \t\t\tcase D3D12_UAV_DIMENSION_TEXTURE2D:\n-\t\t\t\tuavd->Texture2D.MipSlice = _mip;\n+\t\t\t\tuavd->Texture2D.MipSlice   = _mip;\n+\t\t\t\tuavd->Texture2D.PlaneSlice = 0;\n \t\t\t\tbreak;\n \n \t\t\tcase D3D12_UAV_DIMENSION_TEXTURE3D:\n@@ -4111,7 +4112,7 @@ data.NumQualityLevels = 0;\n \n \t\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]);\n \n-\t\t\t\t\t\t\t\tbindLru.add(bindHash, srvHandle[0]);\n+\t\t\t\t\t\t\t\tbindLru.add(bindHash, srvHandle[0], 0);\n \t\t\t\t\t\t\t}\n \t\t\t\t\t\t}\n \t\t\t\t\t\telse \n', 'commit_subject': 'D3D11: Fixed compute image mip selection.', 'repo_name': 'bkaradzic/bgfx', 'committer': {'name': 'Branimir Karadžić', 'email': 'a51d32610a255449bd8868a3bbd33941625e0ee1@gmail.com', 'time_sec': '1439687263', 'tz_offset': '-420', 'date': {'seconds': '1439687263'}}, 'commit_tree': '076abe063ed526564d968b71177c56a71fd2d7cf', 'commit_message': 'D3D11: Fixed compute image mip selection.\n', 'language_name': 'C#', 'license': 'bsd-2-clause', 'hunks': '@@ -2589,7 +2589,8 @@ data.NumQualityLevels = 0;\n \t\t\t{\n \t\t\tdefault:\n \t\t\tcase D3D12_UAV_DIMENSION_TEXTURE2D:\n-\t\t\t\tuavd->Texture2D.MipSlice = _mip;\n+\t\t\t\tuavd->Texture2D.MipSlice   = _mip;\n+\t\t\t\tuavd->Texture2D.PlaneSlice = 0;\n \t\t\t\tbreak;\n \n \t\t\tcase D3D12_UAV_DIMENSION_TEXTURE3D:\n@@ -4111,7 +4112,7 @@ data.NumQualityLevels = 0;\n \n \t\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]);\n \n-\t\t\t\t\t\t\t\tbindLru.add(bindHash, srvHandle[0]);\n+\t\t\t\t\t\t\t\tbindLru.add(bindHash, srvHandle[0], 0);\n \t\t\t\t\t\t\t}\n \t\t\t\t\t\t}\n \t\t\t\t\t\telse \n', 'addition_count': 3, 'deletion_count': 2, 'src_file': 'a/src/renderer_d3d12.cpp', 'tgt_file': 'b/src/renderer_d3d12.cpp', 'file_extension': '.cpp', 'before_file': '/*\n * Copyright 2011-2022 Branimir Karadzic. All rights reserved.\n * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE\n */\n\n#include "bgfx_p.h"\n\n#if BGFX_CONFIG_RENDERER_DIRECT3D12\n#\tinclude "renderer_d3d12.h"\n\n#if !BX_PLATFORM_WINDOWS && !BX_PLATFORM_LINUX\n#\tinclude <inspectable.h>\n#\tif BX_PLATFORM_WINRT\n#\t\tinclude <windows.ui.xaml.media.dxinterop.h>\n#\tendif // BX_PLATFORM_WINRT\n#endif // !BX_PLATFORM_WINDOWS\n\n#if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\nPFN_PIX_GET_THREAD_INFO      bgfx_PIXGetThreadInfo;\nPFN_PIX_EVENTS_REPLACE_BLOCK bgfx_PIXEventsReplaceBlock;\n#endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\nnamespace bgfx { namespace d3d12\n{\n\tstatic char s_viewName[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME];\n\n\tinline void setViewType(ViewId _view, const bx::StringView _str)\n\t{\n\t\tif (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION || BGFX_CONFIG_PROFILER) )\n\t\t{\n\t\t\tbx::memCopy(&s_viewName[_view][3], _str.getPtr(), _str.getLength() );\n\t\t}\n\t}\n\n\tstruct PrimInfo\n\t{\n\t\tD3D_PRIMITIVE_TOPOLOGY m_topology;\n\t\tD3D12_PRIMITIVE_TOPOLOGY_TYPE m_topologyType;\n\t\tuint32_t m_min;\n\t\tuint32_t m_div;\n\t\tuint32_t m_sub;\n\t};\n\n\tstatic const PrimInfo s_primInfo[] =\n\t{\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,  D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,  3, 3, 0 },\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,  3, 1, 2 },\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_LINELIST,      D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,      2, 2, 0 },\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,     D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE,      2, 1, 1 },\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_POINTLIST,     D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT,     1, 1, 0 },\n\t\t{ D3D_PRIMITIVE_TOPOLOGY_UNDEFINED,     D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED, 0, 0, 0 },\n\t};\n\tBX_STATIC_ASSERT(Topology::Count == BX_COUNTOF(s_primInfo)-1);\n\n\tstatic const uint32_t s_checkMsaa[] =\n\t{\n\t\t0,\n\t\t2,\n\t\t4,\n\t\t8,\n\t\t16,\n\t};\n\n\tstatic DXGI_SAMPLE_DESC s_msaa[] =\n\t{\n\t\t{  1, 0 },\n\t\t{  2, 0 },\n\t\t{  4, 0 },\n\t\t{  8, 0 },\n\t\t{ 16, 0 },\n\t};\n\n\tstatic const D3D12_BLEND s_blendFactor[][2] =\n\t{\n\t\t{ D3D12_BLEND(0),               D3D12_BLEND(0)               }, // ignored\n\t\t{ D3D12_BLEND_ZERO,             D3D12_BLEND_ZERO             }, // ZERO\n\t\t{ D3D12_BLEND_ONE,              D3D12_BLEND_ONE              }, // ONE\n\t\t{ D3D12_BLEND_SRC_COLOR,        D3D12_BLEND_SRC_ALPHA        }, // SRC_COLOR\n\t\t{ D3D12_BLEND_INV_SRC_COLOR,    D3D12_BLEND_INV_SRC_ALPHA    }, // INV_SRC_COLOR\n\t\t{ D3D12_BLEND_SRC_ALPHA,        D3D12_BLEND_SRC_ALPHA        }, // SRC_ALPHA\n\t\t{ D3D12_BLEND_INV_SRC_ALPHA,    D3D12_BLEND_INV_SRC_ALPHA    }, // INV_SRC_ALPHA\n\t\t{ D3D12_BLEND_DEST_ALPHA,       D3D12_BLEND_DEST_ALPHA       }, // DST_ALPHA\n\t\t{ D3D12_BLEND_INV_DEST_ALPHA,   D3D12_BLEND_INV_DEST_ALPHA   }, // INV_DST_ALPHA\n\t\t{ D3D12_BLEND_DEST_COLOR,       D3D12_BLEND_DEST_ALPHA       }, // DST_COLOR\n\t\t{ D3D12_BLEND_INV_DEST_COLOR,   D3D12_BLEND_INV_DEST_ALPHA   }, // INV_DST_COLOR\n\t\t{ D3D12_BLEND_SRC_ALPHA_SAT,    D3D12_BLEND_ONE              }, // SRC_ALPHA_SAT\n\t\t{ D3D12_BLEND_BLEND_FACTOR,     D3D12_BLEND_BLEND_FACTOR     }, // FACTOR\n\t\t{ D3D12_BLEND_INV_BLEND_FACTOR, D3D12_BLEND_INV_BLEND_FACTOR }, // INV_FACTOR\n\t};\n\n\tstatic const D3D12_BLEND_OP s_blendEquation[] =\n\t{\n\t\tD3D12_BLEND_OP_ADD,\n\t\tD3D12_BLEND_OP_SUBTRACT,\n\t\tD3D12_BLEND_OP_REV_SUBTRACT,\n\t\tD3D12_BLEND_OP_MIN,\n\t\tD3D12_BLEND_OP_MAX,\n\t};\n\n\tstatic const D3D12_COMPARISON_FUNC s_cmpFunc[] =\n\t{\n\t\tD3D12_COMPARISON_FUNC(0), // ignored\n\t\tD3D12_COMPARISON_FUNC_LESS,\n\t\tD3D12_COMPARISON_FUNC_LESS_EQUAL,\n\t\tD3D12_COMPARISON_FUNC_EQUAL,\n\t\tD3D12_COMPARISON_FUNC_GREATER_EQUAL,\n\t\tD3D12_COMPARISON_FUNC_GREATER,\n\t\tD3D12_COMPARISON_FUNC_NOT_EQUAL,\n\t\tD3D12_COMPARISON_FUNC_NEVER,\n\t\tD3D12_COMPARISON_FUNC_ALWAYS,\n\t};\n\n\tstatic const D3D12_STENCIL_OP s_stencilOp[] =\n\t{\n\t\tD3D12_STENCIL_OP_ZERO,\n\t\tD3D12_STENCIL_OP_KEEP,\n\t\tD3D12_STENCIL_OP_REPLACE,\n\t\tD3D12_STENCIL_OP_INCR,\n\t\tD3D12_STENCIL_OP_INCR_SAT,\n\t\tD3D12_STENCIL_OP_DECR,\n\t\tD3D12_STENCIL_OP_DECR_SAT,\n\t\tD3D12_STENCIL_OP_INVERT,\n\t};\n\n\tstatic const D3D12_CULL_MODE s_cullMode[] =\n\t{\n\t\tD3D12_CULL_MODE_NONE,\n\t\tD3D12_CULL_MODE_FRONT,\n\t\tD3D12_CULL_MODE_BACK,\n\t};\n\n\tstatic const D3D12_TEXTURE_ADDRESS_MODE s_textureAddress[] =\n\t{\n\t\tD3D12_TEXTURE_ADDRESS_MODE_WRAP,\n\t\tD3D12_TEXTURE_ADDRESS_MODE_MIRROR,\n\t\tD3D12_TEXTURE_ADDRESS_MODE_CLAMP,\n\t\tD3D12_TEXTURE_ADDRESS_MODE_BORDER,\n\t};\n\n\t/*\n\t * D3D11_FILTER_MIN_MAG_MIP_POINT               = 0x00,\n\t * D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR        = 0x01,\n\t * D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT  = 0x04,\n\t * D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR        = 0x05,\n\t * D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT        = 0x10,\n\t * D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11,\n\t * D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT        = 0x14,\n\t * D3D11_FILTER_MIN_MAG_MIP_LINEAR              = 0x15,\n\t * D3D11_FILTER_ANISOTROPIC                     = 0x55,\n\t *\n\t * D3D11_COMPARISON_FILTERING_BIT               = 0x80,\n\t * D3D11_ANISOTROPIC_FILTERING_BIT              = 0x40,\n\t *\n\t * According to D3D11_FILTER enum bits for mip, mag and mip are:\n\t * 0x10 // MIN_LINEAR\n\t * 0x04 // MAG_LINEAR\n\t * 0x01 // MIP_LINEAR\n\t */\n\n\tstatic const uint8_t s_textureFilter[3][3] =\n\t{\n\t\t{\n\t\t\t0x10, // min linear\n\t\t\t0x00, // min point\n\t\t\t0x55, // anisotropic\n\t\t},\n\t\t{\n\t\t\t0x04, // mag linear\n\t\t\t0x00, // mag point\n\t\t\t0x55, // anisotropic\n\t\t},\n\t\t{\n\t\t\t0x01, // mip linear\n\t\t\t0x00, // mip point\n\t\t\t0x55, // anisotropic\n\t\t},\n\t};\n\n\tstruct TextureFormatInfo\n\t{\n\t\tDXGI_FORMAT m_fmt;\n\t\tDXGI_FORMAT m_fmtSrv;\n\t\tDXGI_FORMAT m_fmtDsv;\n\t\tDXGI_FORMAT m_fmtSrgb;\n\t\tuint32_t    m_mapping;\n\t};\n\n\tstatic const TextureFormatInfo s_textureFormat[] =\n\t{\n#define $0 D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0\n#define $1 D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1\n#define $R D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0\n#define $G D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1\n#define $B D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2\n#define $A D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3\n\t\t{ DXGI_FORMAT_BC1_UNORM,          DXGI_FORMAT_BC1_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_BC1_UNORM_SRGB,       D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC1\n\t\t{ DXGI_FORMAT_BC2_UNORM,          DXGI_FORMAT_BC2_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_BC2_UNORM_SRGB,       D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC2\n\t\t{ DXGI_FORMAT_BC3_UNORM,          DXGI_FORMAT_BC3_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_BC3_UNORM_SRGB,       D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC3\n\t\t{ DXGI_FORMAT_BC4_UNORM,          DXGI_FORMAT_BC4_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC4\n\t\t{ DXGI_FORMAT_BC5_UNORM,          DXGI_FORMAT_BC5_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC5\n\t\t{ DXGI_FORMAT_BC6H_SF16,          DXGI_FORMAT_BC6H_SF16,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC6H\n\t\t{ DXGI_FORMAT_BC7_UNORM,          DXGI_FORMAT_BC7_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_BC7_UNORM_SRGB,       D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BC7\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ETC1\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ETC2\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ETC2A\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ETC2A1\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC12\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC14\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC12A\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC14A\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC22\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // PTC24\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ATC\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ATCE\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ATCI\n\t\t{ DXGI_FORMAT_ASTC_4X4_UNORM,     DXGI_FORMAT_ASTC_4X4_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_4X4_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC4x4\n\t\t{ DXGI_FORMAT_ASTC_5X4_UNORM,     DXGI_FORMAT_ASTC_5X4_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_5X4_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC5x4\n\t\t{ DXGI_FORMAT_ASTC_5X5_UNORM,     DXGI_FORMAT_ASTC_5X5_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_5X5_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC5x5\n\t\t{ DXGI_FORMAT_ASTC_6X5_UNORM,     DXGI_FORMAT_ASTC_6X5_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_6X5_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC6x5\n\t\t{ DXGI_FORMAT_ASTC_6X6_UNORM,     DXGI_FORMAT_ASTC_6X6_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_6X6_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC6x6\n\t\t{ DXGI_FORMAT_ASTC_8X5_UNORM,     DXGI_FORMAT_ASTC_8X5_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_8X5_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC8x5\n\t\t{ DXGI_FORMAT_ASTC_8X6_UNORM,     DXGI_FORMAT_ASTC_8X6_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_8X6_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC8x6\n\t\t{ DXGI_FORMAT_ASTC_8X8_UNORM,     DXGI_FORMAT_ASTC_8X8_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_8X8_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC8x8\n\t\t{ DXGI_FORMAT_ASTC_10X5_UNORM,    DXGI_FORMAT_ASTC_10X5_UNORM,       DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_10X5_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC10x5\n\t\t{ DXGI_FORMAT_ASTC_10X6_UNORM,    DXGI_FORMAT_ASTC_10X6_UNORM,       DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_10X6_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC10x6\n\t\t{ DXGI_FORMAT_ASTC_10X8_UNORM,    DXGI_FORMAT_ASTC_10X8_UNORM,       DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_10X8_UNORM_SRGB, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC10x8\n\t\t{ DXGI_FORMAT_ASTC_10X10_UNORM,   DXGI_FORMAT_ASTC_10X10_UNORM,      DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_10X10_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC10x10\n\t\t{ DXGI_FORMAT_ASTC_12X10_UNORM,   DXGI_FORMAT_ASTC_12X10_UNORM,      DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_12X10_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC12x10\n\t\t{ DXGI_FORMAT_ASTC_12X12_UNORM,   DXGI_FORMAT_ASTC_12X12_UNORM,      DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_ASTC_12X12_UNORM_SRGB,D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // ASTC12x12\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // Unknown\n\t\t{ DXGI_FORMAT_R1_UNORM,           DXGI_FORMAT_R1_UNORM,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R1\n\t\t{ DXGI_FORMAT_A8_UNORM,           DXGI_FORMAT_A8_UNORM,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // A8\n\t\t{ DXGI_FORMAT_R8_UNORM,           DXGI_FORMAT_R8_UNORM,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R8\n\t\t{ DXGI_FORMAT_R8_SINT,            DXGI_FORMAT_R8_SINT,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R8I\n\t\t{ DXGI_FORMAT_R8_UINT,            DXGI_FORMAT_R8_UINT,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R8U\n\t\t{ DXGI_FORMAT_R8_SNORM,           DXGI_FORMAT_R8_SNORM,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R8S\n\t\t{ DXGI_FORMAT_R16_UNORM,          DXGI_FORMAT_R16_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R16\n\t\t{ DXGI_FORMAT_R16_SINT,           DXGI_FORMAT_R16_SINT,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R16I\n\t\t{ DXGI_FORMAT_R16_UNORM,          DXGI_FORMAT_R16_UNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R16U\n\t\t{ DXGI_FORMAT_R16_FLOAT,          DXGI_FORMAT_R16_FLOAT,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R16F\n\t\t{ DXGI_FORMAT_R16_SNORM,          DXGI_FORMAT_R16_SNORM,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R16S\n\t\t{ DXGI_FORMAT_R32_SINT,           DXGI_FORMAT_R32_SINT,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R32I\n\t\t{ DXGI_FORMAT_R32_UINT,           DXGI_FORMAT_R32_UINT,              DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R32U\n\t\t{ DXGI_FORMAT_R32_FLOAT,          DXGI_FORMAT_R32_FLOAT,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // R32F\n\t\t{ DXGI_FORMAT_R8G8_UNORM,         DXGI_FORMAT_R8G8_UNORM,            DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG8\n\t\t{ DXGI_FORMAT_R8G8_SINT,          DXGI_FORMAT_R8G8_SINT,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG8I\n\t\t{ DXGI_FORMAT_R8G8_UINT,          DXGI_FORMAT_R8G8_UINT,             DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG8U\n\t\t{ DXGI_FORMAT_R8G8_SNORM,         DXGI_FORMAT_R8G8_SNORM,            DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG8S\n\t\t{ DXGI_FORMAT_R16G16_UNORM,       DXGI_FORMAT_R16G16_UNORM,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG16\n\t\t{ DXGI_FORMAT_R16G16_SINT,        DXGI_FORMAT_R16G16_SINT,           DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG16I\n\t\t{ DXGI_FORMAT_R16G16_UINT,        DXGI_FORMAT_R16G16_UINT,           DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG16U\n\t\t{ DXGI_FORMAT_R16G16_FLOAT,       DXGI_FORMAT_R16G16_FLOAT,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG16F\n\t\t{ DXGI_FORMAT_R16G16_SNORM,       DXGI_FORMAT_R16G16_SNORM,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG16S\n\t\t{ DXGI_FORMAT_R32G32_SINT,        DXGI_FORMAT_R32G32_SINT,           DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG32I\n\t\t{ DXGI_FORMAT_R32G32_UINT,        DXGI_FORMAT_R32G32_UINT,           DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG32U\n\t\t{ DXGI_FORMAT_R32G32_FLOAT,       DXGI_FORMAT_R32G32_FLOAT,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG32F\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB8\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB8I\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB8U\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB8S\n\t\t{ DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP,    DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB9E5F\n\t\t{ DXGI_FORMAT_B8G8R8A8_UNORM,     DXGI_FORMAT_B8G8R8A8_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BGRA8\n\t\t{ DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA8\n\t\t{ DXGI_FORMAT_R8G8B8A8_SINT,      DXGI_FORMAT_R8G8B8A8_SINT,         DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA8I\n\t\t{ DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_R8G8B8A8_UINT,         DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA8U\n\t\t{ DXGI_FORMAT_R8G8B8A8_SNORM,     DXGI_FORMAT_R8G8B8A8_SNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA8S\n\t\t{ DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM,    DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA16\n\t\t{ DXGI_FORMAT_R16G16B16A16_SINT,  DXGI_FORMAT_R16G16B16A16_SINT,     DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA16I\n\t\t{ DXGI_FORMAT_R16G16B16A16_UINT,  DXGI_FORMAT_R16G16B16A16_UINT,     DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA16U\n\t\t{ DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,    DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA16F\n\t\t{ DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_SNORM,    DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA16S\n\t\t{ DXGI_FORMAT_R32G32B32A32_SINT,  DXGI_FORMAT_R32G32B32A32_SINT,     DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA32I\n\t\t{ DXGI_FORMAT_R32G32B32A32_UINT,  DXGI_FORMAT_R32G32B32A32_UINT,     DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA32U\n\t\t{ DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,    DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGBA32F\n\t\t{ DXGI_FORMAT_B5G6R5_UNORM,       DXGI_FORMAT_B5G6R5_UNORM,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // B5G6R5\n\t\t{ DXGI_FORMAT_B5G6R5_UNORM,       DXGI_FORMAT_B5G6R5_UNORM,          DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $1) }, // R5G6B5\n\t\t{ DXGI_FORMAT_B4G4R4A4_UNORM,     DXGI_FORMAT_B4G4R4A4_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BGRA4\n\t\t{ DXGI_FORMAT_B4G4R4A4_UNORM,     DXGI_FORMAT_B4G4R4A4_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $A) }, // RGBA4\n\t\t{ DXGI_FORMAT_B5G5R5A1_UNORM,     DXGI_FORMAT_B5G5R5A1_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // BGR5A1\n\t\t{ DXGI_FORMAT_B5G5R5A1_UNORM,     DXGI_FORMAT_B5G5R5A1_UNORM,        DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING($B, $G, $R, $A) }, // RGB5A1\n\t\t{ DXGI_FORMAT_R10G10B10A2_UNORM,  DXGI_FORMAT_R10G10B10A2_UNORM,     DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RGB10A2\n\t\t{ DXGI_FORMAT_R11G11B10_FLOAT,    DXGI_FORMAT_R11G11B10_FLOAT,       DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // RG11B10F\n\t\t{ DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN,               DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // UnknownDepth\n\t\t{ DXGI_FORMAT_R16_TYPELESS,       DXGI_FORMAT_R16_UNORM,             DXGI_FORMAT_D16_UNORM,         DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D16\n\t\t{ DXGI_FORMAT_R24G8_TYPELESS,     DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D24\n\t\t{ DXGI_FORMAT_R24G8_TYPELESS,     DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D24S8\n\t\t{ DXGI_FORMAT_R24G8_TYPELESS,     DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D32\n\t\t{ DXGI_FORMAT_R32_TYPELESS,       DXGI_FORMAT_R32_FLOAT,             DXGI_FORMAT_D32_FLOAT,         DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D16F\n\t\t{ DXGI_FORMAT_R32_TYPELESS,       DXGI_FORMAT_R32_FLOAT,             DXGI_FORMAT_D32_FLOAT,         DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D24F\n\t\t{ DXGI_FORMAT_R32_TYPELESS,       DXGI_FORMAT_R32_FLOAT,             DXGI_FORMAT_D32_FLOAT,         DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D32F\n\t\t{ DXGI_FORMAT_R24G8_TYPELESS,     DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN,              D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING                }, // D0S8\n#undef $0\n#undef $1\n#undef $R\n#undef $G\n#undef $B\n#undef $A\n\t};\n\tBX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) );\n\n\tstatic const D3D12_INPUT_ELEMENT_DESC s_attrib[] =\n\t{\n\t\t{ "POSITION",     0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "NORMAL",       0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TANGENT",      0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "BITANGENT",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "COLOR",        0, DXGI_FORMAT_R8G8B8A8_UINT,   0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "COLOR",        1, DXGI_FORMAT_R8G8B8A8_UINT,   0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "COLOR",        2, DXGI_FORMAT_R8G8B8A8_UINT,   0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "COLOR",        3, DXGI_FORMAT_R8G8B8A8_UINT,   0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "BLENDINDICES", 0, DXGI_FORMAT_R8G8B8A8_UINT,   0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "BLENDWEIGHT",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     0, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     1, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     2, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     3, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     4, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     5, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     6, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t\t{ "TEXCOORD",     7, DXGI_FORMAT_R32G32_FLOAT,    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },\n\t};\n\tBX_STATIC_ASSERT(Attrib::Count == BX_COUNTOF(s_attrib) );\n\n\tstatic const DXGI_FORMAT s_attribType[][4][2] =\n\t{\n\t\t{ // Uint8\n\t\t\t{ DXGI_FORMAT_R8_UINT,            DXGI_FORMAT_R8_UNORM           },\n\t\t\t{ DXGI_FORMAT_R8G8_UINT,          DXGI_FORMAT_R8G8_UNORM         },\n\t\t\t{ DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_R8G8B8A8_UNORM     },\n\t\t\t{ DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_R8G8B8A8_UNORM     },\n\t\t},\n\t\t{ // Uint10\n\t\t\t{ DXGI_FORMAT_R10G10B10A2_UINT,   DXGI_FORMAT_R10G10B10A2_UNORM  },\n\t\t\t{ DXGI_FORMAT_R10G10B10A2_UINT,   DXGI_FORMAT_R10G10B10A2_UNORM  },\n\t\t\t{ DXGI_FORMAT_R10G10B10A2_UINT,   DXGI_FORMAT_R10G10B10A2_UNORM  },\n\t\t\t{ DXGI_FORMAT_R10G10B10A2_UINT,   DXGI_FORMAT_R10G10B10A2_UNORM  },\n\t\t},\n\t\t{ // Int16\n\t\t\t{ DXGI_FORMAT_R16_SINT,           DXGI_FORMAT_R16_SNORM          },\n\t\t\t{ DXGI_FORMAT_R16G16_SINT,        DXGI_FORMAT_R16G16_SNORM       },\n\t\t\t{ DXGI_FORMAT_R16G16B16A16_SINT,  DXGI_FORMAT_R16G16B16A16_SNORM },\n\t\t\t{ DXGI_FORMAT_R16G16B16A16_SINT,  DXGI_FORMAT_R16G16B16A16_SNORM },\n\t\t},\n\t\t{ // Half\n\t\t\t{ DXGI_FORMAT_R16_FLOAT,          DXGI_FORMAT_R16_FLOAT          },\n\t\t\t{ DXGI_FORMAT_R16G16_FLOAT,       DXGI_FORMAT_R16G16_FLOAT       },\n\t\t\t{ DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT },\n\t\t\t{ DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT },\n\t\t},\n\t\t{ // Float\n\t\t\t{ DXGI_FORMAT_R32_FLOAT,          DXGI_FORMAT_R32_FLOAT          },\n\t\t\t{ DXGI_FORMAT_R32G32_FLOAT,       DXGI_FORMAT_R32G32_FLOAT       },\n\t\t\t{ DXGI_FORMAT_R32G32B32_FLOAT,    DXGI_FORMAT_R32G32B32_FLOAT    },\n\t\t\t{ DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT },\n\t\t},\n\t};\n\tBX_STATIC_ASSERT(AttribType::Count == BX_COUNTOF(s_attribType) );\n\n\tstatic D3D12_INPUT_ELEMENT_DESC* fillVertexLayout(uint8_t _stream, D3D12_INPUT_ELEMENT_DESC* _out, const VertexLayout& _layout)\n\t{\n\t\tD3D12_INPUT_ELEMENT_DESC* elem = _out;\n\n\t\tfor (uint32_t attr = 0; attr < Attrib::Count; ++attr)\n\t\t{\n\t\t\tif (UINT16_MAX != _layout.m_attributes[attr])\n\t\t\t{\n\t\t\t\tbx::memCopy(elem, &s_attrib[attr], sizeof(D3D12_INPUT_ELEMENT_DESC) );\n\n\t\t\t\telem->InputSlot = _stream;\n\n\t\t\t\tif (0 == _layout.m_attributes[attr])\n\t\t\t\t{\n\t\t\t\t\telem->AlignedByteOffset = 0;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tuint8_t num;\n\t\t\t\t\tAttribType::Enum type;\n\t\t\t\t\tbool normalized;\n\t\t\t\t\tbool asInt;\n\t\t\t\t\t_layout.decode(Attrib::Enum(attr), num, type, normalized, asInt);\n\t\t\t\t\telem->Format = s_attribType[type][num-1][normalized];\n\t\t\t\t\telem->AlignedByteOffset = _layout.m_offset[attr];\n\t\t\t\t}\n\n\t\t\t\t++elem;\n\t\t\t}\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tvoid setResourceBarrier(ID3D12GraphicsCommandList* _commandList, const ID3D12Resource* _resource, D3D12_RESOURCE_STATES _stateBefore, D3D12_RESOURCE_STATES _stateAfter)\n\t{\n\t\tD3D12_RESOURCE_BARRIER barrier;\n\t\tbarrier.Type  = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;\n\t\tbarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;\n\t\tbarrier.Transition.pResource   = const_cast<ID3D12Resource*>(_resource);\n\t\tbarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;\n\t\tbarrier.Transition.StateBefore = _stateBefore;\n\t\tbarrier.Transition.StateAfter  = _stateAfter;\n\t\t_commandList->ResourceBarrier(1, &barrier);\n\t}\n\n\tBX_PRAGMA_DIAGNOSTIC_PUSH();\n\tBX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunused-const-variable");\n\tBX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration");\n\n\tstatic const GUID IID_ID3D12CommandAllocator     = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } };\n\tstatic const GUID IID_ID3D12CommandQueue         = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } };\n\tstatic const GUID IID_ID3D12CommandSignature     = { 0xc36a797c, 0xec80, 0x4f0a, { 0x89, 0x85, 0xa7, 0xb2, 0x47, 0x50, 0x82, 0xd1 } };\n\tstatic const GUID IID_ID3D12Debug                = { 0x344488b7, 0x6846, 0x474b, { 0xb9, 0x89, 0xf0, 0x27, 0x44, 0x82, 0x45, 0xe0 } };\n\tstatic const GUID IID_ID3D12Debug1               = { 0xaffaa4ca, 0x63fe, 0x4d8e, { 0xb8, 0xad, 0x15, 0x90, 0x00, 0xaf, 0x43, 0x04 } };\n\tstatic const GUID IID_ID3D12DescriptorHeap       = { 0x8efb471d, 0x616c, 0x4f49, { 0x90, 0xf7, 0x12, 0x7b, 0xb7, 0x63, 0xfa, 0x51 } };\n\tstatic const GUID IID_ID3D12Device               = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } };\n\tstatic const GUID IID_ID3D12Device1              = { 0x77acce80, 0x638e, 0x4e65, { 0x88, 0x95, 0xc1, 0xf2, 0x33, 0x86, 0x86, 0x3e } };\n\tstatic const GUID IID_ID3D12Device2              = { 0x30baa41e, 0xb15b, 0x475c, { 0xa0, 0xbb, 0x1a, 0xf5, 0xc5, 0xb6, 0x43, 0x28 } };\n\tstatic const GUID IID_ID3D12Device3              = { 0x81dadc15, 0x2bad, 0x4392, { 0x93, 0xc5, 0x10, 0x13, 0x45, 0xc4, 0xaa, 0x98 } };\n\tstatic const GUID IID_ID3D12Device4              = { 0xe865df17, 0xa9ee, 0x46f9, { 0xa4, 0x63, 0x30, 0x98, 0x31, 0x5a, 0xa2, 0xe5 } };\n\tstatic const GUID IID_ID3D12Device5              = { 0x8b4f173b, 0x2fea, 0x4b80, { 0x8f, 0x58, 0x43, 0x07, 0x19, 0x1a, 0xb9, 0x5d } };\n\tstatic const GUID IID_ID3D12Fence                = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } };\n\tstatic const GUID IID_ID3D12GraphicsCommandList  = { 0x5b160d0f, 0xac1b, 0x4185, { 0x8b, 0xa8, 0xb3, 0xae, 0x42, 0xa5, 0xa4, 0x55 } };\n\tstatic const GUID IID_ID3D12GraphicsCommandList1 = { 0x553103fb, 0x1fe7, 0x4557, { 0xbb, 0x38, 0x94, 0x6d, 0x7d, 0x0e, 0x7c, 0xa7 } };\n\tstatic const GUID IID_ID3D12GraphicsCommandList2 = { 0x38C3E585, 0xFF17, 0x412C, { 0x91, 0x50, 0x4F, 0xC6, 0xF9, 0xD7, 0x2A, 0x28 } };\n\tstatic const GUID IID_ID3D12GraphicsCommandList3 = { 0x6FDA83A7, 0xB84C, 0x4E38, { 0x9A, 0xC8, 0xC7, 0xBD, 0x22, 0x01, 0x6B, 0x3D } };\n\tstatic const GUID IID_ID3D12GraphicsCommandList4 = { 0x8754318e, 0xd3a9, 0x4541, { 0x98, 0xcf, 0x64, 0x5b, 0x50, 0xdc, 0x48, 0x74 } };\n\tstatic const GUID IID_ID3D12InfoQueue            = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } };\n\tstatic const GUID IID_ID3D12PipelineState        = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } };\n\tstatic const GUID IID_ID3D12Resource             = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } };\n\tstatic const GUID IID_ID3D12RootSignature        = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } };\n\tstatic const GUID IID_ID3D12QueryHeap            = { 0x0d9658ae, 0xed45, 0x469e, { 0xa6, 0x1d, 0x97, 0x0e, 0xc5, 0x83, 0xca, 0xb4 } };\n\n\tBX_PRAGMA_DIAGNOSTIC_POP();\n\n\tstatic const GUID s_d3dDeviceIIDs[] =\n\t{\n\t\tIID_ID3D12Device5,\n\t\tIID_ID3D12Device4,\n\t\tIID_ID3D12Device3,\n\t\tIID_ID3D12Device2,\n\t\tIID_ID3D12Device1,\n\t};\n\n\tstruct HeapProperty\n\t{\n\t\tenum Enum\n\t\t{\n\t\t\tDefault,\n\t\t\tTexture,\n\t\t\tUpload,\n\t\t\tReadBack,\n\n\t\t\tCount\n\t\t};\n\n\t\tD3D12_HEAP_PROPERTIES m_properties;\n\t\tD3D12_RESOURCE_STATES m_state;\n\t};\n\n\tstatic HeapProperty s_heapProperties[] =\n\t{\n\t\t{ { D3D12_HEAP_TYPE_DEFAULT,  D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COMMON       },\n\t\t{ { D3D12_HEAP_TYPE_DEFAULT,  D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COMMON       },\n\t\t{ { D3D12_HEAP_TYPE_UPLOAD,   D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_GENERIC_READ },\n\t\t{ { D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0, 0 }, D3D12_RESOURCE_STATE_COPY_DEST    },\n\t};\n\tBX_STATIC_ASSERT(BX_COUNTOF(s_heapProperties) == HeapProperty::Count);\n\n\tstatic inline D3D12_HEAP_PROPERTIES ID3D12DeviceGetCustomHeapProperties(ID3D12Device *device, uint32_t nodeMask, D3D12_HEAP_TYPE heapType)\n\t{\n#if BX_COMPILER_MSVC\n\t\treturn device->GetCustomHeapProperties(nodeMask, heapType);\n#else\n\t\tD3D12_HEAP_PROPERTIES ret;\n\t\tdevice->GetCustomHeapProperties(&ret, nodeMask, heapType);\n\t\treturn ret;\n#endif // BX_COMPILER_MSVC\n\t}\n\n\tstatic void initHeapProperties(ID3D12Device* _device, D3D12_HEAP_PROPERTIES& _properties)\n\t{\n\t\tif (D3D12_HEAP_TYPE_CUSTOM != _properties.Type)\n\t\t{\n\t\t\t_properties = ID3D12DeviceGetCustomHeapProperties(_device, 1, _properties.Type);\n\t\t}\n\t}\n\n\tstatic void initHeapProperties(ID3D12Device* _device)\n\t{\n#if BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS\n\t\tinitHeapProperties(_device, s_heapProperties[HeapProperty::Default ].m_properties);\n\t\tinitHeapProperties(_device, s_heapProperties[HeapProperty::Texture ].m_properties);\n\t\tinitHeapProperties(_device, s_heapProperties[HeapProperty::Upload  ].m_properties);\n\t\tinitHeapProperties(_device, s_heapProperties[HeapProperty::ReadBack].m_properties);\n#else\n\t\tBX_UNUSED(_device);\n#endif // BX_PLATFORM_WINDOWS\n\t}\n\n\tID3D12Resource* createCommittedResource(ID3D12Device* _device, HeapProperty::Enum _heapProperty, const D3D12_RESOURCE_DESC* _resourceDesc, const D3D12_CLEAR_VALUE* _clearValue, bool _memSet = false)\n\t{\n\t\tconst HeapProperty& heapProperty = s_heapProperties[_heapProperty];\n\t\tID3D12Resource* resource;\n\t\tDX_CHECK(_device->CreateCommittedResource(&heapProperty.m_properties\n\t\t\t, D3D12_HEAP_FLAG_NONE\n\t\t\t, _resourceDesc\n\t\t\t, heapProperty.m_state\n\t\t\t, _clearValue\n\t\t\t, IID_ID3D12Resource\n\t\t\t, (void**)&resource\n\t\t\t) );\n\t\tBX_WARN(NULL != resource, "CreateCommittedResource failed (size: %d). Out of memory?"\n\t\t\t, _resourceDesc->Width\n\t\t\t);\n\n\t\tif (BX_ENABLED(BX_PLATFORM_XBOXONE)\n\t\t&&  _memSet)\n\t\t{\n\t\t\tvoid* ptr;\n\t\t\tDX_CHECK(resource->Map(0, NULL, &ptr) );\n\t\t\tD3D12_RESOURCE_ALLOCATION_INFO rai;\n#if BX_COMPILER_MSVC\n\t\t\trai = _device->GetResourceAllocationInfo(1, 1, _resourceDesc);\n#else\n\t\t\t_device->GetResourceAllocationInfo(&rai, 1, 1, _resourceDesc);\n#endif // BX_COMPILER_MSVC\n\t\t\tbx::memSet(ptr, 0, size_t(rai.SizeInBytes) );\n\t\t\tresource->Unmap(0, NULL);\n\t\t}\n\n\t\treturn resource;\n\t}\n\n\tID3D12Resource* createCommittedResource(ID3D12Device* _device, HeapProperty::Enum _heapProperty, uint64_t _size, D3D12_RESOURCE_FLAGS _flags = D3D12_RESOURCE_FLAG_NONE)\n\t{\n\t\tD3D12_RESOURCE_DESC resourceDesc = {};\n\t\tresourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;\n\t\tresourceDesc.Alignment = 0;\n\t\tresourceDesc.Width     = _size;\n\t\tresourceDesc.Height    = 1;\n\t\tresourceDesc.DepthOrArraySize = 1;\n\t\tresourceDesc.MipLevels = 1;\n\t\tresourceDesc.Format             = DXGI_FORMAT_UNKNOWN;\n\t\tresourceDesc.SampleDesc.Count   = 1;\n\t\tresourceDesc.SampleDesc.Quality = 0;\n\t\tresourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;\n\t\tresourceDesc.Flags  = _flags;\n\n\t\treturn createCommittedResource(_device, _heapProperty, &resourceDesc, NULL);\n\t}\n\n\tinline bool isLost(HRESULT _hr)\n\t{\n\t\treturn false\n\t\t\t|| _hr == DXGI_ERROR_DEVICE_REMOVED\n\t\t\t|| _hr == DXGI_ERROR_DEVICE_HUNG\n\t\t\t|| _hr == DXGI_ERROR_DEVICE_RESET\n\t\t\t|| _hr == DXGI_ERROR_DRIVER_INTERNAL_ERROR\n\t\t\t|| _hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE\n\t\t\t;\n\t}\n\n\tstatic const char* getLostReason(HRESULT _hr)\n\t{\n\t\tswitch (_hr)\n\t\t{\n\t\t// The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.\n\t\tcase DXGI_ERROR_DEVICE_REMOVED: return "DXGI_ERROR_DEVICE_REMOVED";\n\n\t\t// The GPU will not respond to more commands, most likely because of an invalid command passed by the calling application.\n\t\tcase DXGI_ERROR_DEVICE_HUNG: return "DXGI_ERROR_DEVICE_HUNG";\n\n\t\t// The GPU will not respond to more commands, most likely because some other application submitted invalid commands.\n\t\t// The calling application should re-create the device and continue.\n\t\tcase DXGI_ERROR_DEVICE_RESET: return "DXGI_ERROR_DEVICE_RESET";\n\n\t\t// An internal issue prevented the driver from carrying out the specified operation. The driver\'s state is probably\n\t\t// suspect, and the application should not continue.\n\t\tcase DXGI_ERROR_DRIVER_INTERNAL_ERROR: return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";\n\n\t\t// A resource is not available at the time of the call, but may become available later.\n\t\tcase DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE";\n\n\t\tcase S_OK: return "S_OK";\n\n\t\tdefault: break;\n\t\t}\n\n\t\treturn "Unknown HRESULT?";\n\t}\n\n\tBX_NO_INLINE void setDebugObjectName(ID3D12Object* _object, const char* _format, ...)\n\t{\n\t\tif (BX_ENABLED(BGFX_CONFIG_DEBUG_OBJECT_NAME) )\n\t\t{\n\t\t\tchar temp[2048];\n\t\t\tva_list argList;\n\t\t\tva_start(argList, _format);\n\t\t\tint size = bx::uint32_min(sizeof(temp)-1, bx::vsnprintf(temp, sizeof(temp), _format, argList) );\n\t\t\tva_end(argList);\n\t\t\ttemp[size] = \'\\0\';\n\n\t\t\twchar_t* wtemp = (wchar_t*)alloca( (size+1)*2);\n\t\t\tmbstowcs(wtemp, temp, size+1);\n\t\t\t_object->SetName(wtemp);\n\t\t}\n\t}\n\n#if USE_D3D12_DYNAMIC_LIB\n\tstatic PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES D3D12EnableExperimentalFeatures;\n\tstatic PFN_D3D12_CREATE_DEVICE                D3D12CreateDevice;\n\tstatic PFN_D3D12_GET_DEBUG_INTERFACE          D3D12GetDebugInterface;\n\tstatic PFN_D3D12_SERIALIZE_ROOT_SIGNATURE     D3D12SerializeRootSignature;\n\n#\tif !BX_PLATFORM_LINUX\n\ttypedef HANDLE  (WINAPI* PFN_CREATE_EVENT_EX_A)(LPSECURITY_ATTRIBUTES _attrs, LPCSTR _name, DWORD _flags, DWORD _access);\n\tstatic PFN_CREATE_EVENT_EX_A CreateEventExA;\n#\tendif // !BX_PLATFORM_LINUX\n#endif // USE_D3D12_DYNAMIC_LIB\n\n\tinline D3D12_CPU_DESCRIPTOR_HANDLE getCPUHandleHeapStart(ID3D12DescriptorHeap* _heap)\n\t{\n#if BX_COMPILER_MSVC\n\t\treturn _heap->GetCPUDescriptorHandleForHeapStart();\n#else\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE handle;\n\t\t_heap->GetCPUDescriptorHandleForHeapStart(&handle);\n\t\treturn handle;\n#endif // BX_COMPILER_MSVC\n\t}\n\n\tinline D3D12_GPU_DESCRIPTOR_HANDLE getGPUHandleHeapStart(ID3D12DescriptorHeap* _heap)\n\t{\n#if BX_COMPILER_MSVC\n\t\treturn _heap->GetGPUDescriptorHandleForHeapStart();\n#else\n\t\tD3D12_GPU_DESCRIPTOR_HANDLE handle;\n\t\t_heap->GetGPUDescriptorHandleForHeapStart(&handle);\n\t\treturn handle;\n#endif // BX_COMPILER_MSVC\n\t}\n\n\tinline D3D12_RESOURCE_DESC getResourceDesc(ID3D12Resource* _resource)\n\t{\n#if BX_COMPILER_MSVC\n\t\treturn _resource->GetDesc();\n#else\n\t\tD3D12_RESOURCE_DESC desc;\n\t\t_resource->GetDesc(&desc);\n\t\treturn desc;\n#endif // BX_COMPILER_MSVC\n\t}\n\n#if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\tstatic PIXEventsThreadInfo s_pixEventsThreadInfo;\n\n\tPIXEventsThreadInfo* WINAPI stubPIXGetThreadInfo()\n\t{\n\t\treturn &s_pixEventsThreadInfo;\n\t}\n\n\tuint64_t WINAPI stubPIXEventsReplaceBlock(bool _getEarliestTime)\n\t{\n\t\tBX_UNUSED(_getEarliestTime);\n\t\treturn 0;\n\t}\n#endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\n\tstruct RendererContextD3D12 : public RendererContextI\n\t{\n\t\tRendererContextD3D12()\n\t\t\t: m_d3d12Dll(NULL)\n\t\t\t, m_renderDocDll(NULL)\n\t\t\t, m_winPixEvent(NULL)\n\t\t\t, m_featureLevel(D3D_FEATURE_LEVEL(0) )\n\t\t\t, m_swapChain(NULL)\n\t\t\t, m_wireframe(false)\n\t\t\t, m_lost(false)\n\t\t\t, m_maxAnisotropy(1)\n\t\t\t, m_depthClamp(false)\n\t\t\t, m_backBufferColorIdx(0)\n\t\t\t, m_rtMsaa(false)\n\t\t\t, m_directAccessSupport(false)\n\t\t{\n\t\t}\n\n\t\t~RendererContextD3D12()\n\t\t{\n\t\t}\n\n\t\tbool init(const Init& _init)\n\t\t{\n\t\t\tstruct ErrorState\n\t\t\t{\n\t\t\t\tenum Enum\n\t\t\t\t{\n\t\t\t\t\tDefault,\n\t\t\t\t\tLoadedKernel32,\n\t\t\t\t\tLoadedD3D12,\n\t\t\t\t\tLoadedDXGI,\n\t\t\t\t\tCreatedDXGIFactory,\n\t\t\t\t\tCreatedCommandQueue,\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tErrorState::Enum errorState = ErrorState::Default;\n//\t\t\tLUID luid;\n\n#if BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\t\t\tm_winPixEvent = bx::dlopen("WinPixEventRuntime.dll");\n\n\t\t\tif (NULL != m_winPixEvent)\n\t\t\t{\n\t\t\t\tbgfx_PIXGetThreadInfo      = (PFN_PIX_GET_THREAD_INFO     )bx::dlsym(m_winPixEvent, "PIXGetThreadInfo");\n\t\t\t\tbgfx_PIXEventsReplaceBlock = (PFN_PIX_EVENTS_REPLACE_BLOCK)bx::dlsym(m_winPixEvent, "PIXEventsReplaceBlock");\n\t\t\t}\n\n\t\t\tif (NULL == bgfx_PIXGetThreadInfo\n\t\t\t||  NULL == bgfx_PIXEventsReplaceBlock)\n\t\t\t{\n\t\t\t\tbgfx_PIXGetThreadInfo      = stubPIXGetThreadInfo;\n\t\t\t\tbgfx_PIXEventsReplaceBlock = stubPIXEventsReplaceBlock;\n\t\t\t}\n#endif // BGFX_CONFIG_DEBUG_ANNOTATION && (BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\n\t\t\tif (_init.debug\n\t\t\t||  _init.profile)\n\t\t\t{\n\t\t\t\tm_renderDocDll = loadRenderDoc();\n\t\t\t}\n\n\t\t\tsetGraphicsDebuggerPresent(NULL != m_renderDocDll || NULL != m_winPixEvent);\n\n\t\t\tm_fbh.idx = kInvalidHandle;\n\t\t\tbx::memSet(m_uniforms, 0, sizeof(m_uniforms) );\n\t\t\tbx::memSet(&m_resolution, 0, sizeof(m_resolution) );\n\n#if USE_D3D12_DYNAMIC_LIB\n\n#\tif !BX_PLATFORM_LINUX\n\t\t\tm_kernel32Dll = bx::dlopen("kernel32.dll");\n\t\t\tif (NULL == m_kernel32Dll)\n\t\t\t{\n\t\t\t\tBX_TRACE("Init error: Failed to load kernel32.dll.");\n\t\t\t\tgoto error;\n\t\t\t}\n\n\t\t\tCreateEventExA = (PFN_CREATE_EVENT_EX_A)bx::dlsym(m_kernel32Dll, "CreateEventExA");\n\t\t\tif (NULL == CreateEventExA)\n\t\t\t{\n\t\t\t\tBX_TRACE("Init error: Function CreateEventExA not found.");\n\t\t\t\tgoto error;\n\t\t\t}\n\n\t\t\terrorState = ErrorState::LoadedKernel32;\n#\tendif // !BX_PLATFORM_LINUX\n\n\t\t\tm_nvapi.init();\n\n\t\t\t{\n\t\t\t\tconst char* d3d12DllName =\n#if BX_PLATFORM_LINUX\n\t\t\t\t\t"libd3d12.so"\n#else\n\t\t\t\t\t"d3d12.dll"\n#endif // BX_PLATFORM_LINUX\n\t\t\t\t\t;\n\n\t\t\t\tm_d3d12Dll = bx::dlopen(d3d12DllName);\n\n\t\t\t\tif (NULL == m_d3d12Dll)\n\t\t\t\t{\n\t\t\t\t\tBX_TRACE("Init error: Failed to load %s.", d3d12DllName);\n\t\t\t\t\tgoto error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\terrorState = ErrorState::LoadedD3D12;\n\n\t\t\tD3D12EnableExperimentalFeatures = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)bx::dlsym(m_d3d12Dll, "D3D12EnableExperimentalFeatures");\n\t\t\tBX_WARN(NULL != D3D12EnableExperimentalFeatures, "Function D3D12EnableExperimentalFeatures not found.");\n\n\t\t\tD3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)bx::dlsym(m_d3d12Dll, "D3D12CreateDevice");\n\t\t\tBX_WARN(NULL != D3D12CreateDevice, "Function D3D12CreateDevice not found.");\n\n\t\t\tD3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)bx::dlsym(m_d3d12Dll, "D3D12GetDebugInterface");\n\t\t\tBX_WARN(NULL != D3D12GetDebugInterface, "Function D3D12GetDebugInterface not found.");\n\n\t\t\tD3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)bx::dlsym(m_d3d12Dll, "D3D12SerializeRootSignature");\n\t\t\tBX_WARN(NULL != D3D12SerializeRootSignature, "Function D3D12SerializeRootSignature not found.");\n\n\t\t\tif (NULL == D3D12CreateDevice\n\t\t\t||  NULL == D3D12GetDebugInterface\n\t\t\t||  NULL == D3D12SerializeRootSignature)\n\t\t\t{\n\t\t\t\tBX_TRACE("Init error: Function not found.");\n\t\t\t\tgoto error;\n\t\t\t}\n#endif // USE_D3D12_DYNAMIC_LIB\n\n#if !BX_PLATFORM_LINUX\n\t\t\tif (!m_dxgi.init(g_caps) )\n\t\t\t{\n\t\t\t\tgoto error;\n\t\t\t}\n\n\t\t\terrorState = ErrorState::LoadedDXGI;\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\tHRESULT hr;\n\n\t\t\t{\n#if BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\t\tif (_init.debug\n\t\t\t\t||  _init.profile)\n\t\t\t\t{\n\t\t\t\t\tID3D12Debug* debug0;\n\t\t\t\t\thr = D3D12GetDebugInterface(IID_ID3D12Debug, (void**)&debug0);\n\n\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif (_init.debug)\n\t\t\t\t\t\t{\n#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\t\t\t\t\tdebug0->EnableDebugLayer();\n\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tID3D12Debug1* debug1;\n\t\t\t\t\t\t\t\thr = debug0->QueryInterface(IID_ID3D12Debug1, (void**)&debug1);\n\n\t\t\t\t\t\t\t\tif (SUCCEEDED(hr))\n\t\t\t\t\t\t\t\t{\n//\t\t\t\t\t\t\t\t\tdebug1->SetEnableGPUBasedValidation(true);\n\n\t\t\t\t\t\t\t\t\t// https://discordapp.com/channels/590611987420020747/593519198995742733/703642988345032804\n\t\t\t\t\t\t\t\t\t// D3D12 Bug Number: 26131261\n\t\t\t\t\t\t\t\t\t// There is a bug in the D3D12 validation that causes example-21 to fail when using UAV\n\t\t\t\t\t\t\t\t\t// Setting this function below to false avoids the bug\n\t\t\t\t\t\t\t\t\tdebug1->SetEnableSynchronizedCommandQueueValidation(false);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tDX_RELEASE(debug1, 1);\n\t\t\t\t\t\t\t}\n#endif // BX_PLATFORM_WINDOWS\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tDX_RELEASE(debug0, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tD3D_FEATURE_LEVEL featureLevel[] =\n\t\t\t\t{\n\t\t\t\t\tD3D_FEATURE_LEVEL_12_1,\n\t\t\t\t\tD3D_FEATURE_LEVEL_12_0,\n\t\t\t\t\tD3D_FEATURE_LEVEL_11_1,\n\t\t\t\t\tD3D_FEATURE_LEVEL_11_0,\n\t\t\t\t};\n\n\t\t\t\thr = E_FAIL;\n\t\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(featureLevel) && FAILED(hr); ++ii)\n\t\t\t\t{\n\t\t\t\t\thr = D3D12CreateDevice(\n#if BX_PLATFORM_LINUX\n\t\t\t\t\t\t\tNULL\n#else\n\t\t\t\t\t\t\tm_dxgi.m_adapter\n#endif // BX_PLATFORM_LINUX\n\t\t\t\t\t\t\t, featureLevel[ii]\n\t\t\t\t\t\t\t, IID_ID3D12Device\n\t\t\t\t\t\t\t, (void**)&m_device\n\t\t\t\t\t\t\t);\n\t\t\t\t\tBX_WARN(FAILED(hr), "Direct3D12 device feature level %d.%d."\n\t\t\t\t\t\t, (featureLevel[ii] >> 12) & 0xf\n\t\t\t\t\t\t, (featureLevel[ii] >>  8) & 0xf\n\t\t\t\t\t\t);\n\t\t\t\t\tm_featureLevel = featureLevel[ii];\n\t\t\t\t}\n#else\n\t\t\t\t// Reference(s):\n\t\t\t\t//  - https://github.com/Microsoft/Xbox-ATG-Samples/blob/1271bfd61b4883c775f395b6f13aeabea70290ca/XDKSamples/Graphics/AdvancedESRAM12/DeviceResources.cpp#L64\n\t\t\t\tD3D12XBOX_CREATE_DEVICE_PARAMETERS params = {};\n\t\t\t\tparams.Version = D3D12_SDK_VERSION;\n\t\t\t\tparams.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAGS(0\n\t\t\t\t\t| (_init.debug   ? D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG        : 0)\n\t\t\t\t\t| (_init.profile ? D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED : 0)\n\t\t\t\t\t);\n\t\t\t\tparams.GraphicsCommandQueueRingSizeBytes = UINT32_MAX;\n\t\t\t\tparams.GraphicsScratchMemorySizeBytes    = UINT32_MAX;\n\t\t\t\tparams.ComputeScratchMemorySizeBytes     = UINT32_MAX;\n\t\t\t\tparams.DisableGeometryShaderAllocations     = true;\n\t\t\t\tparams.DisableTessellationShaderAllocations = true;\n\n\t\t\t\thr = D3D12XboxCreateDevice(\n\t\t\t\t\t\t  m_dxgi.m_adapter\n\t\t\t\t\t\t, &params\n\t\t\t\t\t\t, IID_ID3D12Device\n\t\t\t\t\t\t, (void**)&m_device\n\t\t\t\t\t\t);\n\t\t\t\tm_featureLevel = D3D_FEATURE_LEVEL_12_1;\n\n\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t{\n\t\t\t\t\tm_device->SetDebugErrorFilterX(0x73EC9EAF, D3D12XBOX_DEBUG_FILTER_FLAG_DISABLE_BREAKS);\n\t\t\t\t\tm_device->SetDebugErrorFilterX(0x8EC9B15C, D3D12XBOX_DEBUG_FILTER_FLAG_DISABLE_OUTPUT);\n\t\t\t\t}\n#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\t}\n\n\t\t\tif (FAILED(hr) )\n\t\t\t{\n\t\t\t\tBX_TRACE("Init error: Unable to create Direct3D12 device.");\n\t\t\t\tif (BX_ENABLED(BX_PLATFORM_WINRT) )\n\t\t\t\t{\n\t\t\t\t\tBX_TRACE("Hint: Change UWP app to game?");\n\t\t\t\t}\n\t\t\t\tgoto error;\n\t\t\t}\n\n#if !BX_PLATFORM_LINUX\n\t\t\tm_dxgi.update(m_device);\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\t{\n\t\t\t\tm_deviceInterfaceVersion = 0;\n\t\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(s_d3dDeviceIIDs); ++ii)\n\t\t\t\t{\n\t\t\t\t\tID3D12Device* device;\n\t\t\t\t\thr = m_device->QueryInterface(s_d3dDeviceIIDs[ii], (void**)&device);\n\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tdevice->Release(); // BK - ignore ref count.\n\t\t\t\t\t\tm_deviceInterfaceVersion = BX_COUNTOF(s_d3dDeviceIIDs) - ii;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n#if !BX_PLATFORM_LINUX\n\t\t\tif (BGFX_PCI_ID_NVIDIA != m_dxgi.m_adapterDesc.VendorId)\n\t\t\t{\n\t\t\t\tm_nvapi.shutdown();\n\t\t\t}\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\t{\n\t\t\t\tuint32_t numNodes = m_device->GetNodeCount();\n\t\t\t\tBX_TRACE("D3D12 GPU Architecture (num nodes: %d):", numNodes);\n\t\t\t\tfor (uint32_t ii = 0; ii < numNodes; ++ii)\n\t\t\t\t{\n\t\t\t\t\tD3D12_FEATURE_DATA_ARCHITECTURE architecture;\n\t\t\t\t\tarchitecture.NodeIndex = ii;\n\t\t\t\t\tDX_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &architecture, sizeof(architecture) ) );\n\t\t\t\t\tBX_TRACE("\\tNode % 2d: TileBasedRenderer %d, UMA %d, CacheCoherentUMA %d"\n\t\t\t\t\t\t, ii\n\t\t\t\t\t\t, architecture.TileBasedRenderer\n\t\t\t\t\t\t, architecture.UMA\n\t\t\t\t\t\t, architecture.CacheCoherentUMA\n\t\t\t\t\t\t);\n\t\t\t\t\tif (0 == ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tbx::memCopy(&m_architecture, &architecture, sizeof(architecture) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDX_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &m_options, sizeof(m_options) ) );\n\t\t\tBX_TRACE("D3D12 options:");\n\t\t\tBX_TRACE("\\tTiledResourcesTier %d", m_options.TiledResourcesTier);\n\t\t\tBX_TRACE("\\tResourceBindingTier %d", m_options.ResourceBindingTier);\n\t\t\tBX_TRACE("\\tROVsSupported %d", m_options.ROVsSupported);\n\t\t\tBX_TRACE("\\tConservativeRasterizationTier %d", m_options.ConservativeRasterizationTier);\n\t\t\tBX_TRACE("\\tCrossNodeSharingTier %d", m_options.CrossNodeSharingTier);\n\t\t\tBX_TRACE("\\tResourceHeapTier %d", m_options.ResourceHeapTier);\n\n\t\t\tinitHeapProperties(m_device);\n\n\t\t\tm_cmd.init(m_device);\n\t\t\tm_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, m_cmd.m_commandQueue);\n\t\t\terrorState = ErrorState::CreatedCommandQueue;\n\n\t\t\tif (NULL == g_platformData.backBuffer)\n\t\t\t{\n\t\t\t\tbx::memSet(&m_scd, 0, sizeof(m_scd) );\n\t\t\t\tm_scd.width  = _init.resolution.width;\n\t\t\t\tm_scd.height = _init.resolution.height;\n\t\t\t\tm_scd.format = s_textureFormat[_init.resolution.format].m_fmt;\n\t\t\t\tm_scd.stereo  = false;\n\n\t\t\t\tupdateMsaa(m_scd.format);\n\t\t\t\tm_scd.sampleDesc = s_msaa[(_init.resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT];\n\n\t\t\t\tm_scd.bufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;\n\t\t\t\tm_scd.bufferCount = bx::clamp<uint8_t>(_init.resolution.numBackBuffers, 2, BX_COUNTOF(m_backBufferColor) );\n\t\t\t\tm_scd.scaling = 0 == g_platformData.ndt\n\t\t\t\t\t? DXGI_SCALING_NONE\n\t\t\t\t\t: DXGI_SCALING_STRETCH\n\t\t\t\t\t;\n\t\t\t\tm_scd.swapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;\n\t\t\t\tm_scd.alphaMode  = DXGI_ALPHA_MODE_IGNORE;\n\t\t\t\tm_scd.flags      = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;\n\n\t\t\t\tm_scd.maxFrameLatency = bx::min<uint8_t>(_init.resolution.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY);\n\t\t\t\tm_scd.nwh             = g_platformData.nwh;\n\t\t\t\tm_scd.ndt             = g_platformData.ndt;\n\t\t\t\tm_scd.windowed        = true;\n\n\t\t\t\tm_backBufferColorIdx = m_scd.bufferCount-1;\n\n\t\t\t\tm_msaaRt = NULL;\n\n\t\t\t\tif (NULL != m_scd.nwh)\n\t\t\t\t{\n#if BX_PLATFORM_LINUX\n\t\t\t\t\thr = E_FAIL;\n#else\n\t\t\t\t\thr = m_dxgi.createSwapChain(\n\t\t\t\t\t\t  getDeviceForSwapChain()\n\t\t\t\t\t\t, m_scd\n\t\t\t\t\t\t, &m_swapChain\n\t\t\t\t\t\t);\n#endif // BX_PLATFORM_LINUX\n\n\t\t\t\t\tif (FAILED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_TRACE("Init error: Unable to create Direct3D12 swap chain.");\n\t\t\t\t\t\tgoto error;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_resolution       = _init.resolution;\n\t\t\t\t\t\tm_resolution.reset = _init.resolution.reset & (~BGFX_RESET_INTERNAL_FORCE);\n\n\t\t\t\t\t\tm_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height);\n\t\t\t\t\t\tm_textVideoMem.clear();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (1 < m_scd.sampleDesc.Count)\n\t\t\t\t\t{\n\t\t\t\t\t\tD3D12_RESOURCE_DESC resourceDesc;\n\t\t\t\t\t\tresourceDesc.Dimension  = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\n\t\t\t\t\t\tresourceDesc.Alignment  = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;\n\t\t\t\t\t\tresourceDesc.Width      = m_scd.width;\n\t\t\t\t\t\tresourceDesc.Height     = m_scd.height;\n\t\t\t\t\t\tresourceDesc.MipLevels  = 1;\n\t\t\t\t\t\tresourceDesc.Format     = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? s_textureFormat[m_resolution.format].m_fmtSrgb\n\t\t\t\t\t\t\t\t\t\t\t\t\t: s_textureFormat[m_resolution.format].m_fmt;\n\t\t\t\t\t\tresourceDesc.SampleDesc = m_scd.sampleDesc;\n\t\t\t\t\t\tresourceDesc.Layout     = D3D12_TEXTURE_LAYOUT_UNKNOWN;\n\t\t\t\t\t\tresourceDesc.Flags      = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;\n\t\t\t\t\t\tresourceDesc.DepthOrArraySize = 1;\n\n\t\t\t\t\t\tD3D12_CLEAR_VALUE clearValue;\n\t\t\t\t\t\tclearValue.Format   = resourceDesc.Format;\n\t\t\t\t\t\tclearValue.Color[0] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[1] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[2] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[3] = 0.0f;\n\n\t\t\t\t\t\tm_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true);\n\t\t\t\t\t\tsetDebugObjectName(m_msaaRt, "MSAA Backbuffer");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_presentElapsed = 0;\n\n\t\t\t{\n\t\t\t\tm_resolution.width  = _init.resolution.width;\n\t\t\t\tm_resolution.height = _init.resolution.height;\n\n\t\t\t\tm_windows[0] = BGFX_INVALID_HANDLE;\n\t\t\t\tm_numWindows = 1;\n\n#if BX_PLATFORM_WINDOWS\n\t\t\t\tm_infoQueue = NULL;\n\n\t\t\t\tDX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh\n\t\t\t\t\t, 0\n\t\t\t\t\t| DXGI_MWA_NO_WINDOW_CHANGES\n\t\t\t\t\t| DXGI_MWA_NO_ALT_ENTER\n\t\t\t\t\t) );\n\n\t\t\t\tif (_init.debug)\n\t\t\t\t{\n\t\t\t\t\thr = m_device->QueryInterface(IID_ID3D12InfoQueue, (void**)&m_infoQueue);\n\n\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tm_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);\n\t\t\t\t\t\tm_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR,      true);\n\t\t\t\t\t\tm_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING,    false);\n\n\t\t\t\t\t\tD3D12_INFO_QUEUE_FILTER filter;\n\t\t\t\t\t\tbx::memSet(&filter, 0, sizeof(filter) );\n\n\t\t\t\t\t\tD3D12_MESSAGE_CATEGORY catlist[] =\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tD3D12_MESSAGE_CATEGORY_STATE_CREATION,\n\t\t\t\t\t\t\tD3D12_MESSAGE_CATEGORY_EXECUTION,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tfilter.DenyList.NumCategories = BX_COUNTOF(catlist);\n\t\t\t\t\t\tfilter.DenyList.pCategoryList = catlist;\n\t\t\t\t\t\tm_infoQueue->PushStorageFilter(&filter);\n\t\t\t\t\t}\n\t\t\t\t}\n#endif // BX_PLATFORM_WINDOWS\n\n\t\t\t\tD3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap;\n\t\t\t\trtvDescHeap.NumDescriptors = 0\n\t\t\t\t\t+ BX_COUNTOF(m_backBufferColor)\n\t\t\t\t\t+ BGFX_CONFIG_MAX_FRAME_BUFFERS*BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS\n\t\t\t\t\t;\n\t\t\t\trtvDescHeap.Type     = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;\n\t\t\t\trtvDescHeap.Flags    = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;\n\t\t\t\trtvDescHeap.NodeMask = 1;\n\t\t\t\tDX_CHECK(m_device->CreateDescriptorHeap(&rtvDescHeap\n\t\t\t\t\t, IID_ID3D12DescriptorHeap\n\t\t\t\t\t, (void**)&m_rtvDescriptorHeap\n\t\t\t\t\t) );\n\n\t\t\t\tD3D12_DESCRIPTOR_HEAP_DESC dsvDescHeap;\n\t\t\t\tdsvDescHeap.NumDescriptors = 0\n\t\t\t\t\t+ 1 // reserved for depth backbuffer.\n\t\t\t\t\t+ BGFX_CONFIG_MAX_FRAME_BUFFERS\n\t\t\t\t\t;\n\t\t\t\tdsvDescHeap.Type     = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;\n\t\t\t\tdsvDescHeap.Flags    = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;\n\t\t\t\tdsvDescHeap.NodeMask = 1;\n\t\t\t\tDX_CHECK(m_device->CreateDescriptorHeap(&dsvDescHeap\n\t\t\t\t\t, IID_ID3D12DescriptorHeap\n\t\t\t\t\t, (void**)&m_dsvDescriptorHeap\n\t\t\t\t\t) );\n\n\t\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii)\n\t\t\t\t{\n\t\t\t\t\tm_scratchBuffer[ii].create(BGFX_CONFIG_MAX_DRAW_CALLS*1024\n\t\t\t\t\t\t, BGFX_CONFIG_MAX_TEXTURES + BGFX_CONFIG_MAX_SHADERS + BGFX_CONFIG_MAX_DRAW_CALLS\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tm_samplerAllocator.create(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER\n\t\t\t\t\t, 1024\n\t\t\t\t\t, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS\n\t\t\t\t\t);\n\n\t\t\t\tD3D12_DESCRIPTOR_RANGE descRange[] =\n\t\t\t\t{\n\t\t\t\t\t{ D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND },\n\t\t\t\t\t{ D3D12_DESCRIPTOR_RANGE_TYPE_SRV,     BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND },\n\t\t\t\t\t{ D3D12_DESCRIPTOR_RANGE_TYPE_CBV,     1,                                0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND },\n\t\t\t\t\t{ D3D12_DESCRIPTOR_RANGE_TYPE_UAV,     BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND },\n\t\t\t\t};\n\t\t\t\tBX_STATIC_ASSERT(BX_COUNTOF(descRange) == Rdt::Count);\n\n\t\t\t\tD3D12_ROOT_PARAMETER rootParameter[] =\n\t\t\t\t{\n\t\t\t\t\t{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::Sampler] } }, D3D12_SHADER_VISIBILITY_ALL },\n\t\t\t\t\t{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::SRV]     } }, D3D12_SHADER_VISIBILITY_ALL },\n\t\t\t\t\t{ D3D12_ROOT_PARAMETER_TYPE_CBV,              { { 0, 0                        } }, D3D12_SHADER_VISIBILITY_ALL },\n\t\t\t\t\t{ D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { { 1, &descRange[Rdt::UAV]     } }, D3D12_SHADER_VISIBILITY_ALL },\n\t\t\t\t};\n\t\t\t\trootParameter[Rdt::CBV].Descriptor.RegisterSpace  = 0;\n\t\t\t\trootParameter[Rdt::CBV].Descriptor.ShaderRegister = 0;\n\n\t\t\t\tD3D12_ROOT_SIGNATURE_DESC descRootSignature;\n\t\t\t\tdescRootSignature.NumParameters = BX_COUNTOF(rootParameter);\n\t\t\t\tdescRootSignature.pParameters   = rootParameter;\n\t\t\t\tdescRootSignature.NumStaticSamplers = 0;\n\t\t\t\tdescRootSignature.pStaticSamplers   = NULL;\n\t\t\t\tdescRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;\n\n\t\t\t\tID3DBlob* outBlob;\n\t\t\t\tID3DBlob* errorBlob;\n\t\t\t\tDX_CHECK(D3D12SerializeRootSignature(&descRootSignature\n\t\t\t\t\t, D3D_ROOT_SIGNATURE_VERSION_1\n\t\t\t\t\t, &outBlob\n\t\t\t\t\t, &errorBlob\n\t\t\t\t\t) );\n\n\t\t\t\tDX_CHECK(m_device->CreateRootSignature(0\n\t\t\t\t\t, outBlob->GetBufferPointer()\n\t\t\t\t\t, outBlob->GetBufferSize()\n\t\t\t\t\t, IID_ID3D12RootSignature\n\t\t\t\t\t, (void**)&m_rootSignature\n\t\t\t\t\t) );\n\n\t\t\t\t///\n\t\t\t\tm_directAccessSupport = true\n\t\t\t\t\t&& BX_ENABLED(BX_PLATFORM_XBOXONE)\n\t\t\t\t\t&& m_architecture.UMA\n\t\t\t\t\t;\n\n\t\t\t\tg_caps.supported |= ( 0\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_3D\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_COMPARE_ALL\n\t\t\t\t\t| BGFX_CAPS_INDEX32\n\t\t\t\t\t| BGFX_CAPS_INSTANCING\n\t\t\t\t\t| BGFX_CAPS_DRAW_INDIRECT\n\t\t\t\t\t| BGFX_CAPS_VERTEX_ATTRIB_HALF\n\t\t\t\t\t| BGFX_CAPS_VERTEX_ATTRIB_UINT10\n\t\t\t\t\t| BGFX_CAPS_VERTEX_ID\n\t\t\t\t\t| BGFX_CAPS_FRAGMENT_DEPTH\n\t\t\t\t\t| BGFX_CAPS_BLEND_INDEPENDENT\n\t\t\t\t\t| BGFX_CAPS_COMPUTE\n\t\t\t\t\t| (m_options.ROVsSupported ? BGFX_CAPS_FRAGMENT_ORDERING     : 0)\n\t\t\t\t\t| (m_directAccessSupport   ? BGFX_CAPS_TEXTURE_DIRECT_ACCESS : 0)\n\t\t\t\t\t| (BX_ENABLED(BX_PLATFORM_WINDOWS) ? BGFX_CAPS_SWAP_CHAIN : 0)\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_BLIT\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_READ_BACK\n\t\t\t\t\t| BGFX_CAPS_OCCLUSION_QUERY\n\t\t\t\t\t| BGFX_CAPS_ALPHA_TO_COVERAGE\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_2D_ARRAY\n\t\t\t\t\t| BGFX_CAPS_TEXTURE_CUBE_ARRAY\n\t\t\t\t\t| BGFX_CAPS_IMAGE_RW\n\t\t\t\t\t| BGFX_CAPS_VIEWPORT_LAYER_ARRAY\n\t\t\t\t\t| BGFX_CAPS_DRAW_INDIRECT_COUNT\n\t\t\t\t\t);\n\t\t\t\tg_caps.limits.maxTextureSize     = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;\n\t\t\t\tg_caps.limits.maxTextureLayers   = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;\n\t\t\t\tg_caps.limits.maxFBAttachments   = bx::min<uint8_t>(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS);\n\t\t\t\tg_caps.limits.maxComputeBindings = bx::min(D3D12_UAV_SLOT_COUNT, BGFX_MAX_COMPUTE_BINDINGS);\n\t\t\t\tg_caps.limits.maxVertexStreams   = BGFX_CONFIG_MAX_VERTEX_STREAMS;\n\n\t\t\t\tfor (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)\n\t\t\t\t{\n\t\t\t\t\tuint16_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE;\n\n\t\t\t\t\tconst DXGI_FORMAT fmt = bimg::isDepth(bimg::TextureFormat::Enum(ii) )\n\t\t\t\t\t\t? s_textureFormat[ii].m_fmtDsv\n\t\t\t\t\t\t: s_textureFormat[ii].m_fmt\n\t\t\t\t\t\t;\n\t\t\t\t\tconst DXGI_FORMAT fmtSrgb = s_textureFormat[ii].m_fmtSrgb;\n\n\t\t\t\t\tif (DXGI_FORMAT_UNKNOWN != fmt)\n\t\t\t\t\t{\n\t\t\t\t\t\tD3D12_FEATURE_DATA_FORMAT_SUPPORT data;\n\t\t\t\t\t\tdata.Format = fmt;\n\t\t\t\t\t\thr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );\n\t\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURE2D\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_2D\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURE3D\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_3D\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURECUBE\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_CUBE\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_BUFFER\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_VERTEX\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_SHADER_LOAD\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_RENDER_TARGET\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RENDERTARGET\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_MSAA\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// clear image flag for additional testing\n\t\t\t\t\t\t\tsupport &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ;\n\n\t\t\t\t\t\t\tdata.Format = s_textureFormat[ii].m_fmt;\n\t\t\t\t\t\t\thr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );\n\t\t\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsupport |= 0 != (data.Support2 & (0\n\t\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD\n\t\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ\n\t\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t\tsupport |= 0 != (data.Support2 & (0\n\t\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE\n\t\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE\n\t\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (DXGI_FORMAT_UNKNOWN != fmtSrgb)\n\t\t\t\t\t{\n\t\t\t\t\t\tstruct D3D11_FEATURE_DATA_FORMAT_SUPPORT\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDXGI_FORMAT InFormat;\n\t\t\t\t\t\t\tuint32_t OutFormatSupport;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tD3D12_FEATURE_DATA_FORMAT_SUPPORT data;\n\t\t\t\t\t\tdata.Format = fmtSrgb;\n\t\t\t\t\t\thr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );\n\t\t\t\t\t\tif (SUCCEEDED(hr) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURE2D\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURE3D\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tsupport |= 0 != (data.Support1 & (0\n\t\t\t\t\t\t\t\t\t| D3D12_FORMAT_SUPPORT1_TEXTURECUBE\n\t\t\t\t\t\t\t\t\t) )\n\t\t\t\t\t\t\t\t\t? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB\n\t\t\t\t\t\t\t\t\t: BGFX_CAPS_FORMAT_TEXTURE_NONE\n\t\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tg_caps.formats[ii] = support;\n\t\t\t\t}\n\n\t\t\t\t// Init reserved part of view name.\n\t\t\t\tfor (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii)\n\t\t\t\t{\n\t\t\t\t\tbx::snprintf(s_viewName[ii], BGFX_CONFIG_MAX_VIEW_NAME_RESERVED + 1, "%3d   ", ii);\n\t\t\t\t}\n\n\t\t\t\tpostReset();\n\n\t\t\t\tm_batch.create(4<<10);\n#if !BX_PLATFORM_LINUX\n\t\t\t\tm_batch.setIndirectMode(BGFX_PCI_ID_NVIDIA != m_dxgi.m_adapterDesc.VendorId && BGFX_PCI_ID_MICROSOFT != m_dxgi.m_adapterDesc.VendorId);\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\t\tm_gpuTimer.init();\n\t\t\t\tm_occlusionQuery.init();\n\n\t\t\t\t{\n\t\t\t\t\tD3D12_INDIRECT_ARGUMENT_TYPE argType[] =\n\t\t\t\t\t{\n\t\t\t\t\t\tD3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,\n\t\t\t\t\t\tD3D12_INDIRECT_ARGUMENT_TYPE_DRAW,\n\t\t\t\t\t\tD3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,\n\t\t\t\t\t};\n\n\t\t\t\t\tD3D12_INDIRECT_ARGUMENT_DESC argDesc;\n\t\t\t\t\tbx::memSet(&argDesc, 0, sizeof(argDesc) );\n\n\t\t\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_commandSignature); ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\targDesc.Type = argType[ii];\n\t\t\t\t\t\tD3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = { BGFX_CONFIG_DRAW_INDIRECT_STRIDE, 1, &argDesc, 1 };\n\n\t\t\t\t\t\tm_commandSignature[ii] = NULL;\n\t\t\t\t\t\tDX_CHECK(m_device->CreateCommandSignature(&commandSignatureDesc\n\t\t\t\t\t\t\t, NULL\n\t\t\t\t\t\t\t, IID_ID3D12CommandSignature\n\t\t\t\t\t\t\t, (void**)&m_commandSignature[ii]\n\t\t\t\t\t\t\t) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (m_nvapi.isInitialized() )\n\t\t\t{\n\t\t\t\tfinish();\n\t\t\t\tm_commandList = m_cmd.alloc();\n\t\t\t\tm_nvapi.initAftermath(m_device, m_commandList);\n\t\t\t}\n\n\t\t\tg_internalData.context = m_device;\n\t\t\treturn true;\n\n\t\terror:\n\t\t\tswitch (errorState)\n\t\t\t{\n\t\t\tcase ErrorState::CreatedCommandQueue:\n\t\t\t\tm_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL);\n\t\t\t\tm_cmd.shutdown();\n\t\t\t\tBX_FALLTHROUGH;\n\n\t\t\tcase ErrorState::CreatedDXGIFactory:\n\t\t\t\tDX_RELEASE(m_device,  0);\n#if !BX_PLATFORM_LINUX\n\t\t\t\tm_dxgi.shutdown();\n#endif // !BX_PLATFORM_LINUX\n\t\t\t\tBX_FALLTHROUGH;\n\n#if USE_D3D12_DYNAMIC_LIB\n\t\t\tcase ErrorState::LoadedDXGI:\n\t\t\tcase ErrorState::LoadedD3D12:\n\t\t\t\tbx::dlclose(m_d3d12Dll);\n\t\t\t\tBX_FALLTHROUGH;\n\n\t\t\tcase ErrorState::LoadedKernel32:\n\t\t\t\tbx::dlclose(m_kernel32Dll);\n\t\t\t\tBX_FALLTHROUGH;\n\n#endif // USE_D3D12_DYNAMIC_LIB\n\t\t\tcase ErrorState::Default:\n\t\t\tdefault:\n\t\t\t\tm_nvapi.shutdown();\n\n\t\t\t\tunloadRenderDoc(m_renderDocDll);\n\t\t\t\tbx::dlclose(m_winPixEvent);\n\t\t\t\tm_winPixEvent = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tvoid shutdown()\n\t\t{\n\t\t\tm_cmd.finish();\n\t\t\tm_batch.destroy();\n\n\t\t\tpreReset();\n\n\t\t\tm_gpuTimer.shutdown();\n\t\t\tm_occlusionQuery.shutdown();\n\n\t\t\tm_samplerAllocator.destroy();\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii)\n\t\t\t{\n\t\t\t\tm_scratchBuffer[ii].destroy();\n\t\t\t}\n\n\t\t\tm_pipelineStateCache.invalidate();\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii)\n\t\t\t{\n\t\t\t\tm_indexBuffers[ii].destroy();\n\t\t\t}\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_vertexBuffers); ++ii)\n\t\t\t{\n\t\t\t\tm_vertexBuffers[ii].destroy();\n\t\t\t}\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_shaders); ++ii)\n\t\t\t{\n\t\t\t\tm_shaders[ii].destroy();\n\t\t\t}\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_textures); ++ii)\n\t\t\t{\n\t\t\t\tm_textures[ii].destroy();\n\t\t\t}\n\n#if BX_PLATFORM_WINDOWS\n\t\t\tDX_RELEASE_W(m_infoQueue, 0);\n#endif // BX_PLATFORM_WINDOWS\n\n\t\t\tDX_RELEASE(m_rtvDescriptorHeap, 0);\n\t\t\tDX_RELEASE(m_dsvDescriptorHeap, 0);\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_commandSignature); ++ii)\n\t\t\t{\n\t\t\t\tDX_RELEASE(m_commandSignature[ii], 0);\n\t\t\t}\n\n\t\t\tDX_RELEASE(m_rootSignature, 0);\n\t\t\tDX_RELEASE(m_msaaRt, 0);\n\t\t\tDX_RELEASE(m_swapChain, 0);\n\n\t\t\tm_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL);\n\t\t\tm_cmd.shutdown();\n\n\t\t\tDX_RELEASE(m_device, 0);\n\n\t\t\tm_nvapi.shutdown();\n#if !BX_PLATFORM_LINUX\n\t\t\tm_dxgi.shutdown();\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\tunloadRenderDoc(m_renderDocDll);\n\n\t\t\tbx::dlclose(m_winPixEvent);\n\t\t\tm_winPixEvent = NULL;\n\n#if USE_D3D12_DYNAMIC_LIB\n\t\t\tbx::dlclose(m_d3d12Dll);\n\t\t\tbx::dlclose(m_kernel32Dll);\n#endif // USE_D3D12_DYNAMIC_LIB\n\t\t}\n\n\t\tRendererType::Enum getRendererType() const override\n\t\t{\n\t\t\treturn RendererType::Direct3D12;\n\t\t}\n\n\t\tconst char* getRendererName() const override\n\t\t{\n\t\t\treturn BGFX_RENDERER_DIRECT3D12_NAME;\n\t\t}\n\n\t\tbool isDeviceRemoved() override\n\t\t{\n\t\t\treturn m_lost;\n\t\t}\n\n\t\tvoid flip() override\n\t\t{\n\t\t\tif (!m_lost)\n\t\t\t{\n\t\t\t\tint64_t start = bx::getHPCounter();\n\n\t\t\t\tm_cmd.finish(m_backBufferColorFence[(m_backBufferColorIdx-1) % m_scd.bufferCount]);\n\n\t\t\t\tHRESULT hr = S_OK;\n\t\t\t\tuint32_t syncInterval = !!(m_resolution.reset & BGFX_RESET_VSYNC);\n\t\t\t\tuint32_t presentFlags = 0;\n\t\t\t\tif (syncInterval)\n\t\t\t\t{\n\t\t\t\t\tpresentFlags |= DXGI_PRESENT_RESTART;\n\t\t\t\t}\n#if !BX_PLATFORM_LINUX\n\t\t\t\telse if (m_dxgi.tearingSupported() )\n\t\t\t\t{\n\t\t\t\t\tpresentFlags |= DXGI_PRESENT_ALLOW_TEARING;\n\t\t\t\t}\n#endif // !BX_PLATFORM_LINUX\n\n\t\t\t\tfor (uint32_t ii = 1, num = m_numWindows; ii < num && SUCCEEDED(hr); ++ii)\n\t\t\t\t{\n\t\t\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[m_windows[ii].idx];\n\t\t\t\t\thr = frameBuffer.present(syncInterval, presentFlags);\n\t\t\t\t}\n\n\t\t\t\tif (SUCCEEDED(hr)\n\t\t\t\t&&  NULL != m_swapChain)\n\t\t\t\t{\n\t\t\t\t\thr = m_swapChain->Present(syncInterval, presentFlags);\n\t\t\t\t}\n\n\t\t\t\tint64_t now = bx::getHPCounter();\n\t\t\t\tm_presentElapsed = now - start;\n\n\t\t\t\tm_lost = isLost(hr);\n\t\t\t\tBGFX_FATAL(!m_lost\n\t\t\t\t\t, bgfx::Fatal::DeviceLost\n\t\t\t\t\t, "Device is lost. FAILED 0x%08x %s (%s)"\n\t\t\t\t\t, hr\n\t\t\t\t\t, getLostReason(hr)\n\t\t\t\t\t, DXGI_ERROR_DEVICE_REMOVED == hr ? getLostReason(m_device->GetDeviceRemovedReason() ) : "no info"\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvoid createIndexBuffer(IndexBufferHandle _handle, const Memory* _mem, uint16_t _flags) override\n\t\t{\n\t\t\tm_indexBuffers[_handle.idx].create(_mem->size, _mem->data, _flags, false);\n\t\t}\n\n\t\tvoid destroyIndexBuffer(IndexBufferHandle _handle) override\n\t\t{\n\t\t\tm_indexBuffers[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createVertexLayout(VertexLayoutHandle _handle, const VertexLayout& _layout) override\n\t\t{\n\t\t\tVertexLayout& layout = m_vertexLayouts[_handle.idx];\n\t\t\tbx::memCopy(&layout, &_layout, sizeof(VertexLayout) );\n\t\t\tdump(layout);\n\t\t}\n\n\t\tvoid destroyVertexLayout(VertexLayoutHandle /*_handle*/) override\n\t\t{\n\t\t}\n\n\t\tvoid createVertexBuffer(VertexBufferHandle _handle, const Memory* _mem, VertexLayoutHandle _layoutHandle, uint16_t _flags) override\n\t\t{\n\t\t\tm_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _layoutHandle, _flags);\n\t\t}\n\n\t\tvoid destroyVertexBuffer(VertexBufferHandle _handle) override\n\t\t{\n\t\t\tm_vertexBuffers[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint16_t _flags) override\n\t\t{\n\t\t\tm_indexBuffers[_handle.idx].create(_size, NULL, _flags, false);\n\t\t}\n\n\t\tvoid updateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override\n\t\t{\n\t\t\tm_indexBuffers[_handle.idx].update(m_commandList, _offset, bx::uint32_min(_size, _mem->size), _mem->data);\n\t\t}\n\n\t\tvoid destroyDynamicIndexBuffer(IndexBufferHandle _handle) override\n\t\t{\n\t\t\tm_indexBuffers[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint16_t _flags) override\n\t\t{\n\t\t\tVertexLayoutHandle layoutHandle = BGFX_INVALID_HANDLE;\n\t\t\tm_vertexBuffers[_handle.idx].create(_size, NULL, layoutHandle, _flags);\n\t\t}\n\n\t\tvoid updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override\n\t\t{\n\t\t\tm_vertexBuffers[_handle.idx].update(m_commandList, _offset, bx::uint32_min(_size, _mem->size), _mem->data);\n\t\t}\n\n\t\tvoid destroyDynamicVertexBuffer(VertexBufferHandle _handle) override\n\t\t{\n\t\t\tm_vertexBuffers[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createShader(ShaderHandle _handle, const Memory* _mem) override\n\t\t{\n\t\t\tm_shaders[_handle.idx].create(_mem);\n\t\t}\n\n\t\tvoid destroyShader(ShaderHandle _handle) override\n\t\t{\n\t\t\tm_shaders[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createProgram(ProgramHandle _handle, ShaderHandle _vsh, ShaderHandle _fsh) override\n\t\t{\n\t\t\tm_program[_handle.idx].create(&m_shaders[_vsh.idx], isValid(_fsh) ? &m_shaders[_fsh.idx] : NULL);\n\t\t}\n\n\t\tvoid destroyProgram(ProgramHandle _handle) override\n\t\t{\n\t\t\tm_program[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid* createTexture(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip) override\n\t\t{\n\t\t\treturn m_textures[_handle.idx].create(_mem, _flags, _skip);\n\t\t}\n\n\t\tvoid updateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/) override\n\t\t{\n\t\t}\n\n\t\tvoid updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) override\n\t\t{\n\t\t\tm_textures[_handle.idx].update(m_commandList, _side, _mip, _rect, _z, _depth, _pitch, _mem);\n\t\t}\n\n\t\tvoid updateTextureEnd() override\n\t\t{\n\t\t}\n\n\t\tvoid readTexture(TextureHandle _handle, void* _data, uint8_t _mip ) override\n\t\t{\n\t\t\tconst TextureD3D12& texture = m_textures[_handle.idx];\n\n\t\t\tD3D12_RESOURCE_DESC desc = getResourceDesc(texture.m_ptr);\n\n\t\t\tD3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;\n\t\t\tuint32_t numRows;\n\t\t\tuint64_t total;\n\t\t\tm_device->GetCopyableFootprints(&desc\n\t\t\t\t, _mip\n\t\t\t\t, 1\n\t\t\t\t, 0\n\t\t\t\t, &layout\n\t\t\t\t, &numRows\n\t\t\t\t, NULL\n\t\t\t\t, &total\n\t\t\t\t);\n\n\t\t\tuint32_t srcPitch = layout.Footprint.RowPitch;\n\n\t\t\tID3D12Resource* readback = createCommittedResource(m_device, HeapProperty::ReadBack, total);\n\n\t\t\tuint32_t srcWidth  = bx::uint32_max(1, texture.m_width >>_mip);\n\t\t\tuint32_t srcHeight = bx::uint32_max(1, texture.m_height>>_mip);\n\n\t\t\tD3D12_BOX box;\n\t\t\tbox.left   = 0;\n\t\t\tbox.top    = 0;\n\t\t\tbox.right  = srcWidth;\n\t\t\tbox.bottom = srcHeight;\n\t\t\tbox.front  = 0;\n\t\t\tbox.back   = 1;\n\n\t\t\tD3D12_TEXTURE_COPY_LOCATION dstLocation = { readback,      D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,  { layout } };\n\t\t\tD3D12_TEXTURE_COPY_LOCATION srcLocation = { texture.m_ptr, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { }        };\n\t\t\tsrcLocation.SubresourceIndex = _mip;\n\t\t\tm_commandList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &box);\n\n\t\t\tfinish();\n\t\t\tm_commandList = m_cmd.alloc();\n\n\t\t\tconst uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat) );\n\t\t\tuint8_t* dst      = (uint8_t*)_data;\n\t\t\tuint32_t dstPitch = srcWidth*bpp/8;\n\n\t\t\tuint32_t pitch = bx::uint32_min(srcPitch, dstPitch);\n\n\t\t\tuint8_t* src;\n\t\t\treadback->Map(0, NULL, (void**)&src);\n\n\t\t\tfor (uint32_t yy = 0, height = srcHeight; yy < height; ++yy)\n\t\t\t{\n\t\t\t\tbx::memCopy(dst, src, pitch);\n\n\t\t\t\tsrc += srcPitch;\n\t\t\t\tdst += dstPitch;\n\t\t\t}\n\n\t\t\tD3D12_RANGE writeRange = { 0, 0 };\n\t\t\treadback->Unmap(0, &writeRange);\n\n\t\t\tDX_RELEASE(readback, 0);\n\t\t}\n\n\t\tvoid resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override\n\t\t{\n\t\t\tTextureD3D12& texture = m_textures[_handle.idx];\n\n\t\t\tuint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);\n\t\t\tconst Memory* mem = alloc(size);\n\n\t\t\tbx::StaticMemoryBlockWriter writer(mem->data, mem->size);\n\t\t\tuint32_t magic = BGFX_CHUNK_MAGIC_TEX;\n\t\t\tbx::write(&writer, magic, bx::ErrorAssert{});\n\n\t\t\tTextureCreate tc;\n\t\t\ttc.m_width     = _width;\n\t\t\ttc.m_height    = _height;\n\t\t\ttc.m_depth     = 0;\n\t\t\ttc.m_numLayers = _numLayers;\n\t\t\ttc.m_numMips   = _numMips;\n\t\t\ttc.m_format    = TextureFormat::Enum(texture.m_requestedFormat);\n\t\t\ttc.m_cubeMap   = false;\n\t\t\ttc.m_mem       = NULL;\n\t\t\tbx::write(&writer, tc, bx::ErrorAssert{});\n\n\t\t\ttexture.destroy();\n\t\t\ttexture.create(mem, texture.m_flags, 0);\n\n\t\t\trelease(mem);\n\t\t}\n\n\t\tvoid overrideInternal(TextureHandle _handle, uintptr_t _ptr) override\n\t\t{\n\t\t\t// Resource ref. counts might be messed up outside of bgfx.\n\t\t\t// Disabling ref. count check once texture is overridden.\n\t\t\tsetGraphicsDebuggerPresent(true);\n\t\t\tm_textures[_handle.idx].overrideInternal(_ptr);\n\t\t}\n\n\t\tuintptr_t getInternal(TextureHandle _handle) override\n\t\t{\n\t\t\tsetGraphicsDebuggerPresent(true);\n\t\t\treturn uintptr_t(m_textures[_handle.idx].m_ptr);\n\t\t}\n\n\t\tvoid destroyTexture(TextureHandle _handle) override\n\t\t{\n\t\t\tm_textures[_handle.idx].destroy();\n\t\t}\n\n\t\tvoid createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) override\n\t\t{\n\t\t\tm_frameBuffers[_handle.idx].create(_num, _attachment);\n\t\t}\n\n\t\tvoid createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override\n\t\t{\n\t\t\tfinishAll(true);\n\n\t\t\tfor (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii)\n\t\t\t{\n\t\t\t\tFrameBufferHandle handle = m_windows[ii];\n\t\t\t\tif (isValid(handle)\n\t\t\t\t&&  m_frameBuffers[handle.idx].m_nwh == _nwh)\n\t\t\t\t{\n\t\t\t\t\tdestroyFrameBuffer(handle);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tuint16_t denseIdx = m_numWindows++;\n\t\t\tm_windows[denseIdx] = _handle;\n\t\t\tm_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat);\n\t\t}\n\n\t\tvoid destroyFrameBuffer(FrameBufferHandle _handle) override\n\t\t{\n\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[_handle.idx];\n\n\t\t\tif (NULL != frameBuffer.m_swapChain)\n\t\t\t{\n\t\t\t\tfinishAll(true);\n\t\t\t}\n\n\t\t\tuint16_t denseIdx = frameBuffer.destroy();\n\t\t\tif (UINT16_MAX != denseIdx)\n\t\t\t{\n\t\t\t\t--m_numWindows;\n\t\t\t\tif (m_numWindows > 1)\n\t\t\t\t{\n\t\t\t\t\tFrameBufferHandle handle = m_windows[m_numWindows];\n\t\t\t\t\tm_windows[m_numWindows]  = {kInvalidHandle};\n\t\t\t\t\tif (m_numWindows != denseIdx)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_windows[denseIdx] = handle;\n\t\t\t\t\t\tm_frameBuffers[handle.idx].m_denseIdx = denseIdx;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) override\n\t\t{\n\t\t\tif (NULL != m_uniforms[_handle.idx])\n\t\t\t{\n\t\t\t\tBX_FREE(g_allocator, m_uniforms[_handle.idx]);\n\t\t\t}\n\n\t\t\tconst uint32_t size = bx::alignUp(g_uniformTypeSize[_type] * _num, 16);\n\t\t\tvoid* data = BX_ALLOC(g_allocator, size);\n\t\t\tbx::memSet(data, 0, size);\n\t\t\tm_uniforms[_handle.idx] = data;\n\t\t\tm_uniformReg.add(_handle, _name);\n\t\t}\n\n\t\tvoid destroyUniform(UniformHandle _handle) override\n\t\t{\n\t\t\tBX_FREE(g_allocator, m_uniforms[_handle.idx]);\n\t\t\tm_uniforms[_handle.idx] = NULL;\n\t\t\tm_uniformReg.remove(_handle);\n\t\t}\n\n\t\tvoid requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override\n\t\t{\n\t\t\tBX_UNUSED(_handle);\n\n\t\t\tuint32_t idx = (m_backBufferColorIdx-1) % m_scd.bufferCount;\n\t\t\tm_cmd.finish(m_backBufferColorFence[idx]);\n\t\t\tID3D12Resource* backBuffer = m_backBufferColor[idx];\n\n\t\t\tD3D12_RESOURCE_DESC desc = getResourceDesc(backBuffer);\n\n\t\t\tconst uint32_t width  = (uint32_t)desc.Width;\n\t\t\tconst uint32_t height = (uint32_t)desc.Height;\n\n\t\t\tD3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;\n\t\t\tuint32_t numRows;\n\t\t\tuint64_t total;\n\t\t\tuint64_t pitch;\n\t\t\tm_device->GetCopyableFootprints(&desc\n\t\t\t\t, 0\n\t\t\t\t, 1\n\t\t\t\t, 0\n\t\t\t\t, &layout\n\t\t\t\t, &numRows\n\t\t\t\t, &pitch\n\t\t\t\t, &total\n\t\t\t\t);\n\n\t\t\tID3D12Resource* readback = createCommittedResource(m_device, HeapProperty::ReadBack, total);\n\n\t\t\tD3D12_BOX box;\n\t\t\tbox.left   = 0;\n\t\t\tbox.top    = 0;\n\t\t\tbox.right  = width;\n\t\t\tbox.bottom = height;\n\t\t\tbox.front  = 0;\n\t\t\tbox.back   = 1;\n\n\t\t\tsetResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_SOURCE);\n\t\t\tD3D12_TEXTURE_COPY_LOCATION dst = { readback,   D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,  { layout } };\n\t\t\tD3D12_TEXTURE_COPY_LOCATION src = { backBuffer, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, {}     };\n\t\t\tm_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &box);\n\t\t\tsetResourceBarrier(m_commandList, backBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT);\n\t\t\tfinish();\n\t\t\tm_commandList = m_cmd.alloc();\n\n\t\t\tvoid* data;\n\t\t\treadback->Map(0, NULL, (void**)&data);\n\t\t\tbimg::imageSwizzleBgra8(\n\t\t\t\t  data\n\t\t\t\t, layout.Footprint.RowPitch\n\t\t\t\t, width\n\t\t\t\t, height\n\t\t\t\t, data\n\t\t\t\t, layout.Footprint.RowPitch\n\t\t\t\t);\n\t\t\tg_callback->screenShot(_filePath\n\t\t\t\t, width\n\t\t\t\t, height\n\t\t\t\t, layout.Footprint.RowPitch\n\t\t\t\t, data\n\t\t\t\t, (uint32_t)total\n\t\t\t\t, false\n\t\t\t\t);\n\t\t\tD3D12_RANGE writeRange = { 0, 0 };\n\t\t\treadback->Unmap(0, &writeRange);\n\n\t\t\tDX_RELEASE(readback, 0);\n\t\t}\n\n\t\tvoid updateViewName(ViewId _id, const char* _name) override\n\t\t{\n\t\t\tbx::strCopy(&s_viewName[_id][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED]\n\t\t\t\t, BX_COUNTOF(s_viewName[0]) - BGFX_CONFIG_MAX_VIEW_NAME_RESERVED\n\t\t\t\t, _name\n\t\t\t\t);\n\t\t}\n\n\t\tvoid updateUniform(uint16_t _loc, const void* _data, uint32_t _size) override\n\t\t{\n\t\t\tbx::memCopy(m_uniforms[_loc], _data, _size);\n\t\t}\n\n\t\tvoid invalidateOcclusionQuery(OcclusionQueryHandle _handle) override\n\t\t{\n\t\t\tm_occlusionQuery.invalidate(_handle);\n\t\t}\n\n\t\tvoid setMarker(const char* _marker, uint16_t _len) override\n\t\t{\n\t\t\tBX_UNUSED(_len);\n\n\t\t\tif (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) )\n\t\t\t{\n\t\t\t\tPIX3_SETMARKER(m_commandList, kColorMarker, _marker);\n\t\t\t}\n\t\t}\n\n\t\tvirtual void setName(Handle _handle, const char* _name, uint16_t _len) override\n\t\t{\n\t\t\tswitch (_handle.type)\n\t\t\t{\n\t\t\tcase Handle::IndexBuffer:\n\t\t\t\tsetDebugObjectName(m_indexBuffers[_handle.idx].m_ptr, "%.*s", _len, _name);\n\t\t\t\tbreak;\n\n\t\t\tcase Handle::Shader:\n//\t\t\t\tsetDebugObjectName(m_shaders[_handle.idx].m_ptr, "%.*s", _len, _name);\n\t\t\t\tbreak;\n\n\t\t\tcase Handle::Texture:\n\t\t\t\tsetDebugObjectName(m_textures[_handle.idx].m_ptr, "%.*s", _len, _name);\n\t\t\t\tbreak;\n\n\t\t\tcase Handle::VertexBuffer:\n\t\t\t\tsetDebugObjectName(m_vertexBuffers[_handle.idx].m_ptr, "%.*s", _len, _name);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tBX_ASSERT(false, "Invalid handle type?! %d", _handle.type);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tvoid submitBlit(BlitState& _bs, uint16_t _view);\n\n\t\tvoid submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) override;\n\n\t\tvoid blitSetup(TextVideoMemBlitter& _blitter) override\n\t\t{\n\t\t\tconst uint32_t width  = m_scd.width;\n\t\t\tconst uint32_t height = m_scd.height;\n\n\t\t\tsetFrameBuffer(BGFX_INVALID_HANDLE, false);\n\n\t\t\tD3D12_VIEWPORT vp;\n\t\t\tvp.TopLeftX = 0;\n\t\t\tvp.TopLeftY = 0;\n\t\t\tvp.Width    = (float)width;\n\t\t\tvp.Height   = (float)height;\n\t\t\tvp.MinDepth = 0.0f;\n\t\t\tvp.MaxDepth = 1.0f;\n\t\t\tm_commandList->RSSetViewports(1, &vp);\n\n\t\t\tD3D12_RECT rc;\n\t\t\trc.left   = 0;\n\t\t\trc.top    = 0;\n\t\t\trc.right  = width;\n\t\t\trc.bottom = height;\n\t\t\tm_commandList->RSSetScissorRects(1, &rc);\n\n\t\t\tconst uint64_t state = 0\n\t\t\t\t| BGFX_STATE_WRITE_RGB\n\t\t\t\t| BGFX_STATE_WRITE_A\n\t\t\t\t| BGFX_STATE_DEPTH_TEST_ALWAYS\n\t\t\t\t;\n\n\t\t\tconst VertexLayout* layouts[1] = { &m_vertexLayouts[_blitter.m_vb->layoutHandle.idx] };\n\t\t\tID3D12PipelineState* pso = getPipelineState(state\n\t\t\t\t, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT)\n\t\t\t\t, 1\n\t\t\t\t, layouts\n\t\t\t\t, _blitter.m_program\n\t\t\t\t, 0\n\t\t\t\t);\n\t\t\tm_commandList->SetPipelineState(pso);\n\t\t\tm_commandList->SetGraphicsRootSignature(m_rootSignature);\n\n\t\t\tfloat proj[16];\n\t\t\tbx::mtxOrtho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f, 0.0f, false);\n\n\t\t\tPredefinedUniform& predefined = m_program[_blitter.m_program.idx].m_predefined[0];\n\t\t\tuint8_t flags = predefined.m_type;\n\t\t\tsetShaderUniform(flags, predefined.m_loc, proj, 4);\n\n\t\t\tD3D12_GPU_VIRTUAL_ADDRESS gpuAddress;\n\t\t\tcommitShaderConstants(_blitter.m_program, gpuAddress);\n\n\t\t\tScratchBufferD3D12& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx];\n\t\t\tID3D12DescriptorHeap* heaps[] =\n\t\t\t{\n\t\t\t\tm_samplerAllocator.getHeap(),\n\t\t\t\tscratchBuffer.getHeap(),\n\t\t\t};\n\t\t\tm_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);\n\t\t\tm_commandList->SetGraphicsRootConstantBufferView(Rdt::CBV, gpuAddress);\n\n\t\t\tTextureD3D12& texture = m_textures[_blitter.m_texture.idx];\n\t\t\tuint32_t samplerFlags[] = { uint32_t(texture.m_flags & BGFX_SAMPLER_BITS_MASK) };\n\t\t\tuint16_t samplerStateIdx = getSamplerState(samplerFlags, BX_COUNTOF(samplerFlags), NULL);\n\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );\n\t\t\tD3D12_GPU_DESCRIPTOR_HANDLE srvHandle;\n\t\t\tscratchBuffer.allocSrv(srvHandle, texture);\n\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle);\n\n\t\t\tVertexBufferD3D12&  vb     = m_vertexBuffers[_blitter.m_vb->handle.idx];\n\t\t\tconst VertexLayout& layout = m_vertexLayouts[_blitter.m_vb->layoutHandle.idx];\n\t\t\tD3D12_VERTEX_BUFFER_VIEW viewDesc;\n\t\t\tviewDesc.BufferLocation = vb.m_gpuVA;\n\t\t\tviewDesc.StrideInBytes  = layout.m_stride;\n\t\t\tviewDesc.SizeInBytes    = vb.m_size;\n\t\t\tm_commandList->IASetVertexBuffers(0, 1, &viewDesc);\n\n\t\t\tconst BufferD3D12& ib = m_indexBuffers[_blitter.m_ib->handle.idx];\n\t\t\tD3D12_INDEX_BUFFER_VIEW ibv;\n\t\t\tibv.Format         = DXGI_FORMAT_R16_UINT;\n\t\t\tibv.BufferLocation = ib.m_gpuVA;\n\t\t\tibv.SizeInBytes    = ib.m_size;\n\t\t\tm_commandList->IASetIndexBuffer(&ibv);\n\n\t\t\tm_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\n\t\t}\n\n\t\tvoid blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) override\n\t\t{\n\t\t\tconst uint32_t numVertices = _numIndices*4/6;\n\t\t\tif (0 < numVertices)\n\t\t\t{\n\t\t\t\tm_indexBuffers [_blitter.m_ib->handle.idx].update(m_commandList, 0, _numIndices*2, _blitter.m_ib->data);\n\t\t\t\tm_vertexBuffers[_blitter.m_vb->handle.idx].update(m_commandList, 0, numVertices*_blitter.m_layout.m_stride, _blitter.m_vb->data, true);\n\n\t\t\t\tm_commandList->DrawIndexedInstanced(_numIndices\n\t\t\t\t\t, 1\n\t\t\t\t\t, 0\n\t\t\t\t\t, 0\n\t\t\t\t\t, 0\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvoid preReset()\n\t\t{\n\t\t\tfinishAll();\n\n\t\t\tif (NULL != m_swapChain)\n\t\t\t{\n\t\t\t\tfor (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii)\n\t\t\t\t{\n#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\t\t\tDX_RELEASE(m_backBufferColor[ii], num-1-ii);\n#else\n\t\t\t\t\tDX_RELEASE(m_backBufferColor[ii], 1);\n#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\t\t}\n\t\t\t\tDX_RELEASE(m_backBufferDepthStencil, 0);\n\t\t\t}\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)\n\t\t\t{\n\t\t\t\tm_frameBuffers[ii].preReset();\n\t\t\t}\n\n\t\t\tinvalidateCache();\n\n//\t\t\tcapturePreReset();\n\t\t}\n\n\t\tvoid postReset()\n\t\t{\n\t\t\tbx::memSet(m_backBufferColorFence, 0, sizeof(m_backBufferColorFence) );\n\n\t\t\tuint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\n\n\t\t\tif (NULL != m_swapChain)\n\t\t\t{\n\t\t\t\tfor (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii)\n\t\t\t\t{\n\t\t\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE handle = getCPUHandleHeapStart(m_rtvDescriptorHeap);\n\t\t\t\t\thandle.ptr += ii * rtvDescriptorSize;\n\t\t\t\t\tDX_CHECK(m_swapChain->GetBuffer(ii\n\t\t\t\t\t\t, IID_ID3D12Resource\n\t\t\t\t\t\t, (void**)&m_backBufferColor[ii]\n\t\t\t\t\t\t) );\n\n\t\t\t\t\tD3D12_RENDER_TARGET_VIEW_DESC rtvDesc;\n\t\t\t\t\trtvDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER)\n\t\t\t\t\t\t? s_textureFormat[m_resolution.format].m_fmtSrgb\n\t\t\t\t\t\t: s_textureFormat[m_resolution.format].m_fmt;\n\n\t\t\t\t\tif (1 < getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize)\n\t\t\t\t\t{\n\t\t\t\t\t\trtvDesc.ViewDimension = (NULL == m_msaaRt) ?\n\t\t\t\t\t\t\tD3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\trtvDesc.Texture2DArray.FirstArraySlice = 0;\n\t\t\t\t\t\trtvDesc.Texture2DArray.ArraySize = getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize;\n\t\t\t\t\t\trtvDesc.Texture2DArray.MipSlice = 0;\n\t\t\t\t\t\trtvDesc.Texture2DArray.PlaneSlice = 0;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\trtvDesc.ViewDimension = (NULL == m_msaaRt) ?\n\t\t\t\t\t\t\tD3D12_RTV_DIMENSION_TEXTURE2D : D3D12_RTV_DIMENSION_TEXTURE2DMS;\n\t\t\t\t\t\trtvDesc.Texture2D.MipSlice = 0;\n\t\t\t\t\t\trtvDesc.Texture2D.PlaneSlice = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tm_device->CreateRenderTargetView(\n\t\t\t\t\t\t  NULL == m_msaaRt\n\t\t\t\t\t\t? m_backBufferColor[ii]\n\t\t\t\t\t\t: m_msaaRt\n\t\t\t\t\t\t, &rtvDesc\n\t\t\t\t\t\t, handle\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (BX_ENABLED(BX_PLATFORM_XBOXONE) )\n\t\t\t\t\t{\n\t\t\t\t\t\tID3D12Resource* resource = m_backBufferColor[ii];\n\n\t\t\t\t\t\tBX_ASSERT(DXGI_FORMAT_R8G8B8A8_UNORM == m_scd.format, "");\n\t\t\t\t\t\tconst uint32_t size = m_scd.width*m_scd.height*4;\n\n\t\t\t\t\t\tvoid* ptr;\n\t\t\t\t\t\tDX_CHECK(resource->Map(0, NULL, &ptr) );\n\t\t\t\t\t\tbx::memSet(ptr, 0, size);\n\t\t\t\t\t\tresource->Unmap(0, NULL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tD3D12_RESOURCE_DESC resourceDesc;\n\t\t\tresourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\n\t\t\tresourceDesc.Alignment = 1 < m_scd.sampleDesc.Count ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : 0;\n\t\t\tresourceDesc.Width     = bx::uint32_max(m_resolution.width,  1);\n\t\t\tresourceDesc.Height    = bx::uint32_max(m_resolution.height, 1);\n\t\t\tresourceDesc.DepthOrArraySize = 1;\n\t\t\tresourceDesc.MipLevels        = 1;\n\t\t\tresourceDesc.Format           = DXGI_FORMAT_D24_UNORM_S8_UINT;\n\t\t\tresourceDesc.SampleDesc       = m_scd.sampleDesc;\n\t\t\tresourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;\n\t\t\tresourceDesc.Flags  = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;\n\n\t\t\tD3D12_CLEAR_VALUE clearValue;\n\t\t\tclearValue.Format = resourceDesc.Format;\n\t\t\tclearValue.DepthStencil.Depth   = 1.0f;\n\t\t\tclearValue.DepthStencil.Stencil = 0;\n\n\t\t\tm_commandList = m_cmd.alloc();\n\n\t\t\tm_backBufferDepthStencil = createCommittedResource(m_device, HeapProperty::Default, &resourceDesc, &clearValue);\n\t\t\tm_device->CreateDepthStencilView(m_backBufferDepthStencil, NULL, getCPUHandleHeapStart(m_dsvDescriptorHeap));\n\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_backBufferDepthStencil\n\t\t\t\t, D3D12_RESOURCE_STATE_COMMON\n\t\t\t\t, D3D12_RESOURCE_STATE_DEPTH_WRITE\n\t\t\t\t);\n\n\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)\n\t\t\t{\n\t\t\t\tm_frameBuffers[ii].postReset();\n\t\t\t}\n\n\t\t\tif (NULL != m_msaaRt)\n\t\t\t{\n\t\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t\t, m_msaaRt\n\t\t\t\t\t, D3D12_RESOURCE_STATE_COMMON\n\t\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_SOURCE\n\t\t\t\t\t);\n\t\t\t}\n\n//\t\t\tcapturePostReset();\n\t\t}\n\n\t\tvoid invalidateCache()\n\t\t{\n\t\t\tm_pipelineStateCache.invalidate();\n\n\t\t\tm_samplerStateCache.invalidate();\n\t\t\tm_samplerAllocator.reset();\n\t\t}\n\n\t\tvoid updateMsaa(DXGI_FORMAT _format) const\n\t\t{\n\t\t\tfor (uint32_t ii = 1, last = 0; ii < BX_COUNTOF(s_msaa); ++ii)\n\t\t\t{\n\t\t\t\tuint32_t msaa = s_checkMsaa[ii];\n\n\t\t\t\tD3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS data;\n\t\t\t\tbx::memSet(&data, 0, sizeof(msaa) );\n\t\t\t\tdata.Format = _format;\n\t\t\t\tdata.SampleCount = msaa;\n\t\t\t\tdata.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;\n\t\t\t\tHRESULT hr = m_device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &data, sizeof(data) );\n\n\t\t\t\tif (SUCCEEDED(hr)\n\t\t\t\t&&  0 < data.NumQualityLevels)\n\t\t\t\t{\n\t\t\t\t\ts_msaa[ii].Count   = data.SampleCount;\n\t\t\t\t\ts_msaa[ii].Quality = data.NumQualityLevels-1;\n\t\t\t\t\tlast = ii;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ts_msaa[ii] = s_msaa[last];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tIUnknown* getDeviceForSwapChain() const\n\t\t{\n#\tif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t\treturn m_cmd.m_commandQueue;\n#\telse\n\t\t\treturn m_device;\n#\tendif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT\n\t\t}\n\n\t\tbool updateResolution(const Resolution& _resolution)\n\t\t{\n\t\t\tif (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) )\n\t\t\t{\n\t\t\t\tm_maxAnisotropy = D3D12_REQ_MAXANISOTROPY;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_maxAnisotropy = 1;\n\t\t\t}\n\n\t\t\tbool depthClamp = !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP);\n\n\t\t\tif (m_depthClamp != depthClamp)\n\t\t\t{\n\t\t\t\tm_depthClamp = depthClamp;\n\t\t\t\tm_pipelineStateCache.invalidate();\n\t\t\t}\n\n\t\t\tconst uint32_t maskFlags = ~(0\n\t\t\t\t| BGFX_RESET_MAXANISOTROPY\n\t\t\t\t| BGFX_RESET_DEPTH_CLAMP\n\t\t\t\t| BGFX_RESET_SUSPEND\n\t\t\t\t);\n\n\t\t\tif (m_resolution.width            !=  _resolution.width\n\t\t\t||  m_resolution.height           !=  _resolution.height\n\t\t\t||  m_resolution.format           !=  _resolution.format\n\t\t\t|| (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) )\n\t\t\t{\n\t\t\t\tuint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE);\n\n\t\t\t\tbool resize = true\n\t\t\t\t\t&& BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT)\n\t\t\t\t\t&& (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (_resolution.reset&BGFX_RESET_MSAA_MASK)\n\t\t\t\t\t;\n\n\t\t\t\tm_resolution = _resolution;\n\t\t\t\tm_resolution.reset = flags;\n\n\t\t\t\tm_textVideoMem.resize(false, _resolution.width, _resolution.height);\n\t\t\t\tm_textVideoMem.clear();\n\n\t\t\t\tm_scd.width  = _resolution.width;\n\t\t\t\tm_scd.height = _resolution.height;\n\t\t\t\tm_scd.format = s_textureFormat[_resolution.format].m_fmt;\n\n\t\t\t\tpreReset();\n\n\t\t\t\tDX_RELEASE(m_msaaRt, 0);\n\n\t\t\t\tif (NULL == m_swapChain)\n\t\t\t\t{\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (resize)\n\t\t\t\t\t{\n#if BX_PLATFORM_WINDOWS\n\t\t\t\t\t\tuint32_t nodeMask[] = { 1, 1, 1, 1 };\n\t\t\t\t\t\tBX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(nodeMask) );\n\t\t\t\t\t\tIUnknown* presentQueue[] ={ m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue };\n\t\t\t\t\t\tBX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(presentQueue) );\n\t\t\t\t\t\tDX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd, nodeMask, presentQueue) );\n#elif BX_PLATFORM_WINRT\n\t\t\t\t\t\tDX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd));\n\t\t\t\t\t\tm_backBufferColorIdx = m_scd.bufferCount-1;\n#endif // BX_PLATFORM_WINDOWS\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tupdateMsaa(m_scd.format);\n\t\t\t\t\t\tm_scd.sampleDesc = s_msaa[(m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT];\n\n\t\t\t\t\t\tDX_RELEASE(m_swapChain, 0);\n\n\t\t\t\t\t\tHRESULT hr;\n#if BX_PLATFORM_LINUX\n\t\t\t\t\t\thr = E_FAIL;\n#else\n\t\t\t\t\t\thr = m_dxgi.createSwapChain(\n\t\t\t\t\t\t\t  getDeviceForSwapChain()\n\t\t\t\t\t\t\t, m_scd\n\t\t\t\t\t\t\t, &m_swapChain\n\t\t\t\t\t\t\t);\n#endif // BX_PLATFORM_LINUX\n\t\t\t\t\t\tBGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain.");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (1 < m_scd.sampleDesc.Count)\n\t\t\t\t\t{\n\t\t\t\t\t\tD3D12_RESOURCE_DESC resourceDesc;\n\t\t\t\t\t\tresourceDesc.Dimension  = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\n\t\t\t\t\t\tresourceDesc.Alignment  = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;\n\t\t\t\t\t\tresourceDesc.Width      = m_scd.width;\n\t\t\t\t\t\tresourceDesc.Height     = m_scd.height;\n\t\t\t\t\t\tresourceDesc.MipLevels  = 1;\n\t\t\t\t\t\tresourceDesc.Format     = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? s_textureFormat[m_resolution.format].m_fmtSrgb\n\t\t\t\t\t\t\t\t\t\t\t\t\t: s_textureFormat[m_resolution.format].m_fmt;\n\t\t\t\t\t\tresourceDesc.SampleDesc = m_scd.sampleDesc;\n\t\t\t\t\t\tresourceDesc.Layout     = D3D12_TEXTURE_LAYOUT_UNKNOWN;\n\t\t\t\t\t\tresourceDesc.Flags      = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;\n\t\t\t\t\t\tresourceDesc.DepthOrArraySize = 1;\n\n\t\t\t\t\t\tD3D12_CLEAR_VALUE clearValue;\n\t\t\t\t\t\tclearValue.Format   = resourceDesc.Format;\n\t\t\t\t\t\tclearValue.Color[0] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[1] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[2] = 0.0f;\n\t\t\t\t\t\tclearValue.Color[3] = 0.0f;\n\n\t\t\t\t\t\tm_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true);\n\t\t\t\t\t\tsetDebugObjectName(m_msaaRt, "MSAA Backbuffer");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpostReset();\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tvoid setShaderUniform(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)\n\t\t{\n\t\t\tif (_flags&kUniformFragmentBit)\n\t\t\t{\n\t\t\t\tbx::memCopy(&m_fsScratch[_regIndex], _val, _numRegs*16);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tbx::memCopy(&m_vsScratch[_regIndex], _val, _numRegs*16);\n\t\t\t}\n\t\t}\n\n\t\tvoid setShaderUniform4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)\n\t\t{\n\t\t\tsetShaderUniform(_flags, _regIndex, _val, _numRegs);\n\t\t}\n\n\t\tvoid setShaderUniform4x4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)\n\t\t{\n\t\t\tsetShaderUniform(_flags, _regIndex, _val, _numRegs);\n\t\t}\n\n\t\tvoid commitShaderConstants(ProgramHandle _program, D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress)\n\t\t{\n\t\t\tconst ProgramD3D12& program = m_program[_program.idx];\n\t\t\tuint32_t total = bx::strideAlign(0\n\t\t\t\t+ program.m_vsh->m_size\n\t\t\t\t+ (NULL != program.m_fsh ? program.m_fsh->m_size : 0)\n\t\t\t\t, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT\n\t\t\t\t);\n\t\t\tuint8_t* data = (uint8_t*)m_scratchBuffer[m_backBufferColorIdx].allocCbv(_gpuAddress, total);\n\n\t\t\t{\n\t\t\t\tuint32_t size = program.m_vsh->m_size;\n\t\t\t\tbx::memCopy(data, m_vsScratch, size);\n\t\t\t\tdata += size;\n\t\t\t}\n\n\t\t\tif (NULL != program.m_fsh)\n\t\t\t{\n\t\t\t\tbx::memCopy(data, m_fsScratch, program.m_fsh->m_size);\n\t\t\t}\n\t\t}\n\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh)\n\t\t{\n\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[_fbh.idx];\n\n\t\t\tif (NULL != frameBuffer.m_swapChain)\n\t\t\t{\n#if BX_PLATFORM_WINDOWS\n\t\t\t\tuint8_t idx = uint8_t(frameBuffer.m_swapChain->GetCurrentBackBufferIndex() );\n\t\t\t\tframeBuffer.setState(m_commandList, idx, D3D12_RESOURCE_STATE_RENDER_TARGET);\n\t\t\t\treturn getRtv(_fbh, idx);\n#endif // BX_PLATFORM_WINDOWS\n\t\t\t}\n\n\t\t\treturn getRtv(_fbh, 0);\n\t\t}\n\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh, uint8_t _attachment)\n\t\t{\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = getCPUHandleHeapStart(m_rtvDescriptorHeap);\n\t\t\tuint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE result =\n\t\t\t{\n\t\t\t\trtvDescriptor.ptr + (BX_COUNTOF(m_backBufferColor) + _fbh.idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + _attachment) * rtvDescriptorSize\n\t\t\t};\n\t\t\treturn result;\n\t\t}\n\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE getDsv(FrameBufferHandle _fbh) const\n\t\t{\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(m_dsvDescriptorHeap);\n\t\t\tuint32_t dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE result = { dsvDescriptor.ptr + (1 + _fbh.idx) * dsvDescriptorSize };\n\t\t\treturn result;\n\t\t}\n\n\t\tvoid setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true)\n\t\t{\n\t\t\tif (isValid(m_fbh)\n\t\t\t&&  m_fbh.idx != _fbh.idx)\n\t\t\t{\n\t\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx];\n\n\t\t\t\tif (m_rtMsaa) frameBuffer.resolve();\n\n\t\t\t\tif (NULL == frameBuffer.m_swapChain)\n\t\t\t\t{\n\t\t\t\t\tfor (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tTextureD3D12& texture = m_textures[frameBuffer.m_texture[ii].idx];\n\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isValid(frameBuffer.m_depth) )\n\t\t\t\t\t{\n\t\t\t\t\t\tTextureD3D12& texture = m_textures[frameBuffer.m_depth.idx];\n\t\t\t\t\t\tconst bool writeOnly  = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY);\n\t\t\t\t\t\tif (!writeOnly)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_READ);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!isValid(_fbh) )\n\t\t\t{\n\t\t\t\tif (NULL != m_swapChain)\n\t\t\t\t{\n\t\t\t\t\tm_rtvHandle = getCPUHandleHeapStart(m_rtvDescriptorHeap);\n\t\t\t\t\tuint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\n\t\t\t\t\tm_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize;\n\t\t\t\t\tm_dsvHandle = getCPUHandleHeapStart(m_dsvDescriptorHeap);\n\n\t\t\t\t\tm_currentColor        = &m_rtvHandle;\n\t\t\t\t\tm_currentDepthStencil = &m_dsvHandle;\n\t\t\t\t\tm_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[_fbh.idx];\n\n\t\t\t\tif (0 < frameBuffer.m_num)\n\t\t\t\t{\n\t\t\t\t\tm_rtvHandle = getRtv(_fbh);\n\t\t\t\t\tm_currentColor = &m_rtvHandle;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_currentColor = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (isValid(frameBuffer.m_depth) )\n\t\t\t\t{\n\t\t\t\t\tm_dsvHandle = getDsv(_fbh);\n\t\t\t\t\tm_currentDepthStencil = &m_dsvHandle;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_currentDepthStencil = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (NULL != frameBuffer.m_swapChain)\n\t\t\t\t{\n\t\t\t\t\tframeBuffer.m_needPresent = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tTextureD3D12& texture = m_textures[frameBuffer.m_texture[ii].idx];\n\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_RENDER_TARGET);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isValid(frameBuffer.m_depth) )\n\t\t\t\t\t{\n\t\t\t\t\t\tTextureD3D12& texture = m_textures[frameBuffer.m_depth.idx];\n\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tm_commandList->OMSetRenderTargets(\n\t\t\t\t\t  frameBuffer.m_num\n\t\t\t\t\t, m_currentColor\n\t\t\t\t\t, true\n\t\t\t\t\t, m_currentDepthStencil\n\t\t\t\t\t);\n\t\t\t}\n\t\t\t{\n\t\t\tdefault:\n\t\t\tcase D3D12_UAV_DIMENSION_TEXTURE2D:\n\t\t\t\tuavd->Texture2D.MipSlice = _mip;\n\t\t\t\tbreak;\n\n\t\t\tcase D3D12_UAV_DIMENSION_TEXTURE3D:\n\t\t\t_desc.IndependentBlendEnable = !!(BGFX_STATE_BLEND_INDEPENDENT & _state);\n\n\t\t\tD3D12_RENDER_TARGET_BLEND_DESC* drt = &_desc.RenderTarget[0];\n\t\t\tdrt->BlendEnable   = !!(BGFX_STATE_BLEND_MASK & _state);\n\t\t\tdrt->LogicOpEnable = false;\n\n\t\t\t{\n\t\t\t\tconst uint32_t blend    = uint32_t( (_state & BGFX_STATE_BLEND_MASK         ) >> BGFX_STATE_BLEND_SHIFT);\n\t\t\t\tconst uint32_t equation = uint32_t( (_state & BGFX_STATE_BLEND_EQUATION_MASK) >> BGFX_STATE_BLEND_EQUATION_SHIFT);\n\n\t\t\t\tconst uint32_t srcRGB = (blend      ) & 0xf;\n\t\t\t\tconst uint32_t dstRGB = (blend >>  4) & 0xf;\n\t\t\t\tconst uint32_t srcA   = (blend >>  8) & 0xf;\n\t\t\t\tconst uint32_t dstA   = (blend >> 12) & 0xf;\n\n\t\t\t\tconst uint32_t equRGB = (equation     ) & 0x7;\n\t\t\t\tconst uint32_t equA   = (equation >> 3) & 0x7;\n\n\t\t\t\tdrt->SrcBlend       = s_blendFactor[srcRGB][0];\n\t\t\t\tdrt->DestBlend      = s_blendFactor[dstRGB][0];\n\t\t\t\tdrt->BlendOp        = s_blendEquation[equRGB];\n\n\t\t\t\tdrt->SrcBlendAlpha  = s_blendFactor[srcA][1];\n\t\t\t\tdrt->DestBlendAlpha = s_blendFactor[dstA][1];\n\t\t\t\tdrt->BlendOpAlpha   = s_blendEquation[equA];\n\t\t\t}\n\n\t\t\tuint8_t writeMask = 0;\n\t\t\twriteMask |= (_state & BGFX_STATE_WRITE_R) ? D3D12_COLOR_WRITE_ENABLE_RED   : 0;\n\t\t\twriteMask |= (_state & BGFX_STATE_WRITE_G) ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0;\n\t\t\twriteMask |= (_state & BGFX_STATE_WRITE_B) ? D3D12_COLOR_WRITE_ENABLE_BLUE  : 0;\n\t\t\twriteMask |= (_state & BGFX_STATE_WRITE_A) ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0;\n\n\t\t\tdrt->LogicOp = D3D12_LOGIC_OP_CLEAR;\n\t\t\tdrt->RenderTargetWriteMask = writeMask;\n\n\t\t\tif (_desc.IndependentBlendEnable)\n\t\t\t{\n\t\t\t\tfor (uint32_t ii = 1, rgba = _rgba; ii < BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS; ++ii, rgba >>= 11)\n\t\t\t\t{\n\t\t\t\t\tdrt = &_desc.RenderTarget[ii];\n\t\t\t\t\tdrt->BlendEnable = 0 != (rgba & 0x7ff);\n\t\t\t\t\tdrt->LogicOpEnable = false;\n\n\t\t\t\t\tconst uint32_t src      = (rgba     ) & 0xf;\n\t\t\t\t\tconst uint32_t dst      = (rgba >> 4) & 0xf;\n\t\t\t\t\tconst uint32_t equation = (rgba >> 8) & 0x7;\n\n\t\t\t\t\tdrt->SrcBlend       = s_blendFactor[src][0];\n\t\t\t\t\tdrt->DestBlend      = s_blendFactor[dst][0];\n\t\t\t\t\tdrt->BlendOp        = s_blendEquation[equation];\n\n\t\t\t\t\tdrt->SrcBlendAlpha  = s_blendFactor[src][1];\n\t\t\t\t\tdrt->DestBlendAlpha = s_blendFactor[dst][1];\n\t\t\t\t\tdrt->BlendOpAlpha   = s_blendEquation[equation];\n\n\t\t\t\t\tdrt->LogicOp = D3D12_LOGIC_OP_CLEAR;\n\t\t\t\t\tdrt->RenderTargetWriteMask = writeMask;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (uint32_t ii = 1; ii < BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS; ++ii)\n\t\t\t\t{\n\t\t\t\t\tbx::memCopy(&_desc.RenderTarget[ii], drt, sizeof(D3D12_RENDER_TARGET_BLEND_DESC) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid setRasterizerState(D3D12_RASTERIZER_DESC& _desc, uint64_t _state, bool _wireframe = false)\n\t\t{\n\t\t\tconst uint32_t cull = (_state&BGFX_STATE_CULL_MASK) >> BGFX_STATE_CULL_SHIFT;\n\n\t\t\t_desc.FillMode = _wireframe\n\t\t\t\t? D3D12_FILL_MODE_WIREFRAME\n\t\t\t\t: D3D12_FILL_MODE_SOLID\n\t\t\t\t;\n\t\t\t_desc.CullMode              = s_cullMode[cull];\n\t\t\t_desc.FrontCounterClockwise = !!(_state&BGFX_STATE_FRONT_CCW);;\n\t\t\t_desc.DepthBias             = 0;\n\t\t\t_desc.DepthBiasClamp        = 0.0f;\n\t\t\t_desc.SlopeScaledDepthBias  = 0.0f;\n\t\t\t_desc.DepthClipEnable       = !m_depthClamp;\n\t\t\t_desc.MultisampleEnable     = !!(_state&BGFX_STATE_MSAA);\n\t\t\t_desc.AntialiasedLineEnable = !!(_state&BGFX_STATE_LINEAA);\n\t\t\t_desc.ForcedSampleCount     = 0;\n\t\t\t_desc.ConservativeRaster    = !!(_state&BGFX_STATE_CONSERVATIVE_RASTER)\n\t\t\t\t? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON\n\t\t\t\t: D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF\n\t\t\t\t;\n\t\t}\n\n\t\tvoid setDepthStencilState(D3D12_DEPTH_STENCIL_DESC& _desc, uint64_t _state, uint64_t _stencil = 0)\n\t\t{\n\t\t\tconst uint32_t fstencil = unpackStencil(0, _stencil);\n\n\t\t\tbx::memSet(&_desc, 0, sizeof(_desc) );\n\t\t\tuint32_t func = (_state&BGFX_STATE_DEPTH_TEST_MASK)>>BGFX_STATE_DEPTH_TEST_SHIFT;\n\t\t\t_desc.DepthEnable = 0 != func;\n\t\t\t_desc.DepthWriteMask = !!(BGFX_STATE_WRITE_Z & _state)\n\t\t\t\t? D3D12_DEPTH_WRITE_MASK_ALL\n\t\t\t\t: D3D12_DEPTH_WRITE_MASK_ZERO\n\t\t\t\t;\n\t\t\t_desc.DepthFunc = s_cmpFunc[func];\n\n\t\t\tuint32_t bstencil = unpackStencil(1, _stencil);\n\t\t\tuint32_t frontAndBack = bstencil != BGFX_STENCIL_NONE && bstencil != fstencil;\n\t\t\tbstencil = frontAndBack ? bstencil : fstencil;\n\n\t\t\t_desc.StencilEnable    = 0 != _stencil;\n\t\t\t_desc.StencilReadMask  = (fstencil & BGFX_STENCIL_FUNC_RMASK_MASK) >> BGFX_STENCIL_FUNC_RMASK_SHIFT;\n\t\t\t_desc.StencilWriteMask = 0xff;\n\n\t\t\t_desc.FrontFace.StencilFailOp      = s_stencilOp[(fstencil & BGFX_STENCIL_OP_FAIL_S_MASK) >> BGFX_STENCIL_OP_FAIL_S_SHIFT];\n\t\t\t_desc.FrontFace.StencilDepthFailOp = s_stencilOp[(fstencil & BGFX_STENCIL_OP_FAIL_Z_MASK) >> BGFX_STENCIL_OP_FAIL_Z_SHIFT];\n\t\t\t_desc.FrontFace.StencilPassOp      = s_stencilOp[(fstencil & BGFX_STENCIL_OP_PASS_Z_MASK) >> BGFX_STENCIL_OP_PASS_Z_SHIFT];\n\t\t\t_desc.FrontFace.StencilFunc        = s_cmpFunc[(fstencil & BGFX_STENCIL_TEST_MASK) >> BGFX_STENCIL_TEST_SHIFT];\n\n\t\t\t_desc.BackFace.StencilFailOp       = s_stencilOp[(bstencil & BGFX_STENCIL_OP_FAIL_S_MASK) >> BGFX_STENCIL_OP_FAIL_S_SHIFT];\n\t\t\t_desc.BackFace.StencilDepthFailOp  = s_stencilOp[(bstencil & BGFX_STENCIL_OP_FAIL_Z_MASK) >> BGFX_STENCIL_OP_FAIL_Z_SHIFT];\n\t\t\t_desc.BackFace.StencilPassOp       = s_stencilOp[(bstencil & BGFX_STENCIL_OP_PASS_Z_MASK) >> BGFX_STENCIL_OP_PASS_Z_SHIFT];\n\t\t\t_desc.BackFace.StencilFunc         = s_cmpFunc[(bstencil&BGFX_STENCIL_TEST_MASK) >> BGFX_STENCIL_TEST_SHIFT];\n\t\t}\n\n\t\tuint32_t setInputLayout(D3D12_INPUT_ELEMENT_DESC* _vertexElements, uint8_t _numStreams, const VertexLayout** _layouts, const ProgramD3D12& _program, uint16_t _numInstanceData)\n\t\t{\n\t\t\tuint16_t attrMask[Attrib::Count];\n\t\t\tbx::memCopy(attrMask, _program.m_vsh->m_attrMask, sizeof(attrMask));\n\n\t\t\tD3D12_INPUT_ELEMENT_DESC* elem = _vertexElements;\n\n\t\t\tfor (uint8_t stream = 0; stream < _numStreams; ++stream)\n\t\t\t{\n\t\t\t\tVertexLayout layout;\n\t\t\t\tbx::memCopy(&layout, _layouts[stream], sizeof(VertexLayout));\n\n\t\t\t\tconst bool last = stream == _numStreams-1;\n\n\t\t\t\tfor (uint32_t ii = 0; ii < Attrib::Count; ++ii)\n\t\t\t\t{\n\t\t\t\t\tuint16_t mask = attrMask[ii];\n\t\t\t\t\tuint16_t attr = (layout.m_attributes[ii] & mask);\n\t\t\t\t\tif (0          == attr\n\t\t\t\t\t||  UINT16_MAX == attr)\n\t\t\t\t\t{\n\t\t\t\t\t\tlayout.m_attributes[ii] = last ? ~attr : UINT16_MAX;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tattrMask[ii] = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = fillVertexLayout(stream, elem, layout);\n\t\t\t}\n\n\t\t\tuint32_t num = uint32_t(elem-_vertexElements);\n\n\t\t\tconst D3D12_INPUT_ELEMENT_DESC inst = { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };\n\n\t\t\tfor (uint32_t ii = 0; ii < _numInstanceData; ++ii)\n\t\t\t{\n\t\t\t\tuint32_t index = 7 - ii; // TEXCOORD7 = i_data0, TEXCOORD6 = i_data1, etc.\n\n\t\t\t\tuint32_t jj;\n\t\t\t\tD3D12_INPUT_ELEMENT_DESC* curr = _vertexElements;\n\t\t\t\tfor (jj = 0; jj < num; ++jj)\n\t\t\t\t{\n\t\t\t\t\tcurr = &_vertexElements[jj];\n\t\t\t\t\tif (0 == bx::strCmp(curr->SemanticName, "TEXCOORD")\n\t\t\t\t\t&&  curr->SemanticIndex == index)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (jj == num)\n\t\t\t\t{\n\t\t\t\t\tcurr = elem;\n\t\t\t\t\t++elem;\n\t\t\t\t}\n\n\t\t\t\tbx::memCopy(curr, &inst, sizeof(D3D12_INPUT_ELEMENT_DESC) );\n\t\t\t\tcurr->InputSlot = _numStreams;\n\t\t\t\tcurr->SemanticIndex = index;\n\t\t\t\tcurr->AlignedByteOffset = ii*16;\n\t\t\t}\n\n\t\t\treturn uint32_t(elem-_vertexElements);\n\t\t}\n\n\t\tuint32_t setInputLayout(D3D12_INPUT_ELEMENT_DESC* _vertexElements, const VertexLayout& _layout, const ProgramD3D12& _program, uint16_t _numInstanceData)\n\t\t{\n\t\t\tconst VertexLayout* layouts[1] = { &_layout };\n\t\t\treturn setInputLayout(_vertexElements, BX_COUNTOF(layouts), layouts, _program, _numInstanceData);\n\t\t}\n\n\t\tstatic void patchCb0(DxbcInstruction& _instruction, void* _userData)\n\t\t{\n\t\t\tunion { void* ptr; uint32_t offset; } cast = { _userData };\n\n\t\t\tfor (uint32_t ii = 0; ii < _instruction.numOperands; ++ii)\n\t\t\t{\n\t\t\t\tDxbcOperand& operand = _instruction.operand[ii];\n\t\t\t\tif (DxbcOperandType::ConstantBuffer == operand.type)\n\t\t\t\t{\n\t\t\t\t\tif (DxbcOperandAddrMode::Imm32 == operand.addrMode[0]\n\t\t\t\t\t&&  0 == operand.regIndex[0])\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (uint32_t jj = 1; jj < operand.numAddrModes; ++jj)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (DxbcOperandAddrMode::Imm32    == operand.addrMode[jj]\n\t\t\t\t\t\t\t||  DxbcOperandAddrMode::RegImm32 == operand.addrMode[jj])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\toperand.regIndex[jj] += cast.offset;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (0 != cast.offset)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\toperand.subOperand[jj].regIndex = operand.regIndex[jj];\n\t\t\t\t\t\t\t\toperand.addrMode[jj] = DxbcOperandAddrMode::RegImm32;\n\t\t\t\t\t\t\t\toperand.regIndex[jj] = cast.offset;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tID3D12PipelineState* getPipelineState(ProgramHandle _program)\n\t\t{\n\t\t\tProgramD3D12& program = m_program[_program.idx];\n\n\t\t\tconst uint32_t hash = program.m_vsh->m_hash;\n\n\t\t\tID3D12PipelineState* pso = m_pipelineStateCache.find(hash);\n\n\t\t\tif (BX_LIKELY(NULL != pso) )\n\t\t\t{\n\t\t\t\treturn pso;\n\t\t\t}\n\n\t\t\tD3D12_COMPUTE_PIPELINE_STATE_DESC desc;\n\t\t\tbx::memSet(&desc, 0, sizeof(desc) );\n\n\t\t\tdesc.pRootSignature     = m_rootSignature;\n\t\t\tdesc.CS.pShaderBytecode = program.m_vsh->m_code->data;\n\t\t\tdesc.CS.BytecodeLength  = program.m_vsh->m_code->size;\n\t\t\tdesc.NodeMask           = 1;\n\t\t\tdesc.Flags              = D3D12_PIPELINE_STATE_FLAG_NONE;\n\n\t\t\tuint32_t length = g_callback->cacheReadSize(hash);\n\t\t\tconst bool cached = length > 0;\n\n\t\t\tvoid* cachedData = NULL;\n\n\t\t\tif (cached)\n\t\t\t{\n\t\t\t\tcachedData = BX_ALLOC(g_allocator, length);\n\t\t\t\tif (g_callback->cacheRead(hash, cachedData, length) )\n\t\t\t\t{\n\t\t\t\t\tBX_TRACE("Loading cached compute PSO (size %d).", length);\n\t\t\t\t\tbx::MemoryReader reader(cachedData, length);\n\n\t\t\t\t\tdesc.CachedPSO.pCachedBlob           = reader.getDataPtr();\n\t\t\t\t\tdesc.CachedPSO.CachedBlobSizeInBytes = (size_t)reader.remaining();\n\n\t\t\t\t\tHRESULT hr = m_device->CreateComputePipelineState(&desc\n\t\t\t\t\t\t, IID_ID3D12PipelineState\n\t\t\t\t\t\t, (void**)&pso\n\t\t\t\t\t\t);\n\t\t\t\t\tif (FAILED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_TRACE("Failed to load cached compute PSO (HRESULT 0x%08x).", hr);\n\t\t\t\t\t\tbx::memSet(&desc.CachedPSO, 0, sizeof(desc.CachedPSO) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (NULL == pso)\n\t\t\t{\n\t\t\t\tDX_CHECK(m_device->CreateComputePipelineState(&desc\n\t\t\t\t\t, IID_ID3D12PipelineState\n\t\t\t\t\t, (void**)&pso\n\t\t\t\t\t) );\n\t\t\t}\n\n\t\t\tm_pipelineStateCache.add(hash, pso);\n\n\t\t\tID3DBlob* blob;\n\t\t\tHRESULT hr = pso->GetCachedBlob(&blob);\n\t\t\tif (SUCCEEDED(hr) )\n\t\t\t{\n\t\t\t\tvoid* data = blob->GetBufferPointer();\n\t\t\t\tlength = (uint32_t)blob->GetBufferSize();\n\n\t\t\t\tg_callback->cacheWrite(hash, data, length);\n\n\t\t\t\tDX_RELEASE(blob, 0);\n\t\t\t}\n\n\t\t\tif (NULL != cachedData)\n\t\t\t{\n\t\t\t\tBX_FREE(g_allocator, cachedData);\n\t\t\t}\n\n\t\t\treturn pso;\n\t\t}\n\n\t\tID3D12PipelineState* getPipelineState(\n\t\t\t  uint64_t _state\n\t\t\t, uint64_t _stencil\n\t\t\t, uint8_t _numStreams\n\t\t\t, const VertexLayout** _layouts\n\t\t\t, ProgramHandle _program\n\t\t\t, uint8_t _numInstanceData\n\t\t\t)\n\t\t{\n\t\t\tProgramD3D12& program = m_program[_program.idx];\n\n\t\t\t_state &= 0\n\t\t\t\t| BGFX_STATE_WRITE_RGB\n\t\t\t\t| BGFX_STATE_WRITE_A\n\t\t\t\t| BGFX_STATE_WRITE_Z\n\t\t\t\t| BGFX_STATE_DEPTH_TEST_MASK\n\t\t\t\t| BGFX_STATE_BLEND_MASK\n\t\t\t\t| BGFX_STATE_BLEND_EQUATION_MASK\n\t\t\t\t| BGFX_STATE_BLEND_INDEPENDENT\n\t\t\t\t| BGFX_STATE_BLEND_ALPHA_TO_COVERAGE\n\t\t\t\t| BGFX_STATE_CULL_MASK\n\t\t\t\t| BGFX_STATE_FRONT_CCW\n\t\t\t\t| BGFX_STATE_MSAA\n\t\t\t\t| BGFX_STATE_LINEAA\n\t\t\t\t| BGFX_STATE_CONSERVATIVE_RASTER\n\t\t\t\t| BGFX_STATE_PT_MASK\n\t\t\t\t;\n\n\t\t\t_stencil &= packStencil(~BGFX_STENCIL_FUNC_REF_MASK, ~BGFX_STENCIL_FUNC_REF_MASK);\n\n\t\t\tVertexLayout layout;\n\t\t\tif (0 < _numStreams)\n\t\t\t{\n\t\t\t\tbx::memCopy(&layout, _layouts[0], sizeof(VertexLayout) );\n\t\t\t\tconst uint16_t* attrMask = program.m_vsh->m_attrMask;\n\n\t\t\t\tfor (uint32_t ii = 0; ii < Attrib::Count; ++ii)\n\t\t\t\t{\n\t\t\t\t\tuint16_t mask = attrMask[ii];\n\t\t\t\t\tuint16_t attr = (layout.m_attributes[ii] & mask);\n\t\t\t\t\tlayout.m_attributes[ii] = attr == 0 ? UINT16_MAX : attr == UINT16_MAX ? 0 : attr;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbx::HashMurmur2A murmur;\n\t\t\tmurmur.begin();\n\t\t\tmurmur.add(_state);\n\t\t\tmurmur.add(_stencil);\n\t\t\tmurmur.add(program.m_vsh->m_hash);\n\t\t\tmurmur.add(program.m_vsh->m_attrMask, sizeof(program.m_vsh->m_attrMask) );\n\n\t\t\tif (NULL != program.m_fsh)\n\t\t\t{\n\t\t\t\tmurmur.add(program.m_fsh->m_hash);\n\t\t\t}\n\n\t\t\tfor (uint32_t ii = 0; ii < _numStreams; ++ii)\n\t\t\t{\n\t\t\t\tmurmur.add(_layouts[ii]->m_hash);\n\t\t\t}\n\n\t\t\tmurmur.add(layout.m_attributes, sizeof(layout.m_attributes) );\n\t\t\tmurmur.add(m_fbh.idx);\n\t\t\tmurmur.add(_numInstanceData);\n\t\t\tconst uint32_t hash = murmur.end();\n\n\t\t\tID3D12PipelineState* pso = m_pipelineStateCache.find(hash);\n\n\t\t\tif (NULL != pso)\n\t\t\t{\n\t\t\t\treturn pso;\n\t\t\t}\n\n\t\t\tD3D12_GRAPHICS_PIPELINE_STATE_DESC desc;\n\t\t\tbx::memSet(&desc, 0, sizeof(desc) );\n\n\t\t\tdesc.pRootSignature = m_rootSignature;\n\n\t\t\tdesc.VS.pShaderBytecode = program.m_vsh->m_code->data;\n\t\t\tdesc.VS.BytecodeLength  = program.m_vsh->m_code->size;\n\n\t\t\tconst Memory* temp = NULL;\n\n\t\t\tif (NULL != program.m_fsh)\n\t\t\t{\n \t\t\t\tbx::MemoryReader rd(program.m_fsh->m_code->data, program.m_fsh->m_code->size);\n\n\t\t\t\tDxbcContext dxbc;\n\t\t\t\tbx::Error err;\n\t\t\t\tread(&rd, dxbc, &err);\n\n\t\t\t\tbool patchShader = !dxbc.shader.aon9;\n\t\t\t\tif (BX_ENABLED(BGFX_CONFIG_DEBUG)\n\t\t\t\t&&  patchShader)\n\t\t\t\t{\n\t\t\t\t\tunion { uint32_t offset; void* ptr; } cast = { 0 };\n\t\t\t\t\tfilter(dxbc.shader, dxbc.shader, patchCb0, cast.ptr);\n\n\t\t\t\t\ttemp = alloc(uint32_t(dxbc.header.size));\n\t\t\t\t\tbx::StaticMemoryBlockWriter wr(temp->data, temp->size);\n\n\t\t\t\t\tint32_t size = write(&wr, dxbc, &err);\n\t\t\t\t\tdxbcHash(temp->data + 20, size - 20, temp->data + 4);\n\n\t\t\t\t\tpatchShader = 0 == bx::memCmp(program.m_fsh->m_code->data, temp->data, 16);\n\t\t\t\t\tBX_ASSERT(patchShader, "DXBC fragment shader patching error (ShaderHandle: %d).", program.m_fsh - m_shaders);\n\n\t\t\t\t\tif (!patchShader)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (uint32_t ii = 20; ii < temp->size; ii += 16)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (0 != bx::memCmp(&program.m_fsh->m_code->data[ii], &temp->data[ii], 16) )\n\t\t\t\t\t\t\t{\n\t// \t\t\t\t\t\t\tbx::debugPrintfData(&program.m_fsh->m_code->data[ii], temp->size-ii, "");\n\t// \t\t\t\t\t\t\tbx::debugPrintfData(&temp->data[ii], temp->size-ii, "");\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdesc.PS.pShaderBytecode = program.m_fsh->m_code->data;\n\t\t\t\t\t\tdesc.PS.BytecodeLength  = program.m_fsh->m_code->size;\n\t\t\t\t\t}\n\n\t\t\t\t\trelease(temp);\n\t\t\t\t\ttemp = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (patchShader)\n\t\t\t\t{\n\t\t\t\t\tunion { uint32_t offset; void* ptr; } cast =\n\t\t\t\t\t{\n\t\t\t\t\t\tuint32_t(program.m_vsh->m_size)/16\n\t\t\t\t\t};\n\t\t\t\t\tfilter(dxbc.shader, dxbc.shader, patchCb0, cast.ptr);\n\n\t\t\t\t\ttemp = alloc(uint32_t(dxbc.header.size));\n\t\t\t\t\tbx::StaticMemoryBlockWriter wr(temp->data, temp->size);\n\n\t\t\t\t\tint32_t size = write(&wr, dxbc, &err);\n\t\t\t\t\tdxbcHash(temp->data + 20, size - 20, temp->data + 4);\n\n\t\t\t\t\tdesc.PS.pShaderBytecode = temp->data;\n\t\t\t\t\tdesc.PS.BytecodeLength  = size;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdesc.PS.pShaderBytecode = program.m_fsh->m_code->data;\n\t\t\t\t\tdesc.PS.BytecodeLength  = program.m_fsh->m_code->size;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdesc.PS.pShaderBytecode = NULL;\n\t\t\t\tdesc.PS.BytecodeLength  = 0;\n\t\t\t}\n\n\t\t\tdesc.DS.pShaderBytecode = NULL;\n\t\t\tdesc.DS.BytecodeLength  = 0;\n\n\t\t\tdesc.HS.pShaderBytecode = NULL;\n\t\t\tdesc.HS.BytecodeLength  = 0;\n\n\t\t\tdesc.GS.pShaderBytecode = NULL;\n\t\t\tdesc.GS.BytecodeLength  = 0;\n\n\t\t\tdesc.StreamOutput.pSODeclaration   = NULL;\n\t\t\tdesc.StreamOutput.NumEntries       = 0;\n\t\t\tdesc.StreamOutput.pBufferStrides   = NULL;\n\t\t\tdesc.StreamOutput.NumStrides       = 0;\n\t\t\tdesc.StreamOutput.RasterizedStream = 0;\n\n\t\t\tsetBlendState(desc.BlendState, _state);\n\t\t\tdesc.SampleMask = UINT32_MAX;\n\t\t\tsetRasterizerState(desc.RasterizerState, _state);\n\t\t\tsetDepthStencilState(desc.DepthStencilState, _state, _stencil);\n\n\t\t\tD3D12_INPUT_ELEMENT_DESC vertexElements[Attrib::Count + 1 + BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT];\n\t\t\tdesc.InputLayout.NumElements = setInputLayout(vertexElements, _numStreams, _layouts, program, _numInstanceData);\n\t\t\tdesc.InputLayout.pInputElementDescs = 0 == desc.InputLayout.NumElements\n\t\t\t\t? NULL\n\t\t\t\t: vertexElements\n\t\t\t\t;\n\n\t\t\tuint8_t primIndex = uint8_t( (_state&BGFX_STATE_PT_MASK) >> BGFX_STATE_PT_SHIFT);\n\t\t\tdesc.PrimitiveTopologyType = s_primInfo[primIndex].m_topologyType;\n\n\t\t\tif (isValid(m_fbh) )\n\t\t\t{\n\t\t\t\tconst FrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx];\n\t\t\t\tif (NULL == frameBuffer.m_swapChain)\n\t\t\t\t{\n\t\t\t\t\tdesc.NumRenderTargets = frameBuffer.m_num;\n\n\t\t\t\t\tfor (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tdesc.RTVFormats[ii] = m_textures[frameBuffer.m_texture[ii].idx].m_srvd.Format;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isValid(frameBuffer.m_depth) )\n\t\t\t\t\t{\n\t\t\t\t\t\tdesc.DSVFormat = s_textureFormat[m_textures[frameBuffer.m_depth.idx].m_textureFormat].m_fmtDsv;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdesc.DSVFormat = DXGI_FORMAT_UNKNOWN;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdesc.NumRenderTargets = 1;\n\t\t\t\t\tdesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t\t\tdesc.DSVFormat     = DXGI_FORMAT_UNKNOWN;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdesc.NumRenderTargets = 1;\n\t\t\t\tdesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t\tdesc.DSVFormat     = DXGI_FORMAT_D24_UNORM_S8_UINT;\n\t\t\t}\n\n\t\t\tdesc.SampleDesc = m_scd.sampleDesc;\n\n\t\t\tuint32_t length = g_callback->cacheReadSize(hash);\n\t\t\tconst bool cached = length > 0;\n\n\t\t\tvoid* cachedData = NULL;\n\n\t\t\tif (cached)\n\t\t\t{\n\t\t\t\tcachedData = BX_ALLOC(g_allocator, length);\n\t\t\t\tif (g_callback->cacheRead(hash, cachedData, length) )\n\t\t\t\t{\n\t\t\t\t\tBX_TRACE("Loading cached graphics PSO (size %d).", length);\n\t\t\t\t\tbx::MemoryReader reader(cachedData, length);\n\n\t\t\t\t\tdesc.CachedPSO.pCachedBlob           = reader.getDataPtr();\n\t\t\t\t\tdesc.CachedPSO.CachedBlobSizeInBytes = (size_t)reader.remaining();\n\n\t\t\t\t\tHRESULT hr = m_device->CreateGraphicsPipelineState(&desc\n\t\t\t\t\t\t\t\t\t, IID_ID3D12PipelineState\n\t\t\t\t\t\t\t\t\t, (void**)&pso\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\tif (FAILED(hr) )\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_TRACE("Failed to load cached graphics PSO (HRESULT 0x%08x).", hr);\n\t\t\t\t\t\tbx::memSet(&desc.CachedPSO, 0, sizeof(desc.CachedPSO) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (NULL == pso)\n\t\t\t{\n\t\t\t\tDX_CHECK(m_device->CreateGraphicsPipelineState(&desc\n\t\t\t\t\t, IID_ID3D12PipelineState\n\t\t\t\t\t, (void**)&pso\n\t\t\t\t\t) );\n\t\t\t}\n\n\t\t\tBGFX_FATAL(NULL != pso, Fatal::InvalidShader, "Failed to create PSO!");\n\n\t\t\tm_pipelineStateCache.add(hash, pso);\n\n\t\t\tif (NULL != temp)\n\t\t\t{\n\t\t\t\trelease(temp);\n\t\t\t}\n\n\t\t\tID3DBlob* blob;\n\t\t\tHRESULT hr = pso->GetCachedBlob(&blob);\n\t\t\tif (SUCCEEDED(hr) )\n\t\t\t{\n\t\t\t\tvoid* data = blob->GetBufferPointer();\n\t\t\t\tlength = (uint32_t)blob->GetBufferSize();\n\n\t\t\t\tg_callback->cacheWrite(hash, data, length);\n\n\t\t\t\tDX_RELEASE(blob, 0);\n\t\t\t}\n\n\t\t\tif (NULL != cachedData)\n\t\t\t{\n\t\t\t\tBX_FREE(g_allocator, cachedData);\n\t\t\t}\n\n\t\t\treturn pso;\n\t\t}\n\n\t\tuint16_t getSamplerState(const uint32_t* _flags, uint32_t _num, const float _palette[][4])\n\t\t{\n\t\t\tbx::HashMurmur2A murmur;\n\t\t\tmurmur.begin();\n\t\t\tmurmur.add(_flags, _num * sizeof(uint32_t) );\n\t\t\tuint32_t hash = murmur.end();\n\n\t\t\tuint16_t sampler = m_samplerStateCache.find(hash);\n\t\t\tif (UINT16_MAX == sampler)\n\t\t\t{\n\t\t\t\tsampler = m_samplerAllocator.alloc(_flags, _num, _palette);\n\t\t\t\tm_samplerStateCache.add(hash, sampler);\n\t\t\t}\n\n\t\t\treturn sampler;\n\t\t}\n\n\t\tbool isVisible(Frame* _render, OcclusionQueryHandle _handle, bool _visible)\n\t\t{\n\t\t\treturn _visible == (0 != _render->m_occlusion[_handle.idx]);\n\t\t}\n\n\t\tvoid commit(UniformBuffer& _uniformBuffer)\n\t\t{\n\t\t\t_uniformBuffer.reset();\n\n\t\t\tfor (;;)\n\t\t\t{\n\t\t\t\tuint32_t opcode = _uniformBuffer.read();\n\n\t\t\t\tif (UniformType::End == opcode)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tUniformType::Enum type;\n\t\t\t\tuint16_t loc;\n\t\t\t\tuint16_t num;\n\t\t\t\tuint16_t copy;\n\t\t\t\tUniformBuffer::decodeOpcode(opcode, type, loc, num, copy);\n\n\t\t\t\tconst char* data;\n\t\t\t\tif (copy)\n\t\t\t\t{\n\t\t\t\t\tdata = _uniformBuffer.read(g_uniformTypeSize[type]*num);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tUniformHandle handle;\n\t\t\t\t\tbx::memCopy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );\n\t\t\t\t\tdata = (const char*)m_uniforms[handle.idx];\n\t\t\t\t}\n\n\t\t\t\tswitch ( (uint32_t)type)\n\t\t\t\t{\n\t\t\t\tcase UniformType::Mat3:\n\t\t\t\tcase UniformType::Mat3|kUniformFragmentBit:\n\t\t\t\t\t {\n\t\t\t\t\t\t float* value = (float*)data;\n\t\t\t\t\t\t for (uint32_t ii = 0, count = num/3; ii < count; ++ii,  loc += 3*16, value += 9)\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t Matrix4 mtx;\n\t\t\t\t\t\t\t mtx.un.val[ 0] = value[0];\n\t\t\t\t\t\t\t mtx.un.val[ 1] = value[1];\n\t\t\t\t\t\t\t mtx.un.val[ 2] = value[2];\n\t\t\t\t\t\t\t mtx.un.val[ 3] = 0.0f;\n\t\t\t\t\t\t\t mtx.un.val[ 4] = value[3];\n\t\t\t\t\t\t\t mtx.un.val[ 5] = value[4];\n\t\t\t\t\t\t\t mtx.un.val[ 6] = value[5];\n\t\t\t\t\t\t\t mtx.un.val[ 7] = 0.0f;\n\t\t\t\t\t\t\t mtx.un.val[ 8] = value[6];\n\t\t\t\t\t\t\t mtx.un.val[ 9] = value[7];\n\t\t\t\t\t\t\t mtx.un.val[10] = value[8];\n\t\t\t\t\t\t\t mtx.un.val[11] = 0.0f;\n\t\t\t\t\t\t\t setShaderUniform(uint8_t(type), loc, &mtx.un.val[0], 3);\n\t\t\t\t\t\t }\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UniformType::Sampler:\n\t\t\t\tcase UniformType::Sampler | kUniformFragmentBit:\n\t\t\t\tcase UniformType::Vec4:\n\t\t\t\tcase UniformType::Vec4 | kUniformFragmentBit:\n\t\t\t\tcase UniformType::Mat4:\n\t\t\t\tcase UniformType::Mat4 | kUniformFragmentBit:\n\t\t\t\t\t{\n\t\t\t\t\t\tsetShaderUniform(uint8_t(type), loc, data, num);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase UniformType::End:\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tBX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid clear(const Clear& _clear, const float _palette[][4], const D3D12_RECT* _rect = NULL, uint32_t _num = 0)\n\t\t{\n\t\t\tif (isValid(m_fbh) )\n\t\t\t{\n\t\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx];\n\t\t\t\tframeBuffer.clear(m_commandList, _clear, _palette);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (NULL != m_currentColor\n\t\t\t\t&&  BGFX_CLEAR_COLOR & _clear.m_flags)\n\t\t\t\t{\n\t\t\t\t\tif (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)\n\t\t\t\t\t{\n\t\t\t\t\t\tuint8_t index = _clear.m_index[0];\n\t\t\t\t\t\tif (UINT8_MAX != index)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_commandList->ClearRenderTargetView(*m_currentColor\n\t\t\t\t\t\t\t\t, _palette[index]\n\t\t\t\t\t\t\t\t, _num\n\t\t\t\t\t\t\t\t, _rect\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat frgba[4] =\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_clear.m_index[0] * 1.0f / 255.0f,\n\t\t\t\t\t\t\t_clear.m_index[1] * 1.0f / 255.0f,\n\t\t\t\t\t\t\t_clear.m_index[2] * 1.0f / 255.0f,\n\t\t\t\t\t\t\t_clear.m_index[3] * 1.0f / 255.0f,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tm_commandList->ClearRenderTargetView(*m_currentColor\n\t\t\t\t\t\t\t, frgba\n\t\t\t\t\t\t\t, _num\n\t\t\t\t\t\t\t, _rect\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (NULL != m_currentDepthStencil\n\t\t\t\t&& (BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL) & _clear.m_flags)\n\t\t\t\t{\n\t\t\t\t\tuint32_t flags = 0;\n\t\t\t\t\tflags |= (_clear.m_flags & BGFX_CLEAR_DEPTH  ) ? D3D12_CLEAR_FLAG_DEPTH   : 0;\n\t\t\t\t\tflags |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? D3D12_CLEAR_FLAG_STENCIL : 0;\n\n\t\t\t\t\tm_commandList->ClearDepthStencilView(*m_currentDepthStencil\n\t\t\t\t\t\t, D3D12_CLEAR_FLAGS(flags)\n\t\t\t\t\t\t, _clear.m_depth\n\t\t\t\t\t\t, _clear.m_stencil\n\t\t\t\t\t\t, _num\n\t\t\t\t\t\t, _rect\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid clearQuad(const Rect& _rect, const Clear& _clear, const float _palette[][4])\n\t\t{\n\t\t\tuint32_t width;\n\t\t\tuint32_t height;\n\n\t\t\tif (isValid(m_fbh) )\n\t\t\t{\n\t\t\t\tconst FrameBufferD3D12& fb = m_frameBuffers[m_fbh.idx];\n\t\t\t\twidth  = fb.m_width;\n\t\t\t\theight = fb.m_height;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twidth  = m_scd.width;\n\t\t\t\theight = m_scd.height;\n\t\t\t}\n\n\t\t\tif (0      == _rect.m_x\n\t\t\t&&  0      == _rect.m_y\n\t\t\t&&  width  == _rect.m_width\n\t\t\t&&  height == _rect.m_height)\n\t\t\t{\n\t\t\t\tclear(_clear, _palette);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tD3D12_RECT rect;\n\t\t\t\trect.left   = _rect.m_x;\n\t\t\t\trect.top    = _rect.m_y;\n\t\t\t\trect.right  = _rect.m_x + _rect.m_width;\n\t\t\t\trect.bottom = _rect.m_y + _rect.m_height;\n\t\t\t\tclear(_clear, _palette, &rect, 1);\n\t\t\t}\n\t\t}\n\n\t\tuint64_t kick()\n\t\t{\n\t\t\tuint64_t fence = m_cmd.kick();\n\t\t\tm_commandList = m_cmd.alloc();\n\t\t\treturn fence;\n\t\t}\n\n\t\tvoid finish()\n\t\t{\n\t\t\tm_cmd.kick();\n\t\t\tm_cmd.finish();\n\t\t\tm_commandList = NULL;\n\t\t}\n\n\t\tvoid finishAll(bool _alloc = false)\n\t\t{\n\t\t\tuint64_t fence = m_cmd.kick();\n\t\t\tm_cmd.finish(fence, true);\n\t\t\tm_commandList = _alloc ? m_cmd.alloc() : NULL;\n\t\t}\n\n#if !BX_PLATFORM_LINUX\n\t\tDxgi m_dxgi;\n#endif // !BX_PLATFORM_LINUX\n\n\t\tNvApi m_nvapi;\n\n\t\tvoid* m_kernel32Dll;\n\t\tvoid* m_d3d12Dll;\n\t\tvoid* m_renderDocDll;\n\t\tvoid* m_winPixEvent;\n\n\t\tD3D_FEATURE_LEVEL m_featureLevel;\n\n\t\tD3D_DRIVER_TYPE m_driverType;\n\t\tD3D12_FEATURE_DATA_ARCHITECTURE m_architecture;\n\t\tD3D12_FEATURE_DATA_D3D12_OPTIONS m_options;\n\n\t\tDxgi::SwapChainI* m_swapChain;\n\t\tID3D12Resource*   m_msaaRt;\n\n#if BX_PLATFORM_WINDOWS\n\t\tID3D12InfoQueue* m_infoQueue;\n#endif // BX_PLATFORM_WINDOWS\n\n\t\tint64_t m_presentElapsed;\n\t\tuint16_t m_numWindows;\n\t\tFrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS];\n\n\t\tID3D12Device*       m_device;\n\t\tTimerQueryD3D12     m_gpuTimer;\n\t\tOcclusionQueryD3D12 m_occlusionQuery;\n\n\t\tuint32_t m_deviceInterfaceVersion;\n\n\t\tID3D12DescriptorHeap* m_rtvDescriptorHeap;\n\t\tID3D12DescriptorHeap* m_dsvDescriptorHeap;\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE m_rtvHandle;\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE m_dsvHandle;\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE* m_currentColor;\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE* m_currentDepthStencil;\n\t\tID3D12Resource* m_backBufferColor[BGFX_CONFIG_MAX_BACK_BUFFERS];\n\t\tuint64_t m_backBufferColorFence[BGFX_CONFIG_MAX_BACK_BUFFERS];\n\t\tID3D12Resource* m_backBufferDepthStencil;\n\n\t\tScratchBufferD3D12 m_scratchBuffer[BGFX_CONFIG_MAX_BACK_BUFFERS];\n\t\tDescriptorAllocatorD3D12 m_samplerAllocator;\n\n\t\tID3D12RootSignature*    m_rootSignature;\n\t\tID3D12CommandSignature* m_commandSignature[3];\n\n\t\tCommandQueueD3D12 m_cmd;\n\t\tBatchD3D12 m_batch;\n\t\tID3D12GraphicsCommandList* m_commandList;\n\n\t\tResolution m_resolution;\n\t\tbool m_wireframe;\n\t\tbool m_lost;\n\n\t\tSwapChainDesc m_scd;\n\t\tuint32_t m_maxAnisotropy;\n\t\tbool m_depthClamp;\n\n\t\tBufferD3D12 m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS];\n\t\tVertexBufferD3D12 m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS];\n\t\tShaderD3D12 m_shaders[BGFX_CONFIG_MAX_SHADERS];\n\t\tProgramD3D12 m_program[BGFX_CONFIG_MAX_PROGRAMS];\n\t\tTextureD3D12 m_textures[BGFX_CONFIG_MAX_TEXTURES];\n\t\tVertexLayout m_vertexLayouts[BGFX_CONFIG_MAX_VERTEX_LAYOUTS];\n\t\tFrameBufferD3D12 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];\n\t\tvoid* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];\n\t\tMatrix4 m_predefinedUniforms[PredefinedUniform::Count];\n\t\tUniformRegistry m_uniformReg;\n\n\t\tStateCacheT<ID3D12PipelineState> m_pipelineStateCache;\n\t\tStateCache m_samplerStateCache;\n\n\t\tTextVideoMem m_textVideoMem;\n\n\t\tuint8_t m_fsScratch[64<<10];\n\t\tuint8_t m_vsScratch[64<<10];\n\n\t\tFrameBufferHandle m_fbh;\n\t\tuint32_t m_backBufferColorIdx;\n\t\tbool m_rtMsaa;\n\t\tbool m_directAccessSupport;\n\t};\n\n\tstatic RendererContextD3D12* s_renderD3D12;\n\n\tRendererContextI* rendererCreate(const Init& _init)\n\t{\n\t\ts_renderD3D12 = BX_NEW(g_allocator, RendererContextD3D12);\n\t\tif (!s_renderD3D12->init(_init) )\n\t\t{\n\t\t\tBX_DELETE(g_allocator, s_renderD3D12);\n\t\t\ts_renderD3D12 = NULL;\n\t\t}\n\t\treturn s_renderD3D12;\n\t}\n\n\tvoid rendererDestroy()\n\t{\n\t\ts_renderD3D12->shutdown();\n\t\tBX_DELETE(g_allocator, s_renderD3D12);\n\t\ts_renderD3D12 = NULL;\n\t}\n\n\tvoid ScratchBufferD3D12::create(uint32_t _size, uint32_t _maxDescriptors)\n\t{\n\t\tm_size = _size;\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tm_incrementSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);\n\n\t\tD3D12_DESCRIPTOR_HEAP_DESC desc;\n\t\tdesc.NumDescriptors = _maxDescriptors;\n\t\tdesc.Type     = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;\n\t\tdesc.Flags    = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;\n\t\tdesc.NodeMask = 1;\n\t\tDX_CHECK(device->CreateDescriptorHeap(&desc\n\t\t\t, IID_ID3D12DescriptorHeap\n\t\t\t, (void**)&m_heap\n\t\t\t) );\n\n\t\tm_upload = createCommittedResource(device, HeapProperty::Upload, desc.NumDescriptors * 1024);\n\t\tm_gpuVA  = m_upload->GetGPUVirtualAddress();\n\t\tD3D12_RANGE readRange = { 0, 0 };\n\t\tm_upload->Map(0, &readRange, (void**)&m_data);\n\n\t\treset(m_gpuHandle);\n\t}\n\n\tvoid ScratchBufferD3D12::destroy()\n\t{\n\t\tD3D12_RANGE writeRange = { 0, 0 };\n\t\tm_upload->Unmap(0, &writeRange);\n\n\t\tDX_RELEASE(m_upload, 0);\n\t\tDX_RELEASE(m_heap, 0);\n\t}\n\n\tvoid ScratchBufferD3D12::reset(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle)\n\t{\n\t\tm_pos = 0;\n\t\tm_cpuHandle = getCPUHandleHeapStart(m_heap);\n\t\tm_gpuHandle = getGPUHandleHeapStart(m_heap);\n\t\t_gpuHandle = m_gpuHandle;\n\t}\n\n\tvoid ScratchBufferD3D12::allocEmpty(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle)\n\t{\n\t\tm_cpuHandle.ptr += m_incrementSize;\n\n\t\t_gpuHandle = m_gpuHandle;\n\t\tm_gpuHandle.ptr += m_incrementSize;\n\t}\n\n\tvoid* ScratchBufferD3D12::allocCbv(D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress, uint32_t _size)\n\t{\n\t\t_gpuAddress = m_gpuVA + m_pos;\n\t\tvoid* data = &m_data[m_pos];\n\n\t\tm_pos += bx::alignUp(_size, 256);\n\n//\t\tD3D12_CONSTANT_BUFFER_VIEW_DESC desc;\n//\t\tdesc.BufferLocation = _gpuAddress;\n//\t\tdesc.SizeInBytes    = _size;\n//\t\tID3D12Device* device = s_renderD3D12->m_device;\n//\t\tdevice->CreateConstantBufferView(&desc\n//\t\t\t, m_cpuHandle\n//\t\t\t);\n//\t\tm_cpuHandle.ptr += m_incrementSize;\n//\t\tm_gpuHandle.ptr += m_incrementSize;\n\n\t\treturn data;\n\t}\n\n\tvoid ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint8_t _mip)\n\t{\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\n\t\tD3D12_SHADER_RESOURCE_VIEW_DESC tmpSrvd;\n\t\tD3D12_SHADER_RESOURCE_VIEW_DESC* srvd = &_texture.m_srvd;\n\t\tif (0 != _mip)\n\t\t{\n\t\t\tbx::memCopy(&tmpSrvd, srvd, sizeof(tmpSrvd) );\n\t\t\tsrvd = &tmpSrvd;\n\n\t\t\tswitch (_texture.m_srvd.ViewDimension)\n\t\t\t{\n\t\t\tdefault:\n\t\t\tcase D3D12_SRV_DIMENSION_TEXTURE2D:\n\t\t\t\tsrvd->Texture2D.MostDetailedMip = _mip;\n\t\t\t\tsrvd->Texture2D.MipLevels       = 1;\n\t\t\t\tsrvd->Texture2D.PlaneSlice      = 0;\n\t\t\t\tsrvd->Texture2D.ResourceMinLODClamp = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase D3D12_SRV_DIMENSION_TEXTURECUBE:\n\t\t\t\tsrvd->TextureCube.MostDetailedMip = _mip;\n\t\t\t\tsrvd->TextureCube.MipLevels       = 1;\n\t\t\t\tsrvd->TextureCube.ResourceMinLODClamp = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase D3D12_SRV_DIMENSION_TEXTURE3D:\n\t\t\t\tsrvd->Texture3D.MostDetailedMip = _mip;\n\t\t\t\tsrvd->Texture3D.MipLevels       = 1;\n\t\t\t\tsrvd->Texture3D.ResourceMinLODClamp = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tdevice->CreateShaderResourceView(NULL != _texture.m_singleMsaa ? _texture.m_singleMsaa : _texture.m_ptr\n\t\t\t, srvd\n\t\t\t, m_cpuHandle\n\t\t\t);\n\t\tm_cpuHandle.ptr += m_incrementSize;\n\n\t\t_gpuHandle = m_gpuHandle;\n\t\tm_gpuHandle.ptr += m_incrementSize;\n\t}\n\n\tvoid ScratchBufferD3D12::allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint8_t _mip)\n\t{\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\n\t\tD3D12_UNORDERED_ACCESS_VIEW_DESC tmpUavd;\n\t\tD3D12_UNORDERED_ACCESS_VIEW_DESC* uavd = &_texture.m_uavd;\n\n\t\tif (0 != _mip)\n\t\t{\n\t\t\tbx::memCopy(&tmpUavd, uavd, sizeof(tmpUavd) );\n\t\t\tuavd = &tmpUavd;\n\n\t\t\tswitch (_texture.m_uavd.ViewDimension)\n\t\t\t{\n\t\t\tdefault:\n\t\t\tcase D3D12_UAV_DIMENSION_TEXTURE2D:\n\t\t\t\tuavd->Texture2D.MipSlice   = _mip;\n\t\t\t\tuavd->Texture2D.PlaneSlice = 0;\n\t\t\t\tbreak;\n\t\t\tcase D3D12_UAV_DIMENSION_TEXTURE2DARRAY:\n\t\t\t\tuavd->Texture2DArray.MipSlice   = _mip;\n\t\t\t\tuavd->Texture2DArray.PlaneSlice = 0;\n\t\t\t\tbreak;\n\n\t\t\tcase D3D12_UAV_DIMENSION_TEXTURE3D:\n\t\t\t\tuavd->Texture3D.MipSlice = _mip;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tdevice->CreateUnorderedAccessView(_texture.m_ptr\n\t\t\t, NULL\n\t\t\t, uavd\n\t\t\t, m_cpuHandle\n\t\t\t);\n\t\tm_cpuHandle.ptr += m_incrementSize;\n\n\t\t_gpuHandle = m_gpuHandle;\n\t\tm_gpuHandle.ptr += m_incrementSize;\n\t}\n\n\tvoid ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, BufferD3D12& _buffer)\n\t{\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tdevice->CreateShaderResourceView(_buffer.m_ptr\n\t\t\t, &_buffer.m_srvd\n\t\t\t, m_cpuHandle\n\t\t\t);\n\t\tm_cpuHandle.ptr += m_incrementSize;\n\n\t\t_gpuHandle = m_gpuHandle;\n\t\tm_gpuHandle.ptr += m_incrementSize;\n\t}\n\n\tvoid ScratchBufferD3D12::allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, BufferD3D12& _buffer)\n\t{\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tdevice->CreateUnorderedAccessView(_buffer.m_ptr\n\t\t\t, NULL\n\t\t\t, &_buffer.m_uavd\n\t\t\t, m_cpuHandle\n\t\t\t);\n\t\tm_cpuHandle.ptr += m_incrementSize;\n\n\t\t_gpuHandle = m_gpuHandle;\n\t\tm_gpuHandle.ptr += m_incrementSize;\n\t}\n\n\tvoid DescriptorAllocatorD3D12::create(D3D12_DESCRIPTOR_HEAP_TYPE _type, uint16_t _maxDescriptors, uint16_t _numDescriptorsPerBlock)\n\t{\n\t\tm_handleAlloc = bx::createHandleAlloc(g_allocator, _maxDescriptors);\n\t\tm_numDescriptorsPerBlock = _numDescriptorsPerBlock;\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\n\t\tm_incrementSize = device->GetDescriptorHandleIncrementSize(_type);\n\n\t\tD3D12_DESCRIPTOR_HEAP_DESC desc;\n\t\tdesc.NumDescriptors = _maxDescriptors;\n\t\tdesc.Type     = _type;\n\t\tdesc.Flags    = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;\n\t\tdesc.NodeMask = 1;\n\t\tDX_CHECK(device->CreateDescriptorHeap(&desc\n\t\t\t, IID_ID3D12DescriptorHeap\n\t\t\t, (void**)&m_heap\n\t\t\t) );\n\n\t\tm_cpuHandle = getCPUHandleHeapStart(m_heap);\n\t\tm_gpuHandle = getGPUHandleHeapStart(m_heap);\n\t}\n\n\tvoid DescriptorAllocatorD3D12::destroy()\n\t{\n\t\tbx::destroyHandleAlloc(g_allocator, m_handleAlloc);\n\n\t\tDX_RELEASE(m_heap, 0);\n\t}\n\n\tuint16_t DescriptorAllocatorD3D12::alloc(ID3D12Resource* _ptr, const D3D12_SHADER_RESOURCE_VIEW_DESC* _desc)\n\t{\n\t\tuint16_t idx = m_handleAlloc->alloc();\n\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = { m_cpuHandle.ptr + idx * m_incrementSize };\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tdevice->CreateShaderResourceView(_ptr\n\t\t\t, _desc\n\t\t\t, cpuHandle\n\t\t\t);\n\n\t\treturn idx;\n\t}\n\n\tuint16_t DescriptorAllocatorD3D12::alloc(const uint32_t* _flags, uint32_t _num, const float _palette[][4])\n\t{\n\t\tuint16_t idx = m_handleAlloc->alloc();\n\n\t\tID3D12Device* device   = s_renderD3D12->m_device;\n\t\tuint32_t maxAnisotropy = s_renderD3D12->m_maxAnisotropy;\n\n\t\tfor (uint32_t ii = 0; ii < _num; ++ii)\n\t\t{\n\t\t\tuint32_t flags = _flags[ii];\n\n\t\t\tconst uint32_t cmpFunc   = (flags&BGFX_SAMPLER_COMPARE_MASK)>>BGFX_SAMPLER_COMPARE_SHIFT;\n\t\t\tconst uint8_t  minFilter = s_textureFilter[0][(flags&BGFX_SAMPLER_MIN_MASK)>>BGFX_SAMPLER_MIN_SHIFT];\n\t\t\tconst uint8_t  magFilter = s_textureFilter[1][(flags&BGFX_SAMPLER_MAG_MASK)>>BGFX_SAMPLER_MAG_SHIFT];\n\t\t\tconst uint8_t  mipFilter = s_textureFilter[2][(flags&BGFX_SAMPLER_MIP_MASK)>>BGFX_SAMPLER_MIP_SHIFT];\n\t\t\tconst uint8_t  filter    = 0 == cmpFunc ? 0 : D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;\n\n\t\t\tD3D12_SAMPLER_DESC sd;\n\t\t\tsd.Filter   = (D3D12_FILTER)(filter|minFilter|magFilter|mipFilter);\n\t\t\tsd.AddressU = s_textureAddress[(flags&BGFX_SAMPLER_U_MASK)>>BGFX_SAMPLER_U_SHIFT];\n\t\t\tsd.AddressV = s_textureAddress[(flags&BGFX_SAMPLER_V_MASK)>>BGFX_SAMPLER_V_SHIFT];\n\t\t\tsd.AddressW = s_textureAddress[(flags&BGFX_SAMPLER_W_MASK)>>BGFX_SAMPLER_W_SHIFT];\n\t\t\tsd.MipLODBias     = float(BGFX_CONFIG_MIP_LOD_BIAS);\n\t\t\tsd.MaxAnisotropy  = maxAnisotropy;\n\t\t\tsd.ComparisonFunc = 0 == cmpFunc ? D3D12_COMPARISON_FUNC_NEVER : s_cmpFunc[cmpFunc];\n\n\t\t\tuint32_t index = (flags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT;\n\n\t\t\tif (NULL != _palette\n\t\t\t&&  needBorderColor(flags) )\n\t\t\t{\n\t\t\t\tconst float* rgba = _palette[index];\n\t\t\t\tsd.BorderColor[0] = rgba[0];\n\t\t\t\tsd.BorderColor[1] = rgba[1];\n\t\t\t\tsd.BorderColor[2] = rgba[2];\n\t\t\t\tsd.BorderColor[3] = rgba[3];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsd.BorderColor[0] = 0.0f;\n\t\t\t\tsd.BorderColor[1] = 0.0f;\n\t\t\t\tsd.BorderColor[2] = 0.0f;\n\t\t\t\tsd.BorderColor[3] = 0.0f;\n\t\t\t}\n\t\t\tsd.MinLOD   = 0;\n\t\t\tsd.MaxLOD   = D3D12_FLOAT32_MAX;\n\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE cpuHandle =\n\t\t\t{\n\t\t\t\tm_cpuHandle.ptr + (idx * m_numDescriptorsPerBlock + ii) * m_incrementSize\n\t\t\t};\n\n\t\t\tdevice->CreateSampler(&sd, cpuHandle);\n\t\t}\n\n\t\treturn idx;\n\t}\n\n\tvoid DescriptorAllocatorD3D12::free(uint16_t _idx)\n\t{\n\t\tm_handleAlloc->free(_idx);\n\t}\n\n\tvoid DescriptorAllocatorD3D12::reset()\n\t{\n\t\tuint16_t max = m_handleAlloc->getMaxHandles();\n\t\tbx::destroyHandleAlloc(g_allocator, m_handleAlloc);\n\t\tm_handleAlloc = bx::createHandleAlloc(g_allocator, max);\n\t}\n\n\tD3D12_GPU_DESCRIPTOR_HANDLE DescriptorAllocatorD3D12::get(uint16_t _idx)\n\t{\n\t\tD3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = { m_gpuHandle.ptr + _idx * m_numDescriptorsPerBlock * m_incrementSize };\n\t\treturn gpuHandle;\n\t}\n\n\tvoid CommandQueueD3D12::init(ID3D12Device* _device)\n\t{\n\t\tD3D12_COMMAND_QUEUE_DESC queueDesc;\n\t\tqueueDesc.Type     = D3D12_COMMAND_LIST_TYPE_DIRECT;\n\t\tqueueDesc.Priority = 0;\n\t\tqueueDesc.Flags    = D3D12_COMMAND_QUEUE_FLAG_NONE;\n\t\tqueueDesc.NodeMask = 1;\n\t\tDX_CHECK(_device->CreateCommandQueue(&queueDesc\n\t\t\t, IID_ID3D12CommandQueue\n\t\t\t, (void**)&m_commandQueue\n\t\t\t) );\n\n\t\tm_completedFence = 0;\n\t\tm_currentFence   = 0;\n\t\tDX_CHECK(_device->CreateFence(0\n\t\t\t, D3D12_FENCE_FLAG_NONE\n\t\t\t, IID_ID3D12Fence\n\t\t\t, (void**)&m_fence\n\t\t\t) );\n\n\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_commandList); ++ii)\n\t\t{\n\t\t\tDX_CHECK(_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT\n\t\t\t\t, IID_ID3D12CommandAllocator\n\t\t\t\t, (void**)&m_commandList[ii].m_commandAllocator\n\t\t\t\t) );\n\n\t\t\tDX_CHECK(_device->CreateCommandList(0\n\t\t\t\t, D3D12_COMMAND_LIST_TYPE_DIRECT\n\t\t\t\t, m_commandList[ii].m_commandAllocator\n\t\t\t\t, NULL\n\t\t\t\t, IID_ID3D12GraphicsCommandList\n\t\t\t\t, (void**)&m_commandList[ii].m_commandList\n\t\t\t\t) );\n\n\t\t\tDX_CHECK(m_commandList[ii].m_commandList->Close() );\n\t\t}\n\t}\n\n\tvoid CommandQueueD3D12::shutdown()\n\t{\n\t\tfinish(UINT64_MAX, true);\n\n\t\tDX_RELEASE(m_fence, 0);\n\n\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_commandList); ++ii)\n\t\t{\n\t\t\tDX_RELEASE(m_commandList[ii].m_commandAllocator, 0);\n\t\t\tDX_RELEASE(m_commandList[ii].m_commandList, 0);\n\t\t}\n\n\t\tDX_RELEASE(m_commandQueue, 0);\n\t}\n\n\tID3D12GraphicsCommandList* CommandQueueD3D12::alloc()\n\t{\n\t\twhile (0 == m_control.reserve(1) )\n\t\t{\n\t\t\tconsume();\n\t\t}\n\n\t\tCommandList& commandList = m_commandList[m_control.m_current];\n\t\tDX_CHECK(commandList.m_commandAllocator->Reset() );\n\t\tDX_CHECK(commandList.m_commandList->Reset(commandList.m_commandAllocator, NULL) );\n\t\treturn commandList.m_commandList;\n\t}\n\n\tuint64_t CommandQueueD3D12::kick()\n\t{\n\t\tCommandList& commandList = m_commandList[m_control.m_current];\n\t\tDX_CHECK(commandList.m_commandList->Close() );\n\n\t\tID3D12CommandList* commandLists[] = { commandList.m_commandList };\n\t\tm_commandQueue->ExecuteCommandLists(BX_COUNTOF(commandLists), commandLists);\n\n#if BX_PLATFORM_LINUX\n\t\tcommandList.m_event = NULL;\n#else\n\t\tcommandList.m_event = CreateEventExA(NULL, NULL, 0, EVENT_ALL_ACCESS);\n#endif // BX_PLATFORM_LINUX\n\t\tconst uint64_t fence = m_currentFence++;\n\t\tm_commandQueue->Signal(m_fence, fence);\n\t\tm_fence->SetEventOnCompletion(fence, commandList.m_event);\n\n\t\tm_control.commit(1);\n\n\t\treturn fence;\n\t}\n\n\tvoid CommandQueueD3D12::finish(uint64_t _waitFence, bool _finishAll)\n\t{\n\t\twhile (0 < m_control.available() )\n\t\t{\n\t\t\tconsume();\n\n\t\t\tif (!_finishAll\n\t\t\t&&  _waitFence <= m_completedFence)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tBX_ASSERT(0 == m_control.available(), "");\n\t}\n\n\tbool CommandQueueD3D12::tryFinish(uint64_t _waitFence)\n\t{\n\t\tif (0 < m_control.available() )\n\t\t{\n\t\t\tif (consume(0)\n\t\t\t&& _waitFence <= m_completedFence)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tvoid CommandQueueD3D12::release(ID3D12Resource* _ptr)\n\t{\n\t\tm_release[m_control.m_current].push_back(_ptr);\n\t}\n\n\tbool CommandQueueD3D12::consume(uint32_t _ms)\n\t{\n\t\tCommandList& commandList = m_commandList[m_control.m_read];\n#if BX_PLATFORM_LINUX\n\t\tBX_UNUSED(commandList, _ms);\n#else\n\t\tif (WAIT_OBJECT_0 == WaitForSingleObject(commandList.m_event, _ms) )\n\t\t{\n\t\t\tCloseHandle(commandList.m_event);\n\t\t\tcommandList.m_event = NULL;\n\t\t\tm_completedFence = m_fence->GetCompletedValue();\n\t\t\tBX_WARN(UINT64_MAX != m_completedFence, "D3D12: Device lost.");\n\n\t\t\tm_commandQueue->Wait(m_fence, m_completedFence);\n\n\t\t\tResourceArray& ra = m_release[m_control.m_read];\n\t\t\tfor (ResourceArray::iterator it = ra.begin(), itEnd = ra.end(); it != itEnd; ++it)\n\t\t\t{\n\t\t\t\tDX_RELEASE(*it, 0);\n\t\t\t}\n\t\t\tra.clear();\n\n\t\t\tm_control.consume(1);\n\n\t\t\treturn true;\n\t\t}\n#endif // !BX_PLATFORM_LINUX\n\n\t\treturn false;\n\t}\n\n\tvoid BatchD3D12::create(uint32_t _maxDrawPerBatch)\n\t{\n\t\tm_maxDrawPerBatch = _maxDrawPerBatch;\n\t\tsetSeqMode(false);\n\t\tsetIndirectMode(true);\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tID3D12RootSignature* rootSignature = s_renderD3D12->m_rootSignature;\n\n\t\tD3D12_INDIRECT_ARGUMENT_DESC drawArgDesc[] =\n\t\t{\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 0        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 1        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 2        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 3        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 4        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { { Rdt::CBV } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,                 { { 0        } } },\n\t\t};\n\n\t\tD3D12_COMMAND_SIGNATURE_DESC drawCommandSignature =\n\t\t{\n\t\t\tsizeof(DrawIndirectCommand),\n\t\t\tBX_COUNTOF(drawArgDesc),\n\t\t\tdrawArgDesc,\n\t\t\t1,\n\t\t};\n\n\t\tDX_CHECK(device->CreateCommandSignature(&drawCommandSignature\n\t\t\t, rootSignature\n\t\t\t, IID_ID3D12CommandSignature\n\t\t\t, (void**)&m_commandSignature[Draw]\n\t\t\t) );\n\n\t\tD3D12_INDIRECT_ARGUMENT_DESC drawIndexedArgDesc[] =\n\t\t{\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 0        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 1        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 2        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 3        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,   { { 4        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,    { { 0        } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, { { Rdt::CBV } } },\n\t\t\t{ D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,         { { 0        } } },\n\t\t};\n\n\t\tD3D12_COMMAND_SIGNATURE_DESC drawIndexedCommandSignature =\n\t\t{\n\t\t\tsizeof(DrawIndexedIndirectCommand),\n\t\t\tBX_COUNTOF(drawIndexedArgDesc),\n\t\t\tdrawIndexedArgDesc,\n\t\t\t1,\n\t\t};\n\n\t\tDX_CHECK(device->CreateCommandSignature(&drawIndexedCommandSignature\n\t\t\t, rootSignature\n\t\t\t, IID_ID3D12CommandSignature\n\t\t\t, (void**)&m_commandSignature[DrawIndexed]\n\t\t\t) );\n\n\t\tm_cmds[Draw       ] = BX_ALLOC(g_allocator, m_maxDrawPerBatch*sizeof(DrawIndirectCommand) );\n\t\tm_cmds[DrawIndexed] = BX_ALLOC(g_allocator, m_maxDrawPerBatch*sizeof(DrawIndexedIndirectCommand) );\n\n\t\tuint32_t cmdSize = bx::max<uint32_t>(sizeof(DrawIndirectCommand), sizeof(DrawIndexedIndirectCommand) );\n\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_indirect); ++ii)\n\t\t{\n\t\t\tm_indirect[ii].create(m_maxDrawPerBatch*cmdSize\n\t\t\t\t, NULL\n\t\t\t\t, BGFX_BUFFER_DRAW_INDIRECT\n\t\t\t\t, false\n\t\t\t\t, cmdSize\n\t\t\t\t);\n\t\t}\n\t}\n\n\tvoid BatchD3D12::destroy()\n\t{\n\t\tBX_FREE(g_allocator, m_cmds[0]);\n\t\tBX_FREE(g_allocator, m_cmds[1]);\n\n\t\tDX_RELEASE(m_commandSignature[0], 0);\n\t\tDX_RELEASE(m_commandSignature[1], 0);\n\n\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_indirect); ++ii)\n\t\t{\n\t\t\tm_indirect[ii].destroy();\n\t\t}\n\t}\n\n\ttemplate<typename Ty>\n\tTy& BatchD3D12::getCmd(Enum _type)\n\t{\n\t\tuint32_t index = m_num[_type];\n\t\tBX_ASSERT(index < m_maxDrawPerBatch, "Memory corruption...");\n\t\tm_num[_type]++;\n\t\tTy* cmd = &reinterpret_cast<Ty*>(m_cmds[_type])[index];\n\t\treturn *cmd;\n\t}\n\n\tuint8_t fill(ID3D12GraphicsCommandList* _commandList, D3D12_VERTEX_BUFFER_VIEW* _vbv, const RenderDraw& _draw, uint32_t& _outNumVertices)\n\t{\n\t\tuint8_t numStreams = 0;\n\t\t_outNumVertices = _draw.m_numVertices;\n\n\t\tif (UINT8_MAX != _draw.m_streamMask)\n\t\t{\n\t\t\tfor (uint32_t idx = 0, streamMask = _draw.m_streamMask\n\t\t\t\t; 0 != streamMask\n\t\t\t\t; streamMask >>= 1, idx += 1, ++numStreams\n\t\t\t\t)\n\t\t\t{\n\t\t\t\tconst uint32_t ntz = bx::uint32_cnttz(streamMask);\n\t\t\t\tstreamMask >>= ntz;\n\t\t\t\tidx         += ntz;\n\n\t\t\t\tconst Stream& stream = _draw.m_stream[idx];\n\n\t\t\t\tuint16_t handle = stream.m_handle.idx;\n\t\t\t\tVertexBufferD3D12& vb = s_renderD3D12->m_vertexBuffers[handle];\n\t\t\t\tvb.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\n\t\t\t\tconst uint16_t layoutIdx = !isValid(vb.m_layoutHandle) ? stream.m_layoutHandle.idx : vb.m_layoutHandle.idx;\n\t\t\t\tconst VertexLayout& layout = s_renderD3D12->m_vertexLayouts[layoutIdx];\n\t\t\t\tuint32_t stride = layout.m_stride;\n\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW& vbv = _vbv[numStreams];\n\t\t\t\tvbv.BufferLocation = vb.m_gpuVA + stream.m_startVertex * stride;\n\t\t\t\tvbv.StrideInBytes  = layout.m_stride;\n\t\t\t\tvbv.SizeInBytes    = vb.m_size;\n\n\t\t\t\t_outNumVertices = bx::uint32_min(UINT32_MAX == _draw.m_numVertices\n\t\t\t\t\t? vb.m_size/stride\n\t\t\t\t\t: _draw.m_numVertices\n\t\t\t\t\t, _outNumVertices\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\n\t\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, srvHandle[0]);\n\n\t\t\t\t\t\t\t\tbindLru.add(bindHash, srvHandle[0]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse \n\t\t\t_commandList->SetGraphicsRootConstantBufferView(Rdt::CBV, _cbv);\n\n\t\t\tD3D12_VERTEX_BUFFER_VIEW vbvs[BGFX_CONFIG_MAX_VERTEX_STREAMS+1];\n\n\t\t\tuint32_t numVertices;\n\t\t\tuint8_t  numStreams = fill(_commandList, vbvs, _draw, numVertices);\n\n\t\t\tif (isValid(_draw.m_instanceDataBuffer) )\n\t\t\t{\n\t\t\t\tVertexBufferD3D12& inst = s_renderD3D12->m_vertexBuffers[_draw.m_instanceDataBuffer.idx];\n\t\t\t\tinst.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW& vbv = vbvs[numStreams++];\n\t\t\t\tvbv.BufferLocation = inst.m_gpuVA + _draw.m_instanceDataOffset;\n\t\t\t\tvbv.StrideInBytes  = _draw.m_instanceDataStride;\n\t\t\t\tvbv.SizeInBytes    = _draw.m_numInstances * _draw.m_instanceDataStride;\n\t\t\t}\n\n\t\t\t_commandList->IASetVertexBuffers(0\n\t\t\t\t, numStreams\n\t\t\t\t, vbvs\n\t\t\t\t);\n\n\t\t\tconst VertexBufferD3D12& indirect = s_renderD3D12->m_vertexBuffers[_draw.m_indirectBuffer.idx];\n\t\t\tconst uint32_t numDrawIndirect = UINT16_MAX == _draw.m_numIndirect\n\t\t\t\t? indirect.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE\n\t\t\t\t: _draw.m_numIndirect\n\t\t\t\t;\n\t\t\tID3D12Resource* numIndirect = NULL;\n\t\t\tuint32_t numOffsetIndirect = 0;\n\t\t\tif (isValid(_draw.m_numIndirectBuffer) )\n\t\t\t{\n\t\t\t\tnumIndirect = s_renderD3D12->m_indexBuffers[_draw.m_numIndirectBuffer.idx].m_ptr;\n\t\t\t\tnumOffsetIndirect = _draw.m_numIndirectIndex * sizeof(uint32_t);\n\t\t\t}\n\n\t\t\tuint32_t numIndices = 0;\n\n\t\t\tif (isValid(_draw.m_indexBuffer) )\n\t\t\t{\n\t\t\t\tBufferD3D12& ib = s_renderD3D12->m_indexBuffers[_draw.m_indexBuffer.idx];\n\t\t\t\tib.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\n\t\t\t\tconst bool isIndex16          = _draw.isIndex16();\n\t\t\t\tconst uint32_t indexSize      = isIndex16 ? 2 : 4;\n\t\t\t\tconst DXGI_FORMAT indexFormat = isIndex16\n\t\t\t\t\t? DXGI_FORMAT_R16_UINT\n\t\t\t\t\t: DXGI_FORMAT_R32_UINT\n\t\t\t\t\t;\n\n\t\t\t\tnumIndices = UINT32_MAX == _draw.m_numIndices\n\t\t\t\t\t? ib.m_size / indexSize\n\t\t\t\t\t: _draw.m_numIndices\n\t\t\t\t\t;\n\n\t\t\t\tD3D12_INDEX_BUFFER_VIEW ibv;\n\t\t\t\tibv.BufferLocation = ib.m_gpuVA;\n\t\t\t\tibv.SizeInBytes    = ib.m_size;\n\t\t\t\tibv.Format         = indexFormat;\n\t\t\t\t_commandList->IASetIndexBuffer(&ibv);\n\n\t\t\t\t_commandList->ExecuteIndirect(\n\t\t\t\t\t  s_renderD3D12->m_commandSignature[2]\n\t\t\t\t\t, numDrawIndirect\n\t\t\t\t\t, indirect.m_ptr\n\t\t\t\t\t, _draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE\n\t\t\t\t\t, numIndirect\n\t\t\t\t\t, numOffsetIndirect\n\t\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_commandList->ExecuteIndirect(\n\t\t\t\t\t  s_renderD3D12->m_commandSignature[1]\n\t\t\t\t\t, numDrawIndirect\n\t\t\t\t\t, indirect.m_ptr\n\t\t\t\t\t, _draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE\n\t\t\t\t\t, numIndirect\n\t\t\t\t\t, numOffsetIndirect\n\t\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn numIndices;\n\t\t}\n\n\t\tEnum type = Enum(!!isValid(_draw.m_indexBuffer) );\n\n\t\tuint32_t numIndices = 0;\n\n\t\tif (Draw == type)\n\t\t{\n\t\t\tDrawIndirectCommand& cmd = getCmd<DrawIndirectCommand>(Draw);\n\t\t\tcmd.cbv = _cbv;\n\n\t\t\tuint32_t numVertices;\n\t\t\tuint8_t  numStreams = fill(_commandList, cmd.vbv, _draw, numVertices);\n\n\t\t\tif (isValid(_draw.m_instanceDataBuffer) )\n\t\t\t{\n\t\t\t\tVertexBufferD3D12& inst = s_renderD3D12->m_vertexBuffers[_draw.m_instanceDataBuffer.idx];\n\t\t\t\tinst.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW& vbv = cmd.vbv[numStreams++];\n\t\t\t\tvbv.BufferLocation = inst.m_gpuVA + _draw.m_instanceDataOffset;\n\t\t\t\tvbv.StrideInBytes  = _draw.m_instanceDataStride;\n\t\t\t\tvbv.SizeInBytes    = _draw.m_numInstances * _draw.m_instanceDataStride;\n\t\t\t}\n\n\t\t\tfor (; numStreams < BX_COUNTOF(cmd.vbv); ++numStreams)\n\t\t\t{\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW* vbv = &cmd.vbv[numStreams];\n\t\t\t\tbx::memSet(vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));\n\t\t\t}\n\n\t\t\tcmd.args.InstanceCount          = _draw.m_numInstances;\n\t\t\tcmd.args.VertexCountPerInstance = numVertices;\n\t\t\tcmd.args.StartVertexLocation    = 0;\n\t\t\tcmd.args.StartInstanceLocation  = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBufferD3D12& ib = s_renderD3D12->m_indexBuffers[_draw.m_indexBuffer.idx];\n\t\t\tib.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\n\t\t\tconst bool isIndex16          = _draw.isIndex16();\n\t\t\tconst uint32_t indexSize      = isIndex16 ? 2 : 4;\n\t\t\tconst DXGI_FORMAT indexFormat = isIndex16 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;\n\n\t\t\tnumIndices = UINT32_MAX == _draw.m_numIndices\n\t\t\t\t? ib.m_size / indexSize\n\t\t\t\t: _draw.m_numIndices\n\t\t\t\t;\n\n\t\t\tDrawIndexedIndirectCommand& cmd = getCmd<DrawIndexedIndirectCommand>(DrawIndexed);\n\t\t\tcmd.cbv = _cbv;\n\t\t\tcmd.ibv.BufferLocation = ib.m_gpuVA;\n\t\t\tcmd.ibv.SizeInBytes    = ib.m_size;\n\t\t\tcmd.ibv.Format         = indexFormat;\n\n\t\t\tuint32_t numVertices;\n\t\t\tuint8_t  numStreams = fill(_commandList, cmd.vbv, _draw, numVertices);\n\n\t\t\tif (isValid(_draw.m_instanceDataBuffer) )\n\t\t\t{\n\t\t\t\tVertexBufferD3D12& inst = s_renderD3D12->m_vertexBuffers[_draw.m_instanceDataBuffer.idx];\n\t\t\t\tinst.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW& vbv = cmd.vbv[numStreams++];\n\t\t\t\tvbv.BufferLocation = inst.m_gpuVA + _draw.m_instanceDataOffset;\n\t\t\t\tvbv.StrideInBytes  = _draw.m_instanceDataStride;\n\t\t\t\tvbv.SizeInBytes    = _draw.m_numInstances * _draw.m_instanceDataStride;\n\t\t\t}\n\n\t\t\tfor (; numStreams < BX_COUNTOF(cmd.vbv); ++numStreams)\n\t\t\t{\n\t\t\t\tD3D12_VERTEX_BUFFER_VIEW* vbv = &cmd.vbv[numStreams];\n\t\t\t\tbx::memSet(vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));\n\t\t\t}\n\n\t\t\tcmd.args.IndexCountPerInstance = numIndices;\n\t\t\tcmd.args.InstanceCount         = _draw.m_numInstances;\n\t\t\tcmd.args.StartIndexLocation    = _draw.m_startIndex;\n\t\t\tcmd.args.BaseVertexLocation    = 0;\n\t\t\tcmd.args.StartInstanceLocation = 0;\n\t\t}\n\n\t\tif (BX_UNLIKELY(m_flushPerBatch == m_num[type]) )\n\t\t{\n\t\t\tflush(_commandList, type);\n\t\t}\n\n\t\treturn numIndices;\n\t}\n\n\tstatic const uint32_t s_indirectCommandSize[] =\n\t{\n\t\tsizeof(BatchD3D12::DrawIndirectCommand),\n\t\tsizeof(BatchD3D12::DrawIndexedIndirectCommand),\n\t};\n\tBX_STATIC_ASSERT(BX_COUNTOF(s_indirectCommandSize) == BatchD3D12::Count);\n\n\tvoid BatchD3D12::flush(ID3D12GraphicsCommandList* _commandList, Enum _type)\n\t{\n\t\tuint32_t num = m_num[_type];\n\t\tif (0 != num)\n\t\t{\n\t\t\tm_num[_type] = 0;\n\n\t\t\tif (m_minIndirect < num)\n\t\t\t{\n\t\t\t\tm_stats.m_numIndirect[_type]++;\n\n\t\t\t\tBufferD3D12& indirect = m_indirect[m_currIndirect++];\n\t\t\t\tm_currIndirect %= BX_COUNTOF(m_indirect);\n\n\t\t\t\tindirect.update(_commandList, 0, num*s_indirectCommandSize[_type], m_cmds[_type]);\n\n\t\t\t\t_commandList->ExecuteIndirect(m_commandSignature[_type]\n\t\t\t\t\t, num\n\t\t\t\t\t, indirect.m_ptr\n\t\t\t\t\t, 0\n\t\t\t\t\t, NULL\n\t\t\t\t\t, 0\n\t\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_stats.m_numImmediate[_type]++;\n\n\t\t\t\tif (Draw == _type)\n\t\t\t\t{\n\t\t\t\t\tconst DrawIndirectCommand* cmds = reinterpret_cast<DrawIndirectCommand*>(m_cmds[_type]);\n\n\t\t\t\t\tfor (uint32_t ii = 0; ii < num; ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst DrawIndirectCommand& cmd = cmds[ii];\n\t\t\t\t\t\tif (m_current.cbv != cmd.cbv)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_current.cbv = cmd.cbv;\n\t\t\t\t\t\t\t_commandList->SetGraphicsRootConstantBufferView(Rdt::CBV, cmd.cbv);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (0 != bx::memCmp(m_current.vbv, cmd.vbv, sizeof(cmd.vbv) ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbx::memCopy(m_current.vbv, cmd.vbv, sizeof(cmd.vbv) );\n\t\t\t\t\t\t\t_commandList->IASetVertexBuffers(0\n\t\t\t\t\t\t\t\t, BGFX_CONFIG_MAX_VERTEX_STREAMS+1\n\t\t\t\t\t\t\t\t, cmd.vbv\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_commandList->DrawInstanced(\n\t\t\t\t\t\t\t  cmd.args.VertexCountPerInstance\n\t\t\t\t\t\t\t, cmd.args.InstanceCount\n\t\t\t\t\t\t\t, cmd.args.StartVertexLocation\n\t\t\t\t\t\t\t, cmd.args.StartInstanceLocation\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst DrawIndexedIndirectCommand* cmds = reinterpret_cast<DrawIndexedIndirectCommand*>(m_cmds[_type]);\n\n\t\t\t\t\tfor (uint32_t ii = 0; ii < num; ++ii)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst DrawIndexedIndirectCommand& cmd = cmds[ii];\n\t\t\t\t\t\tif (m_current.cbv != cmd.cbv)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_current.cbv = cmd.cbv;\n\t\t\t\t\t\t\t_commandList->SetGraphicsRootConstantBufferView(Rdt::CBV, cmd.cbv);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (0 != bx::memCmp(m_current.vbv, cmd.vbv, sizeof(cmd.vbv) ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbx::memCopy(m_current.vbv, cmd.vbv, sizeof(cmd.vbv) );\n\t\t\t\t\t\t\t_commandList->IASetVertexBuffers(0\n\t\t\t\t\t\t\t\t, BGFX_CONFIG_MAX_VERTEX_STREAMS+1\n\t\t\t\t\t\t\t\t, cmd.vbv\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (0 != bx::memCmp(&m_current.ibv, &cmd.ibv, sizeof(cmd.ibv) ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbx::memCopy(&m_current.ibv, &cmd.ibv, sizeof(cmd.ibv) );\n\t\t\t\t\t\t\t_commandList->IASetIndexBuffer(&cmd.ibv);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_commandList->DrawIndexedInstanced(\n\t\t\t\t\t\t\t  cmd.args.IndexCountPerInstance\n\t\t\t\t\t\t\t, cmd.args.InstanceCount\n\t\t\t\t\t\t\t, cmd.args.StartIndexLocation\n\t\t\t\t\t\t\t, cmd.args.BaseVertexLocation\n\t\t\t\t\t\t\t, cmd.args.StartInstanceLocation\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid BatchD3D12::flush(ID3D12GraphicsCommandList* _commandList, bool _clean)\n\t{\n\t\tflush(_commandList, Draw);\n\t\tflush(_commandList, DrawIndexed);\n\n\t\tif (_clean)\n\t\t{\n\t\t\tbx::memSet(&m_current, 0, sizeof(m_current) );\n\t\t}\n\t}\n\n\tvoid BatchD3D12::begin()\n\t{\n\t\tbx::memSet(&m_stats,   0, sizeof(m_stats) );\n\t\tbx::memSet(&m_current, 0, sizeof(m_current) );\n\t}\n\n\tvoid BatchD3D12::end(ID3D12GraphicsCommandList* _commandList)\n\t{\n\t\tflush(_commandList);\n\t}\n\n\tstruct UavFormat\n\t{\n\t\tDXGI_FORMAT format[3];\n\t\tuint32_t    stride;\n\t};\n\n\tstatic const UavFormat s_uavFormat[] =\n\t{\t//  BGFX_BUFFER_COMPUTE_TYPE_INT,  BGFX_BUFFER_COMPUTE_TYPE_UINT,  BGFX_BUFFER_COMPUTE_TYPE_FLOAT\n\t\t{ { DXGI_FORMAT_UNKNOWN,           DXGI_FORMAT_UNKNOWN,            DXGI_FORMAT_UNKNOWN            },  0 }, // ignored\n\t\t{ { DXGI_FORMAT_R8_SINT,           DXGI_FORMAT_R8_UINT,            DXGI_FORMAT_UNKNOWN            },  1 }, // BGFX_BUFFER_COMPUTE_FORMAT_8X1\n\t\t{ { DXGI_FORMAT_R8G8_SINT,         DXGI_FORMAT_R8G8_UINT,          DXGI_FORMAT_UNKNOWN            },  2 }, // BGFX_BUFFER_COMPUTE_FORMAT_8X2\n\t\t{ { DXGI_FORMAT_R8G8B8A8_SINT,     DXGI_FORMAT_R8G8B8A8_UINT,      DXGI_FORMAT_UNKNOWN            },  4 }, // BGFX_BUFFER_COMPUTE_FORMAT_8X4\n\t\t{ { DXGI_FORMAT_R16_SINT,          DXGI_FORMAT_R16_UINT,           DXGI_FORMAT_R16_FLOAT          },  2 }, // BGFX_BUFFER_COMPUTE_FORMAT_16X1\n\t\t{ { DXGI_FORMAT_R16G16_SINT,       DXGI_FORMAT_R16G16_UINT,        DXGI_FORMAT_R16G16_FLOAT       },  4 }, // BGFX_BUFFER_COMPUTE_FORMAT_16X2\n\t\t{ { DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_UINT,  DXGI_FORMAT_R16G16B16A16_FLOAT },  8 }, // BGFX_BUFFER_COMPUTE_FORMAT_16X4\n\t\t{ { DXGI_FORMAT_R32_SINT,          DXGI_FORMAT_R32_UINT,           DXGI_FORMAT_R32_FLOAT          },  4 }, // BGFX_BUFFER_COMPUTE_FORMAT_32X1\n\t\t{ { DXGI_FORMAT_R32G32_SINT,       DXGI_FORMAT_R32G32_UINT,        DXGI_FORMAT_R32G32_FLOAT       },  8 }, // BGFX_BUFFER_COMPUTE_FORMAT_32X2\n\t\t{ { DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_UINT,  DXGI_FORMAT_R32G32B32A32_FLOAT }, 16 }, // BGFX_BUFFER_COMPUTE_FORMAT_32X4\n\t};\n\n\tvoid BufferD3D12::create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride)\n\t{\n\t\tm_size    = _size;\n\t\tm_flags   = _flags;\n\n\t\tconst bool needUav = 0 != (_flags & (BGFX_BUFFER_COMPUTE_WRITE|BGFX_BUFFER_DRAW_INDIRECT) );\n\t\tconst bool drawIndirect = 0 != (_flags & BGFX_BUFFER_DRAW_INDIRECT);\n\t\tm_dynamic = NULL == _data || needUav;\n\n\t\tDXGI_FORMAT format;\n\t\tuint32_t    stride;\n\n\t\tuint32_t flags = needUav\n\t\t\t? D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS\n\t\t\t: D3D12_RESOURCE_FLAG_NONE\n\t\t\t;\n\n\t\tif (drawIndirect)\n\t\t{\n#if BX_PLATFORM_XBOXONE\n\t\t\tflags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER;\n#endif // BX_PLATFORM_XBOXONE\n\t\t\tformat = _vertex ? DXGI_FORMAT_R32G32B32A32_UINT : DXGI_FORMAT_R32_UINT;\n\t\t\tstride = _vertex ? 16 : 4;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tuint32_t uavFormat = (_flags & BGFX_BUFFER_COMPUTE_FORMAT_MASK) >> BGFX_BUFFER_COMPUTE_FORMAT_SHIFT;\n\t\t\tif (0 == uavFormat)\n\t\t\t{\n\t\t\t\tif (_vertex)\n\t\t\t\t{\n\t\t\t\t\tformat = DXGI_FORMAT_R32G32B32A32_FLOAT;\n\t\t\t\t\tstride = 16;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (0 == (_flags & BGFX_BUFFER_INDEX32) )\n\t\t\t\t\t{\n\t\t\t\t\t\tformat = DXGI_FORMAT_R16_UINT;\n\t\t\t\t\t\tstride = 2;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tformat = DXGI_FORMAT_R32_UINT;\n\t\t\t\t\t\tstride = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconst uint32_t uavType = bx::uint32_satsub( (_flags & BGFX_BUFFER_COMPUTE_TYPE_MASK) >> BGFX_BUFFER_COMPUTE_TYPE_SHIFT, 1);\n\t\t\t\tformat = s_uavFormat[uavFormat].format[uavType];\n\t\t\t\tstride = s_uavFormat[uavFormat].stride;\n\t\t\t}\n\t\t}\n\n\t\tstride = 0 == _stride ? stride : _stride;\n\n\t\tm_srvd.Format                      = format;\n\t\tm_srvd.ViewDimension               = D3D12_SRV_DIMENSION_BUFFER;\n\t\tm_srvd.Shader4ComponentMapping     = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;\n\t\tm_srvd.Buffer.FirstElement         = 0;\n\t\tm_srvd.Buffer.NumElements          = m_size / stride;\n\t\tm_srvd.Buffer.StructureByteStride  = 0;\n\t\tm_srvd.Buffer.Flags                = D3D12_BUFFER_SRV_FLAG_NONE;\n\n\t\tm_uavd.Format                      = format;\n\t\tm_uavd.ViewDimension               = D3D12_UAV_DIMENSION_BUFFER;\n\t\tm_uavd.Buffer.FirstElement         = 0;\n\t\tm_uavd.Buffer.NumElements          = m_size / stride;\n\t\tm_uavd.Buffer.StructureByteStride  = 0;\n\t\tm_uavd.Buffer.CounterOffsetInBytes = 0;\n\t\tm_uavd.Buffer.Flags                = D3D12_BUFFER_UAV_FLAG_NONE;\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;\n\n\t\tm_ptr   = createCommittedResource(device, HeapProperty::Default, _size, D3D12_RESOURCE_FLAGS(flags) );\n\t\tm_gpuVA = m_ptr->GetGPUVirtualAddress();\n\t\tsetState(commandList, drawIndirect\n\t\t\t? D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT\n\t\t\t: D3D12_RESOURCE_STATE_GENERIC_READ\n\t\t\t);\n\n\t\tif (!m_dynamic)\n\t\t{\n\t\t\tupdate(commandList, 0, _size, _data);\n\t\t}\n\t}\n\n\tvoid BufferD3D12::update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool /*_discard*/)\n\t{\n\t\tID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, _size);\n\t\tuint8_t* data;\n\n\t\tD3D12_RANGE readRange = { 0, 0 };\n\t\tDX_CHECK(staging->Map(0, &readRange, (void**)&data) );\n\t\tbx::memCopy(data, _data, _size);\n\t\tD3D12_RANGE writeRange = { 0, _size };\n\t\tstaging->Unmap(0, &writeRange);\n\n\t\tD3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST);\n\t\t_commandList->CopyBufferRegion(m_ptr, _offset, staging, 0, _size);\n\t\tsetState(_commandList, state);\n\n\t\ts_renderD3D12->m_cmd.release(staging);\n\t}\n\n\tvoid BufferD3D12::destroy()\n\t{\n\t\tif (NULL != m_ptr)\n\t\t{\n\t\t\ts_renderD3D12->m_cmd.release(m_ptr);\n\t\t\tm_dynamic = false;\n\t\t\tm_state   = D3D12_RESOURCE_STATE_COMMON;\n\t\t}\n\t}\n\n\tD3D12_RESOURCE_STATES BufferD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)\n\t{\n\t\tif (m_state != _state)\n\t\t{\n\t\t\tsetResourceBarrier(_commandList\n\t\t\t\t, m_ptr\n\t\t\t\t, m_state\n\t\t\t\t, _state\n\t\t\t\t);\n\n\t\t\tbx::swap(m_state, _state);\n\t\t}\n\n\t\treturn _state;\n\t}\n\n\tvoid VertexBufferD3D12::create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle, uint16_t _flags)\n\t{\n\t\tBufferD3D12::create(_size, _data, _flags, true);\n\t\tm_layoutHandle = _layoutHandle;\n\t}\n\n\tvoid ShaderD3D12::create(const Memory* _mem)\n\t{\n\t\tbx::MemoryReader reader(_mem->data, _mem->size);\n\n\t\tbx::ErrorAssert err;\n\n\t\tuint32_t magic;\n\t\tbx::read(&reader, magic, &err);\n\n\t\tconst bool fragment = isShaderType(magic, \'F\');\n\n\t\tuint32_t hashIn;\n\t\tbx::read(&reader, hashIn, &err);\n\n\t\tuint32_t hashOut;\n\n\t\tif (isShaderVerLess(magic, 6) )\n\t\t{\n\t\t\thashOut = hashIn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbx::read(&reader, hashOut, &err);\n\t\t}\n\n\t\tuint16_t count;\n\t\tbx::read(&reader, count, &err);\n\n\t\tm_numPredefined = 0;\n\t\tm_numUniforms = count;\n\n\t\tBX_TRACE("%s Shader consts %d"\n\t\t\t, getShaderTypeName(magic)\n\t\t\t, count\n\t\t\t);\n\n\t\tuint8_t fragmentBit = fragment ? kUniformFragmentBit : 0;\n\n\t\tif (0 < count)\n\t\t{\n\t\t\tfor (uint32_t ii = 0; ii < count; ++ii)\n\t\t\t{\n\t\t\t\tuint8_t nameSize = 0;\n\t\t\t\tbx::read(&reader, nameSize, &err);\n\n\t\t\t\tchar name[256] = {};\n\t\t\t\tbx::read(&reader, &name, nameSize, &err);\n\t\t\t\tname[nameSize] = \'\\0\';\n\n\t\t\t\tuint8_t type = 0;\n\t\t\t\tbx::read(&reader, type, &err);\n\n\t\t\t\tuint8_t num = 0;\n\t\t\t\tbx::read(&reader, num, &err);\n\n\t\t\t\tuint16_t regIndex = 0;\n\t\t\t\tbx::read(&reader, regIndex, &err);\n\n\t\t\t\tuint16_t regCount = 0;\n\t\t\t\tbx::read(&reader, regCount, &err);\n\n\t\t\t\tif (!isShaderVerLess(magic, 8) )\n\t\t\t\t{\n\t\t\t\t\tuint16_t texInfo = 0;\n\t\t\t\t\tbx::read(&reader, texInfo, &err);\n\t\t\t\t}\n\n\t\t\t\tif (!isShaderVerLess(magic, 10) )\n\t\t\t\t{\n\t\t\t\t\tuint16_t texFormat = 0;\n\t\t\t\t\tbx::read(&reader, texFormat, &err);\n\t\t\t\t}\n\n\t\t\t\tconst char* kind = "invalid";\n\n\t\t\t\tPredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);\n\t\t\t\tif (PredefinedUniform::Count != predefined)\n\t\t\t\t{\n\t\t\t\t\tkind = "predefined";\n\t\t\t\t\tm_predefined[m_numPredefined].m_loc   = regIndex;\n\t\t\t\t\tm_predefined[m_numPredefined].m_count = regCount;\n\t\t\t\t\tm_predefined[m_numPredefined].m_type  = uint8_t(predefined|fragmentBit);\n\t\t\t\t\tm_numPredefined++;\n\t\t\t\t}\n\t\t\t\telse if (0 == (kUniformSamplerBit & type) )\n\t\t\t\t{\n\t\t\t\t\tconst UniformRegInfo* info = s_renderD3D12->m_uniformReg.find(name);\n\t\t\t\t\tBX_WARN(NULL != info, "User defined uniform \'%s\' is not found, it won\'t be set.", name);\n\n\t\t\t\t\tif (NULL != info)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (NULL == m_constantBuffer)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_constantBuffer = UniformBuffer::create(1024);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tkind = "user";\n\t\t\t\t\t\tm_constantBuffer->writeUniformHandle( (UniformType::Enum)(type|fragmentBit), regIndex, info->m_handle, regCount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tkind = "sampler";\n\t\t\t\t}\n\n\t\t\t\tBX_TRACE("\\t%s: %s (%s), num %2d, r.index %3d, r.count %2d"\n\t\t\t\t\t, kind\n\t\t\t\t\t, name\n\t\t\t\t\t, getUniformTypeName(UniformType::Enum(type&~kUniformMask) )\n\t\t\t\t\t, num\n\t\t\t\t\t, regIndex\n\t\t\t\t\t, regCount\n\t\t\t\t\t);\n\t\t\t\tBX_UNUSED(kind);\n\t\t\t}\n\n\t\t\tif (NULL != m_constantBuffer)\n\t\t\t{\n\t\t\t\tm_constantBuffer->finish();\n\t\t\t}\n\t\t}\n\n\t\tuint32_t shaderSize;\n\t\tbx::read(&reader, shaderSize, &err);\n\n\t\tconst void* code = reader.getDataPtr();\n\t\tbx::skip(&reader, shaderSize+1);\n\n\t\tm_code = copy(code, shaderSize);\n\n\t\tuint8_t numAttrs = 0;\n\t\tbx::read(&reader, numAttrs, &err);\n\n\t\tbx::memSet(m_attrMask, 0, sizeof(m_attrMask) );\n\n\t\tfor (uint32_t ii = 0; ii < numAttrs; ++ii)\n\t\t{\n\t\t\tuint16_t id;\n\t\t\tbx::read(&reader, id, &err);\n\n\t\t\tAttrib::Enum attr = idToAttrib(id);\n\n\t\t\tif (Attrib::Count != attr)\n\t\t\t{\n\t\t\t\tm_attrMask[attr] = UINT16_MAX;\n\t\t\t}\n\t\t}\n\n\t\tbx::HashMurmur2A murmur;\n\t\tmurmur.begin();\n\t\tmurmur.add(hashIn);\n\t\tmurmur.add(hashOut);\n\t\tmurmur.add(code, shaderSize);\n\t\tmurmur.add(numAttrs);\n\t\tmurmur.add(m_attrMask, numAttrs);\n\t\tm_hash = murmur.end();\n\n\t\tbx::read(&reader, m_size, &err);\n\t}\n\n\tstatic void memcpySubresource(\n\t\t  const D3D12_MEMCPY_DEST* _dst\n\t\t, const D3D12_SUBRESOURCE_DATA* _src\n\t\t, uint64_t _rowSizeInBytes\n\t\t, uint32_t _numRows\n\t\t, uint32_t _numSlices\n\t\t)\n\t{\n\t\tfor (uint32_t zz = 0; zz < _numSlices; ++zz)\n\t\t{\n\t\t\t      uint8_t* _dstSlice = (      uint8_t*)(_dst->pData) + _dst->SlicePitch * zz;\n\t\t\tconst uint8_t* _srcSlice = (const uint8_t*)(_src->pData) + _src->SlicePitch * zz;\n\t\t\tfor (uint32_t yy = 0; yy < _numRows; ++yy)\n\t\t\t{\n\t\t\t\tbx::memCopy(\n\t\t\t\t\t  _dstSlice + _dst->RowPitch * yy\n\t\t\t\t\t, _srcSlice + _src->RowPitch * yy\n\t\t\t\t\t, size_t(_rowSizeInBytes)\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic uint64_t updateSubresources(\n\t\t  ID3D12GraphicsCommandList* _commandList\n\t\t, ID3D12Resource* _dstResource\n\t\t, ID3D12Resource* _intermediate\n\t\t, uint32_t _firstSubresource\n\t\t, uint32_t _numSubresources\n\t\t, uint64_t _requiredSize\n\t\t, const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* _layouts\n\t\t, const uint32_t* _numRows\n\t\t, const uint64_t* _rowSizesInBytes\n\t\t, const D3D12_SUBRESOURCE_DATA* _srcData\n\t\t)\n\t{\n\t\tuint8_t* data;\n\t\tDX_CHECK(_intermediate->Map(0, NULL, (void**)&data) );\n\n\t\tfor (uint32_t ii = 0; ii < _numSubresources; ++ii)\n\t\t{\n\t\t\tD3D12_MEMCPY_DEST dstData =\n\t\t\t{\n\t\t\t\tdata + _layouts[ii].Offset,\n\t\t\t\t_layouts[ii].Footprint.RowPitch,\n\t\t\t\t_layouts[ii].Footprint.RowPitch * _numRows[ii],\n\t\t\t};\n\n\t\t\tmemcpySubresource(\n\t\t\t\t  &dstData\n\t\t\t\t, &_srcData[ii]\n\t\t\t\t, _rowSizesInBytes[ii]\n\t\t\t\t, _numRows[ii]\n\t\t\t\t, _layouts[ii].Footprint.Depth\n\t\t\t\t);\n\t\t}\n\n\t\t_intermediate->Unmap(0, NULL);\n\n\t\tD3D12_RESOURCE_DESC dstDesc = getResourceDesc(_dstResource);\n\t\tif (dstDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)\n\t\t{\n\t\t\t_commandList->CopyBufferRegion(\n\t\t\t\t  _dstResource\n\t\t\t\t, 0\n\t\t\t\t, _intermediate\n\t\t\t\t, _layouts[0].Offset\n\t\t\t\t, _layouts[0].Footprint.Width\n\t\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (uint32_t i = 0; i < _numSubresources; ++i)\n\t\t\t{\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION src;\n\t\t\t\tsrc.pResource        = _intermediate;\n\t\t\t\tsrc.Type             = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;\n\t\t\t\tsrc.PlacedFootprint  = _layouts[i];\n\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION dst;\n\t\t\t\tdst.pResource        = _dstResource;\n\t\t\t\tdst.Type             = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\n\t\t\t\tdst.SubresourceIndex = i + _firstSubresource;\n\n\t\t\t\t_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);\n\t\t\t}\n\t\t}\n\n\t\treturn _requiredSize;\n\t}\n\n\tstatic uint64_t updateSubresources(\n\t\t  ID3D12GraphicsCommandList* _commandList\n\t\t, ID3D12Resource* _dstResource\n\t\t, ID3D12Resource* _intermediate\n\t\t, uint64_t _intermediateOffset\n\t\t, uint32_t _firstSubresource\n\t\t, uint32_t _numSubresources\n\t\t, D3D12_SUBRESOURCE_DATA* _srcData\n\t\t)\n\t{\n\t\tuint64_t requiredSize = 0;\n\n\t\tconst size_t sizeInBytes = size_t(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(uint32_t) + sizeof(uint64_t) ) * _numSubresources;\n\t\tD3D12_PLACED_SUBRESOURCE_FOOTPRINT* layouts = (D3D12_PLACED_SUBRESOURCE_FOOTPRINT*)BX_ALLOC(g_allocator, sizeInBytes);\n\t\tuint64_t* rowSizesInBytes = (uint64_t*)(layouts + _numSubresources);\n\t\tuint32_t* numRows         = (uint32_t*)(rowSizesInBytes + _numSubresources);\n\n\t\tD3D12_RESOURCE_DESC desc = getResourceDesc(_dstResource);\n\t\ts_renderD3D12->m_device->GetCopyableFootprints(\n\t\t\t  &desc\n\t\t\t, _firstSubresource\n\t\t\t, _numSubresources\n\t\t\t, _intermediateOffset\n\t\t\t, layouts\n\t\t\t, numRows\n\t\t\t, rowSizesInBytes\n\t\t\t, &requiredSize\n\t\t\t);\n\n\t\tconst uint64_t result = updateSubresources(\n\t\t\t  _commandList\n\t\t\t, _dstResource\n\t\t\t, _intermediate\n\t\t\t, _firstSubresource\n\t\t\t, _numSubresources\n\t\t\t, requiredSize\n\t\t\t, layouts\n\t\t\t, numRows\n\t\t\t, rowSizesInBytes\n\t\t\t, _srcData\n\t\t\t);\n\n\t\tBX_FREE(g_allocator, layouts);\n\n\t\treturn result;\n\t}\n\n\tvoid* TextureD3D12::create(const Memory* _mem, uint64_t _flags, uint8_t _skip)\n\t{\n\t\tbimg::ImageContainer imageContainer;\n\n\t\tif (bimg::imageParse(imageContainer, _mem->data, _mem->size) )\n\t\t{\n\t\t\tconst bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(imageContainer.m_format);\n\t\t\tconst uint8_t startLod = bx::min<uint8_t>(_skip, imageContainer.m_numMips-1);\n\n\t\t\tbimg::TextureInfo ti;\n\t\t\tbimg::imageGetSize(\n\t\t\t\t  &ti\n\t\t\t\t, uint16_t(imageContainer.m_width >>startLod)\n\t\t\t\t, uint16_t(imageContainer.m_height>>startLod)\n\t\t\t\t, uint16_t(imageContainer.m_depth >>startLod)\n\t\t\t\t, imageContainer.m_cubeMap\n\t\t\t\t, 1 < imageContainer.m_numMips\n\t\t\t\t, imageContainer.m_numLayers\n\t\t\t\t, imageContainer.m_format\n\t\t\t\t);\n\t\t\tti.numMips = bx::min<uint8_t>(imageContainer.m_numMips-startLod, ti.numMips);\n\n\t\t\tm_flags     = _flags;\n\t\t\tm_width     = ti.width;\n\t\t\tm_height    = ti.height;\n\t\t\tm_depth     = ti.depth;\n\t\t\tm_numLayers = ti.numLayers;\n\t\t\tm_requestedFormat  = uint8_t(imageContainer.m_format);\n\t\t\tm_textureFormat    = uint8_t(getViableTextureFormat(imageContainer) );\n\t\t\tconst bool convert = m_textureFormat != m_requestedFormat;\n\t\t\tconst uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) );\n\n\t\t\tif (imageContainer.m_cubeMap)\n\t\t\t{\n\t\t\t\tm_type = TextureCube;\n\t\t\t}\n\t\t\telse if (imageContainer.m_depth > 1)\n\t\t\t{\n\t\t\t\tm_type = Texture3D;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_type = Texture2D;\n\t\t\t}\n\n\t\t\tm_numMips = ti.numMips;\n\t\t\tconst uint16_t numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1);\n\t\t\tconst uint32_t numSrd   = numSides * ti.numMips;\n\t\t\tD3D12_SUBRESOURCE_DATA* srd = (D3D12_SUBRESOURCE_DATA*)alloca(numSrd*sizeof(D3D12_SUBRESOURCE_DATA) );\n\n\t\t\tuint32_t kk = 0;\n\n\t\t\tconst bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) );\n\t\t\tconst bool swizzle    = TextureFormat::BGRA8 == m_textureFormat && 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE);\n\n\t\t\tconst bool writeOnly    = 0 != (m_flags&BGFX_TEXTURE_RT_WRITE_ONLY);\n\t\t\tconst bool computeWrite = 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE);\n\t\t\tconst bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK);\n\t\t\tconst bool blit         = 0 != (m_flags&BGFX_TEXTURE_BLIT_DST);\n\n\t\t\tconst uint32_t msaaQuality = bx::uint32_satsub((m_flags & BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT, 1);\n\t\t\tconst DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality];\n\n\t\t\tconst bool needResolve = true\n\t\t\t\t&& 1 < msaa.Count\n\t\t\t\t&& 0 == (m_flags & BGFX_TEXTURE_MSAA_SAMPLE)\n\t\t\t\t&& !writeOnly\n\t\t\t\t;\n\n\t\t\tBX_TRACE("Texture %3d: %s (requested: %s), %dx%d%s RT[%c], BO[%c], CW[%c]%s."\n\t\t\t\t, this - s_renderD3D12->m_textures\n\t\t\t\t, getName( (TextureFormat::Enum)m_textureFormat)\n\t\t\t\t, getName( (TextureFormat::Enum)m_requestedFormat)\n\t\t\t\t, ti.width\n\t\t\t\t, ti.height\n\t\t\t\t, imageContainer.m_cubeMap ? "x6" : ""\n\t\t\t\t, renderTarget ? \'x\' : \' \'\n\t\t\t\t, writeOnly    ? \'x\' : \' \'\n\t\t\t\t, computeWrite ? \'x\' : \' \'\n\t\t\t\t, swizzle ? " (swizzle BGRA8 -> RGBA8)" : ""\n\t\t\t\t);\n\n\t\t\tfor (uint8_t side = 0; side < numSides; ++side)\n\t\t\t{\n\t\t\t\tfor (uint8_t lod = 0; lod < ti.numMips; ++lod)\n\t\t\t\t{\n\t\t\t\t\tbimg::ImageMip mip;\n\t\t\t\t\tif (bimg::imageGetRawData(imageContainer, side, lod+startLod, _mem->data, _mem->size, mip) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif (convert)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst uint32_t pitch = bx::strideAlign(bx::max<uint32_t>(mip.m_width,  4)*bpp/8, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);\n\t\t\t\t\t\t\tconst uint32_t slice = bx::strideAlign(bx::max<uint32_t>(mip.m_height, 4)*pitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);\n\t\t\t\t\t\t\tconst uint32_t size  = slice*mip.m_depth;\n\n\t\t\t\t\t\t\tuint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size);\n\t\t\t\t\t\t\tbimg::imageDecodeToBgra8(\n\t\t\t\t\t\t\t\t  g_allocator\n\t\t\t\t\t\t\t\t, temp\n\t\t\t\t\t\t\t\t, mip.m_data\n\t\t\t\t\t\t\t\t, mip.m_width\n\t\t\t\t\t\t\t\t, mip.m_height\n\t\t\t\t\t\t\t\t, pitch\n\t\t\t\t\t\t\t\t, mip.m_format\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tsrd[kk].pData      = temp;\n\t\t\t\t\t\t\tsrd[kk].RowPitch   = pitch;\n\t\t\t\t\t\t\tsrd[kk].SlicePitch = slice;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (compressed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst uint32_t pitch = bx::strideAlign( (mip.m_width /blockInfo.blockWidth )*mip.m_blockSize, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);\n\t\t\t\t\t\t\tconst uint32_t slice = bx::strideAlign( (mip.m_height/blockInfo.blockHeight)*pitch,           D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);\n\t\t\t\t\t\t\tconst uint32_t size  = slice*mip.m_depth;\n\n\t\t\t\t\t\t\tuint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size);\n\t\t\t\t\t\t\tbimg::imageCopy(temp\n\t\t\t\t\t\t\t\t\t,  mip.m_height/blockInfo.blockHeight\n\t\t\t\t\t\t\t\t\t, (mip.m_width /blockInfo.blockWidth )*mip.m_blockSize\n\t\t\t\t\t\t\t\t\t, mip.m_depth\n\t\t\t\t\t\t\t\t\t, mip.m_data\n\t\t\t\t\t\t\t\t\t, pitch\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tsrd[kk].pData      = temp;\n\t\t\t\t\t\t\tsrd[kk].RowPitch   = pitch;\n\t\t\t\t\t\t\tsrd[kk].SlicePitch = slice;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst uint32_t pitch = bx::strideAlign(mip.m_width*mip.m_bpp / 8, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);\n\t\t\t\t\t\t\tconst uint32_t slice = bx::strideAlign(mip.m_height*pitch,        D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);\n\n\t\t\t\t\t\t\tuint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, slice*mip.m_depth);\n\t\t\t\t\t\t\tbimg::imageCopy(temp\n\t\t\t\t\t\t\t\t\t, mip.m_height\n\t\t\t\t\t\t\t\t\t, mip.m_width*mip.m_bpp/8\n\t\t\t\t\t\t\t\t\t, mip.m_depth\n\t\t\t\t\t\t\t\t\t, mip.m_data\n\t\t\t\t\t\t\t\t\t, pitch\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tsrd[kk].pData = temp;\n\t\t\t\t\t\t\tsrd[kk].RowPitch   = pitch;\n\t\t\t\t\t\t\tsrd[kk].SlicePitch = slice;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t++kk;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst TextureFormatInfo& tfi = s_textureFormat[m_textureFormat];\n\t\t\tbx::memSet(&m_srvd, 0, sizeof(m_srvd) );\n\t\t\tm_srvd.Shader4ComponentMapping = tfi.m_mapping;\n\t\t\tm_srvd.Format = (m_flags & BGFX_TEXTURE_SRGB) ? tfi.m_fmtSrgb : tfi.m_fmtSrv;\n\t\t\tm_uavd.Format = tfi.m_fmtSrv;\n\t\t\tDXGI_FORMAT format = tfi.m_fmt;\n\t\t\tif (swizzle)\n\t\t\t{\n\t\t\t\tformat        = DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t\tm_srvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t\tm_uavd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;\n\t\t\t}\n\n\t\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\t\tID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;\n\n\t\t\tD3D12_RESOURCE_DESC resourceDesc;\n\t\t\tresourceDesc.Alignment  = 1 < msaa.Count ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : 0;\n\t\t\tresourceDesc.Width      = ti.width;\n\t\t\tresourceDesc.Height     = ti.height;\n\t\t\tresourceDesc.MipLevels  = ti.numMips;\n\t\t\tresourceDesc.Format     = format;\n\t\t\tresourceDesc.SampleDesc = msaa;\n\t\t\tresourceDesc.Layout     = D3D12_TEXTURE_LAYOUT_UNKNOWN;\n\t\t\tresourceDesc.Flags      = D3D12_RESOURCE_FLAG_NONE;\n\t\t\tresourceDesc.DepthOrArraySize = numSides;\n\t\t\tD3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;\n\n\t\t\tD3D12_CLEAR_VALUE* clearValue = NULL;\n\t\t\tif (bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) ) )\n\t\t\t{\n\t\t\t\tresourceDesc.Format = tfi.m_fmt;\n\t\t\t\tresourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;\n\t\t\t\tstate              |= D3D12_RESOURCE_STATE_DEPTH_WRITE;\n\t\t\t\tstate              &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;\n\n\t\t\t\tclearValue = (D3D12_CLEAR_VALUE*)alloca(sizeof(D3D12_CLEAR_VALUE) );\n\t\t\t\tclearValue->Format = tfi.m_fmtDsv;\n\t\t\t\tclearValue->DepthStencil.Depth   = 1.0f;\n\t\t\t\tclearValue->DepthStencil.Stencil = 0;\n\t\t\t}\n\t\t\telse if (renderTarget)\n\t\t\t{\n\t\t\t\tresourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;\n\t\t\t\tstate              |= D3D12_RESOURCE_STATE_RENDER_TARGET;\n\t\t\t\tstate              &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;\n\n\t\t\t\tclearValue = (D3D12_CLEAR_VALUE*)alloca(sizeof(D3D12_CLEAR_VALUE) );\n\t\t\t\tclearValue->Format = resourceDesc.Format;\n\t\t\t\tclearValue->Color[0] = 0.0f;\n\t\t\t\tclearValue->Color[1] = 0.0f;\n\t\t\t\tclearValue->Color[2] = 0.0f;\n\t\t\t\tclearValue->Color[3] = 0.0f;\n\t\t\t}\n\n\t\t\tif (writeOnly)\n\t\t\t{\n\t\t\t\tresourceDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;\n\t\t\t\tstate              &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;\n\t\t\t}\n\n\t\t\tif (computeWrite)\n\t\t\t{\n\t\t\t\tresourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;\n\t\t\t}\n\n\t\t\tif (blit)\n\t\t\t{\n\t\t\t\tstate = D3D12_RESOURCE_STATE_COPY_DEST;\n\t\t\t}\n\n\t\t\tconst bool directAccess = s_renderD3D12->m_directAccessSupport\n\t\t\t\t&& !renderTarget\n//\t\t\t\t&& !readBack\n\t\t\t\t&& !blit\n\t\t\t\t&& !writeOnly\n\t\t\t\t;\n\n\t\t\tswitch (m_type)\n\t\t\t{\n\t\t\tcase Texture2D:\n\t\t\t\tresourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\n\n\t\t\t\tif (1 < ti.numLayers)\n\t\t\t\t{\n\t\t\t\t\tif (1 < msaa.Count && !needResolve)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\tm_srvd.Texture2DMSArray.FirstArraySlice = 0;\n\t\t\t\t\t\tm_srvd.Texture2DMSArray.ArraySize       = ti.numLayers;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\t\tm_srvd.Texture2DArray.MostDetailedMip     = 0;\n\t\t\t\t\t\tm_srvd.Texture2DArray.MipLevels           = ti.numMips;\n\t\t\t\t\t\tm_srvd.Texture2DArray.FirstArraySlice     = 0;\n\t\t\t\t\t\tm_srvd.Texture2DArray.ArraySize           = ti.numLayers;\n\t\t\t\t\t\tm_srvd.Texture2DArray.PlaneSlice          = 0;\n\t\t\t\t\t\tm_srvd.Texture2DArray.ResourceMinLODClamp = 0.0f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (1 < msaa.Count && !needResolve)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;\n\t\t\t\t\t\tm_srvd.Texture2D.MostDetailedMip     = 0;\n\t\t\t\t\t\tm_srvd.Texture2D.MipLevels           = ti.numMips;\n\t\t\t\t\t\tm_srvd.Texture2D.PlaneSlice          = 0;\n\t\t\t\t\t\tm_srvd.Texture2D.ResourceMinLODClamp = 0.0f;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (1 < ti.numLayers)\n\t\t\t\t{\n\t\t\t\t\tm_uavd.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\tm_uavd.Texture2DArray.MipSlice        = 0;\n\t\t\t\t\tm_uavd.Texture2DArray.FirstArraySlice = 0;\n\t\t\t\t\tm_uavd.Texture2DArray.ArraySize       = ti.numLayers;\n\t\t\t\t\tm_uavd.Texture2DArray.PlaneSlice      = 0;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_uavd.ViewDimension        = D3D12_UAV_DIMENSION_TEXTURE2D;\n\t\t\t\t\tm_uavd.Texture2D.MipSlice   = 0;\n\t\t\t\t\tm_uavd.Texture2D.PlaneSlice = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Texture3D:\n\t\t\t\tresourceDesc.Dimension        = D3D12_RESOURCE_DIMENSION_TEXTURE3D;\n\t\t\t\tresourceDesc.DepthOrArraySize = uint16_t(m_depth);\n\t\t\t\tm_srvd.ViewDimension                 = D3D12_SRV_DIMENSION_TEXTURE3D;\n\t\t\t\tm_srvd.Texture3D.MostDetailedMip     = 0;\n\t\t\t\tm_srvd.Texture3D.MipLevels           = ti.numMips;\n\t\t\t\tm_srvd.Texture3D.ResourceMinLODClamp = 0.0f;\n\n\t\t\t\tm_uavd.ViewDimension         = D3D12_UAV_DIMENSION_TEXTURE3D;\n\t\t\t\tm_uavd.Texture3D.MipSlice    = 0;\n\t\t\t\tm_uavd.Texture3D.FirstWSlice = 0;\n\t\t\t\tm_uavd.Texture3D.WSize       = m_depth;\n\t\t\t\tbreak;\n\n\t\t\tcase TextureCube:\n\t\t\t\tresourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;\n\n\t\t\t\tif (1 < ti.numLayers)\n\t\t\t\t{\n\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;\n\t\t\t\t\tm_srvd.TextureCubeArray.MostDetailedMip     = 0;\n\t\t\t\t\tm_srvd.TextureCubeArray.MipLevels           = ti.numMips;\n\t\t\t\t\tm_srvd.TextureCubeArray.ResourceMinLODClamp = 0.0f;\n\t\t\t\t\tm_srvd.TextureCubeArray.NumCubes            = ti.numLayers;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;\n\t\t\t\t\tm_srvd.TextureCube.MostDetailedMip     = 0;\n\t\t\t\t\tm_srvd.TextureCube.MipLevels           = ti.numMips;\n\t\t\t\t\tm_srvd.TextureCube.ResourceMinLODClamp = 0.0f;\n\t\t\t\t}\n\n\t\t\t\tm_uavd.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\tm_uavd.Texture2DArray.MipSlice        = 0;\n\t\t\t\tm_uavd.Texture2DArray.FirstArraySlice = 0;\n\t\t\t\tm_uavd.Texture2DArray.ArraySize       = 6;\n\t\t\t\tm_uavd.Texture2DArray.PlaneSlice      = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tm_ptr = createCommittedResource(device, HeapProperty::Texture, &resourceDesc, clearValue, renderTarget);\n\n\t\t\tif (directAccess)\n\t\t\t{\n\t\t\t\tDX_CHECK(m_ptr->Map(0, NULL, &m_directAccessPtr) );\n\t\t\t}\n\n\t\t\tif (kk != 0)\n\t\t\t{\n\t\t\t\tuint64_t uploadBufferSize;\n\t\t\t\tdevice->GetCopyableFootprints(&resourceDesc, 0, numSrd, 0, NULL, NULL, NULL, &uploadBufferSize);\n\n\t\t\t\tID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, uint32_t(uploadBufferSize) );\n\n\t\t\t\tsetState(commandList, D3D12_RESOURCE_STATE_COPY_DEST);\n\n\t\t\t\tuint64_t result = updateSubresources(commandList\n\t\t\t\t\t, m_ptr\n\t\t\t\t\t, staging\n\t\t\t\t\t, 0\n\t\t\t\t\t, 0\n\t\t\t\t\t, numSrd\n\t\t\t\t\t, srd\n\t\t\t\t\t);\n\t\t\t\tBX_ASSERT(0 != result, "Invalid size"); BX_UNUSED(result);\n\t\t\t\tBX_TRACE("Update subresource %" PRId64, result);\n\n\t\t\t\tsetState(commandList, state);\n\n\t\t\t\ts_renderD3D12->m_cmd.release(staging);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsetState(commandList, state);\n\t\t\t}\n\n\t\t\tif (0 != kk)\n\t\t\t{\n\t\t\t\tkk = 0;\n\t\t\t\tfor (uint8_t side = 0; side < numSides; ++side)\n\t\t\t\t{\n\t\t\t\t\tfor (uint32_t lod = 0, num = ti.numMips; lod < num; ++lod)\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_FREE(g_allocator, const_cast<void*>(srd[kk].pData) );\n\t\t\t\t\t\t++kk;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (needResolve)\n\t\t\t{\n\t\t\t\tD3D12_RESOURCE_DESC rd = resourceDesc;\n\n\t\t\t\trd.Alignment = 0;\n\t\t\t\trd.SampleDesc = s_msaa[0];\n\t\t\t\trd.Flags &= ~(D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);\n\n\t\t\t\tm_singleMsaa = createCommittedResource(device, HeapProperty::Texture, &rd, NULL);\n\n\t\t\t\tsetResourceBarrier(commandList\n\t\t\t\t\t, m_singleMsaa\n\t\t\t\t\t, D3D12_RESOURCE_STATE_COMMON\n\t\t\t\t\t, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn m_directAccessPtr;\n\t}\n\n\tvoid TextureD3D12::destroy()\n\t{\n\t\tif (NULL != m_ptr)\n\t\t{\n\t\t\tif (NULL != m_directAccessPtr)\n\t\t\t{\n\t\t\t\tD3D12_RANGE writeRange = { 0, 0 };\n\t\t\t\tm_ptr->Unmap(0, &writeRange);\n\t\t\t\tm_directAccessPtr = NULL;\n\t\t\t}\n\n\t\t\tif (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED))\n\t\t\t{\n\t\t\t\ts_renderD3D12->m_cmd.release(m_ptr);\n\t\t\t\tm_ptr   = NULL;\n\t\t\t\tm_state = D3D12_RESOURCE_STATE_COMMON;\n\n\t\t\t\tif (NULL != m_singleMsaa)\n\t\t\t\t{\n\t\t\t\t\ts_renderD3D12->m_cmd.release(m_singleMsaa);\n\t\t\t\t\tm_singleMsaa = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid TextureD3D12::overrideInternal(uintptr_t _ptr)\n\t{\n\t\tdestroy();\n\t\tm_flags |= BGFX_SAMPLER_INTERNAL_SHARED;\n\t\tm_ptr = (ID3D12Resource*)_ptr;\n\t}\n\n\tvoid 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)\n\t{\n\t\tD3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST);\n\n\t\tconst uint32_t subres = _mip + (_side * m_numMips);\n\t\tconst uint32_t bpp    = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) );\n\t\tuint32_t rectpitch    = _rect.m_width*bpp/8;\n\t\tif (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat)))\n\t\t{\n\t\t\tconst bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat));\n\t\t\trectpitch = (_rect.m_width / blockInfo.blockWidth) * blockInfo.blockSize;\n\t\t}\n\n\t\tconst uint32_t srcpitch   = UINT16_MAX == _pitch ? rectpitch : _pitch;\n\t\tconst uint32_t slicepitch = rectpitch*_rect.m_height;\n\n\t\tconst bool convert = m_textureFormat != m_requestedFormat;\n\n\t\tD3D12_BOX box;\n\t\tbox.left   = 0;\n\t\tbox.top    = 0;\n\t\tbox.right  = box.left + _rect.m_width;\n\t\tbox.bottom = box.top  + _rect.m_height;\n\n\t\tif (TextureD3D12::Texture3D == m_type)\n\t\t{\n\t\t\tbox.front = _z;\n\t\t\tbox.back  = box.front + _depth;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbox.front = 0;\n\t\t\tbox.back  = 1;\n\t\t}\n\n\t\tuint8_t* srcData = _mem->data;\n\t\tuint8_t* temp = NULL;\n\n\t\tif (convert)\n\t\t{\n\t\t\ttemp = (uint8_t*)BX_ALLOC(g_allocator, slicepitch);\n\t\t\tbimg::imageDecodeToBgra8(g_allocator, temp, srcData, _rect.m_width, _rect.m_height, srcpitch, bimg::TextureFormat::Enum(m_requestedFormat));\n\t\t\tsrcData = temp;\n\n\t\t\tbox.right  = bx::max(1u, m_width  >> _mip);\n\t\t\tbox.bottom = bx::max(1u, m_height >> _mip);\n\t\t}\n\n\t\tD3D12_RESOURCE_DESC desc = getResourceDesc(m_ptr);\n\n\t\tdesc.Width  = _rect.m_width;\n\t\tdesc.Height = _rect.m_height;\n\n\t\tuint32_t numRows;\n\t\tuint64_t totalBytes;\n\t\tD3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;\n\t\ts_renderD3D12->m_device->GetCopyableFootprints(&desc\n\t\t\t, 0\n\t\t\t, 1\n\t\t\t, 0\n\t\t\t, &layout\n\t\t\t, &numRows\n\t\t\t, NULL\n\t\t\t, &totalBytes\n\t\t\t);\n\n\t\tconst uint32_t rowPitch = layout.Footprint.RowPitch;\n\n\t\tID3D12Resource* staging = createCommittedResource(s_renderD3D12->m_device, HeapProperty::Upload, totalBytes);\n\t\tuint8_t* dstData;\n\n\t\tD3D12_RANGE readRange = { 0, 0 };\n\t\tDX_CHECK(staging->Map(0, &readRange, (void**)&dstData) );\n\n\t\tfor (uint32_t ii = 0, height = numRows; ii < height; ++ii)\n\t\t{\n\t\t\tbx::memCopy(&dstData[ii*rowPitch], &srcData[ii*srcpitch], srcpitch);\n\t\t}\n\n\t\tif (NULL != temp)\n\t\t{\n\t\t\tBX_FREE(g_allocator, temp);\n\t\t}\n\n\t\tD3D12_RANGE writeRange = { 0, numRows*rowPitch };\n\t\tstaging->Unmap(0, &writeRange);\n\n\t\tD3D12_TEXTURE_COPY_LOCATION dst = { m_ptr,   D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, {        } };\n\t\tdst.SubresourceIndex = subres;\n\t\tD3D12_TEXTURE_COPY_LOCATION src = { staging, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,  { layout } };\n\t\t_commandList->CopyTextureRegion(&dst, _rect.m_x, _rect.m_y, 0, &src, &box);\n\n\t\tsetState(_commandList, state);\n\n\t\ts_renderD3D12->m_cmd.release(staging);\n\t}\n\n\tvoid TextureD3D12::resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip)\n\t{\n\t\tBX_UNUSED(_resolve);\n\n\t\tbool needResolve = NULL != m_singleMsaa;\n\t\tif (needResolve)\n\t\t{\n\t\t\tD3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);\n\n\t\t\tsetResourceBarrier(_commandList\n\t\t\t\t, m_singleMsaa\n\t\t\t\t, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_DEST\n\t\t\t);\n\n\t\t\tfor (uint32_t ii = _layer; ii < _numLayers; ++ii)\n\t\t\t{\n\t\t\t\tconst uint32_t resource = _mip + (ii * m_numMips);\n\n\t\t\t\t_commandList->ResolveSubresource(m_singleMsaa\n\t\t\t\t\t, resource\n\t\t\t\t\t, m_ptr\n\t\t\t\t\t, resource\n\t\t\t\t\t, s_textureFormat[m_textureFormat].m_fmt\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tsetResourceBarrier(_commandList\n\t\t\t\t, m_singleMsaa\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_DEST\n\t\t\t\t, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE\n\t\t\t);\n\n\t\t\tsetState(_commandList, state);\n\t\t}\n\t}\n\n\tD3D12_RESOURCE_STATES TextureD3D12::setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state)\n\t{\n\t\tif (m_state != _state)\n\t\t{\n\t\t\tsetResourceBarrier(_commandList\n\t\t\t\t, m_ptr\n\t\t\t\t, m_state\n\t\t\t\t, _state\n\t\t\t\t);\n\n\t\t\tbx::swap(m_state, _state);\n\t\t}\n\n\t\treturn _state;\n\t}\n\n\tvoid FrameBufferD3D12::create(uint8_t _num, const Attachment* _attachment)\n\t{\n\t\tm_denseIdx = UINT16_MAX;\n\t\tm_numTh = _num;\n\t\tbx::memCopy(m_attachment, _attachment, _num*sizeof(Attachment) );\n\n\t\tpostReset();\n\t}\n\n\tvoid FrameBufferD3D12::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat)\n\t{\n\t\tBX_UNUSED(_nwh, _width, _height, _format, _depthFormat);\n\n#if BX_PLATFORM_WINDOWS\n\t\tSwapChainDesc scd;\n\t\tbx::memCopy(&scd, &s_renderD3D12->m_scd, sizeof(SwapChainDesc) );\n\t\tscd.format     = TextureFormat::Count == _format ? scd.format : s_textureFormat[_format].m_fmt;\n\t\tscd.width      = _width;\n\t\tscd.height     = _height;\n\t\tscd.nwh        = _nwh;\n\t\tscd.sampleDesc = s_msaa[0];\n\n\t\tHRESULT hr;\n\t\thr = s_renderD3D12->m_dxgi.createSwapChain(\n\t\t\t  s_renderD3D12->getDeviceForSwapChain()\n\t\t\t, scd\n\t\t\t, &m_swapChain\n\t\t\t);\n\t\tBGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain.");\n\t\tm_state = D3D12_RESOURCE_STATE_PRESENT;\n\n\t\tDX_CHECK(s_renderD3D12->m_dxgi.m_factory->MakeWindowAssociation(\n\t\t\t  (HWND)_nwh\n\t\t\t, 0\n\t\t\t| DXGI_MWA_NO_WINDOW_CHANGES\n\t\t\t| DXGI_MWA_NO_ALT_ENTER\n\t\t\t) );\n\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tFrameBufferHandle fbh = { uint16_t(this - s_renderD3D12->m_frameBuffers) };\n\n\t\tfor (uint32_t ii = 0, num = scd.bufferCount; ii < num; ++ii)\n\t\t{\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = s_renderD3D12->getRtv(fbh, uint8_t(ii) );\n\n\t\t\tID3D12Resource* colorBuffer;\n\t\t\tDX_CHECK(m_swapChain->GetBuffer(ii\n\t\t\t\t, IID_ID3D12Resource\n\t\t\t\t, (void**)&colorBuffer\n\t\t\t\t) );\n\t\t\tdevice->CreateRenderTargetView(colorBuffer, NULL, rtvHandle);\n\t\t\tDX_RELEASE(colorBuffer, 0);\n\t\t}\n#endif // BX_PLATFORM_WINDOWS\n\n\t\tm_nwh      = _nwh;\n\t\tm_denseIdx = _denseIdx;\n\t\tm_num      = 1;\n\t}\n\n\tuint16_t FrameBufferD3D12::destroy()\n\t{\n\t\tDX_RELEASE(m_swapChain, 0);\n\n\t\tm_nwh   = NULL;\n\t\tm_numTh = 0;\n\t\tm_needPresent = false;\n\n\t\tm_depth.idx = bgfx::kInvalidHandle;\n\n\t\tuint16_t denseIdx = m_denseIdx;\n\t\tm_denseIdx = UINT16_MAX;\n\n\t\treturn denseIdx;\n\t}\n\n\tHRESULT FrameBufferD3D12::present(uint32_t _syncInterval, uint32_t _flags)\n\t{\n\t\tif (m_needPresent)\n\t\t{\n\t\t\tHRESULT hr = m_swapChain->Present(_syncInterval, _flags);\n\t\t\thr = !isLost(hr) ? S_OK : hr;\n\t\t\tm_needPresent = false;\n\t\t\treturn hr;\n\t\t}\n\n\t\treturn S_OK;\n\t}\n\n\tvoid FrameBufferD3D12::preReset()\n\t{\n\t}\n\n\tvoid FrameBufferD3D12::postReset()\n\t{\n\t\tif (m_numTh != 0)\n\t\t{\n\t\t\tID3D12Device* device = s_renderD3D12->m_device;\n\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_rtvDescriptorHeap);\n\t\t\tuint32_t rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\n\t\t\tuint32_t fbhIdx = (uint32_t)(this - s_renderD3D12->m_frameBuffers);\n\t\t\trtvDescriptor.ptr += (BX_COUNTOF(s_renderD3D12->m_backBufferColor) + fbhIdx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) * rtvDescriptorSize;\n\n\t\t\tm_width  = 0;\n\t\t\tm_height = 0;\n\t\t\tm_depth.idx = bgfx::kInvalidHandle;\n\t\t\tm_num = 0;\n\t\t\tfor (uint32_t ii = 0; ii < m_numTh; ++ii)\n\t\t\t{\n\t\t\t\tconst Attachment& at = m_attachment[ii];\n\n\t\t\t\tif (isValid(at.handle) )\n\t\t\t\t{\n\t\t\t\t\tconst TextureD3D12& texture = s_renderD3D12->m_textures[at.handle.idx];\n\n\t\t\t\t\tif (0 == m_width)\n\t\t\t\t\t{\n\t\t\t\t\t\tD3D12_RESOURCE_DESC desc = getResourceDesc(texture.m_ptr);\n\t\t\t\t\t\tm_width  = uint32_t(desc.Width);\n\t\t\t\t\t\tm_height = uint32_t(desc.Height);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst uint32_t msaaQuality = bx::uint32_satsub((texture.m_flags & BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT, 1);\n\t\t\t\t\tconst DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality];\n\n\t\t\t\t\tif (bimg::isDepth(bimg::TextureFormat::Enum(texture.m_textureFormat) ) )\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_ASSERT(!isValid(m_depth), "");\n\t\t\t\t\t\tm_depth = at.handle;\n\t\t\t\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_dsvDescriptorHeap);\n\t\t\t\t\t\tuint32_t dsvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\n\t\t\t\t\t\tdsvDescriptor.ptr += (1 + fbhIdx) * dsvDescriptorSize;\n\n\t\t\t\t\t\tconst bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(texture.m_textureFormat) );\n\t\t\t\t\t\tBX_UNUSED(blockInfo);\n\n\t\t\t\t\t\tD3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;\n\t\t\t\t\t\tbx::memSet(&dsvDesc, 0, sizeof(dsvDesc) );\n\t\t\t\t\t\tdsvDesc.Format        = s_textureFormat[texture.m_textureFormat].m_fmtDsv;\n\t\t\t\t\t\tdsvDesc.Flags         = D3D12_DSV_FLAG_NONE\n// \t\t\t\t\t\t\t| (blockInfo.depthBits   > 0 ? D3D12_DSV_FLAG_READ_ONLY_DEPTH   : D3D12_DSV_FLAG_NONE)\n// \t\t\t\t\t\t\t| (blockInfo.stencilBits > 0 ? D3D12_DSV_FLAG_READ_ONLY_STENCIL : D3D12_DSV_FLAG_NONE)\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\tswitch (texture.m_type)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\tcase TextureD3D12::Texture2D:\n\t\t\t\t\t\t\tif (1 < msaa.Count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (1 < texture.m_numLayers)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2DMSArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2DMSArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (1 < texture.m_numLayers)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.MipSlice        = at.mip;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;\n\t\t\t\t\t\t\t\t\tdsvDesc.Texture2D.MipSlice   = at.mip;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TextureD3D12::TextureCube:\n\t\t\t\t\t\t\tif (1 < msaa.Count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\t\t\tdsvDesc.Texture2DMSArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\tdsvDesc.Texture2DMSArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\tdsvDesc.Texture2DArray.MipSlice        = at.mip;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdevice->CreateDepthStencilView(texture.m_ptr\n\t\t\t\t\t\t\t, &dsvDesc\n\t\t\t\t\t\t\t, dsvDescriptor\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\telse if (Access::Write == at.access)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_texture[m_num] = at.handle;\n\t\t\t\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE rtv = { rtvDescriptor.ptr + m_num * rtvDescriptorSize };\n\n\t\t\t\t\t\tD3D12_RENDER_TARGET_VIEW_DESC desc;\n\t\t\t\t\t\tdesc.Format = texture.m_srvd.Format;\n\n\t\t\t\t\t\tswitch (texture.m_type)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\tcase TextureD3D12::Texture2D:\n\t\t\t\t\t\t\tif (1 < msaa.Count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (1 < texture.m_numLayers)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DMSArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DMSArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (1 < texture.m_numLayers)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DArray.MipSlice        = at.mip;\n\t\t\t\t\t\t\t\t\tdesc.Texture2DArray.PlaneSlice      = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;\n\t\t\t\t\t\t\t\t\tdesc.Texture2D.MipSlice   = at.mip;\n\t\t\t\t\t\t\t\t\tdesc.Texture2D.PlaneSlice = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TextureD3D12::TextureCube:\n\t\t\t\t\t\t\tif (1 < msaa.Count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;\n\t\t\t\t\t\t\t\tdesc.Texture2DMSArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\tdesc.Texture2DMSArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;\n\t\t\t\t\t\t\t\tdesc.Texture2DArray.FirstArraySlice = at.layer;\n\t\t\t\t\t\t\t\tdesc.Texture2DArray.ArraySize       = at.numLayers;\n\t\t\t\t\t\t\t\tdesc.Texture2DArray.MipSlice        = at.mip;\n\t\t\t\t\t\t\t\tdesc.Texture2DArray.PlaneSlice      = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase TextureD3D12::Texture3D:\n\t\t\t\t\t\t\tdesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;\n\t\t\t\t\t\t\tdesc.Texture3D.MipSlice    = at.mip;\n\t\t\t\t\t\t\tdesc.Texture3D.FirstWSlice = at.layer;\n\t\t\t\t\t\t\tdesc.Texture3D.WSize       = at.numLayers;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdevice->CreateRenderTargetView(texture.m_ptr\n\t\t\t\t\t\t\t, &desc\n\t\t\t\t\t\t\t, rtv\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\tm_num++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tBX_ASSERT(false, "");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid FrameBufferD3D12::resolve()\n\t{\n\t\tif (0 < m_numTh)\n\t\t{\n\t\t\tfor (uint32_t ii = 0; ii < m_numTh; ++ii)\n\t\t\t{\n\t\t\t\tconst Attachment& at = m_attachment[ii];\n\n\t\t\t\tif (isValid(at.handle) )\n\t\t\t\t{\n\t\t\t\t\tTextureD3D12& texture = s_renderD3D12->m_textures[at.handle.idx];\n\t\t\t\t\ttexture.resolve(s_renderD3D12->m_commandList, at.resolve, at.layer, at.numLayers, at.mip);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid FrameBufferD3D12::clear(ID3D12GraphicsCommandList* _commandList, const Clear& _clear, const float _palette[][4], const D3D12_RECT* _rect, uint32_t _num)\n\t{\n\t\tID3D12Device* device = s_renderD3D12->m_device;\n\t\tFrameBufferHandle fbh = { (uint16_t)(this - s_renderD3D12->m_frameBuffers) };\n\t\tD3D12_CPU_DESCRIPTOR_HANDLE rtv = s_renderD3D12->getRtv(fbh);\n\t\tuint32_t rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);\n\n\t\tif (BGFX_CLEAR_COLOR & _clear.m_flags\n\t\t&&  0 != m_num)\n\t\t{\n\t\t\tif (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)\n\t\t\t{\n\t\t\t\tfor (uint32_t ii = 0, num = m_num; ii < num; ++ii)\n\t\t\t\t{\n\t\t\t\t\tuint8_t index = _clear.m_index[ii];\n\t\t\t\t\tif (UINT8_MAX != index)\n\t\t\t\t\t{\n\t\t\t\t\t\t_commandList->ClearRenderTargetView(rtv\n\t\t\t\t\t\t\t\t, _palette[index]\n\t\t\t\t\t\t\t\t, _num\n\t\t\t\t\t\t\t\t, _rect\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\trtv.ptr += rtvDescriptorSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfloat frgba[4] =\n\t\t\t\t{\n\t\t\t\t\t_clear.m_index[0]*1.0f/255.0f,\n\t\t\t\t\t_clear.m_index[1]*1.0f/255.0f,\n\t\t\t\t\t_clear.m_index[2]*1.0f/255.0f,\n\t\t\t\t\t_clear.m_index[3]*1.0f/255.0f,\n\t\t\t\t};\n\t\t\t\tfor (uint32_t ii = 0, num = m_num; ii < num; ++ii)\n\t\t\t\t{\n\t\t\t\t\t_commandList->ClearRenderTargetView(rtv\n\t\t\t\t\t\t, frgba\n\t\t\t\t\t\t, _num\n\t\t\t\t\t\t, _rect\n\t\t\t\t\t\t);\n\t\t\t\t\trtv.ptr += rtvDescriptorSize;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isValid(m_depth)\n\t\t&& (BGFX_CLEAR_DEPTH|BGFX_CLEAR_STENCIL) & _clear.m_flags)\n\t\t{\n\t\t\tD3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_dsvDescriptorHeap);\n\t\t\tuint32_t dsvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);\n\t\t\tdsvDescriptor.ptr += (1 + fbh.idx) * dsvDescriptorSize;\n\n\t\t\tDWORD flags = 0;\n\t\t\tflags |= (_clear.m_flags & BGFX_CLEAR_DEPTH)   ? D3D12_CLEAR_FLAG_DEPTH   : 0;\n\t\t\tflags |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? D3D12_CLEAR_FLAG_STENCIL : 0;\n\n\t\t\t_commandList->ClearDepthStencilView(dsvDescriptor\n\t\t\t\t, D3D12_CLEAR_FLAGS(flags)\n\t\t\t\t, _clear.m_depth\n\t\t\t\t, _clear.m_stencil\n\t\t\t\t, _num\n\t\t\t\t, _rect\n\t\t\t\t);\n\t\t}\n\t}\n\n\tD3D12_RESOURCE_STATES FrameBufferD3D12::setState(ID3D12GraphicsCommandList* _commandList, uint8_t _idx, D3D12_RESOURCE_STATES _state)\n\t{\n\t\tif (m_state != _state)\n\t\t{\n\t\t\tID3D12Resource* colorBuffer;\n\t\t\tDX_CHECK(m_swapChain->GetBuffer(_idx\n\t\t\t\t, IID_ID3D12Resource\n\t\t\t\t, (void**)&colorBuffer\n\t\t\t\t) );\n\n\t\t\tsetResourceBarrier(_commandList\n\t\t\t\t, colorBuffer\n\t\t\t\t, m_state\n\t\t\t\t, _state\n\t\t\t\t);\n\n\t\t\tDX_RELEASE(colorBuffer, 0);\n\n\t\t\tbx::swap(m_state, _state);\n\t\t}\n\n\t\treturn _state;\n\t}\n\n\tvoid TimerQueryD3D12::init()\n\t{\n\t\tD3D12_QUERY_HEAP_DESC queryHeapDesc;\n\t\tqueryHeapDesc.Count    = m_control.m_size * 2;\n\t\tqueryHeapDesc.NodeMask = 1;\n\t\tqueryHeapDesc.Type     = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;\n\t\tDX_CHECK(s_renderD3D12->m_device->CreateQueryHeap(&queryHeapDesc\n\t\t\t, IID_ID3D12QueryHeap\n\t\t\t, (void**)&m_queryHeap\n\t\t\t) );\n\n\t\tconst uint32_t size = queryHeapDesc.Count*sizeof(uint64_t);\n\t\tm_readback = createCommittedResource(s_renderD3D12->m_device\n\t\t\t, HeapProperty::ReadBack\n\t\t\t, size\n\t\t\t);\n\n\t\tDX_CHECK(s_renderD3D12->m_cmd.m_commandQueue->GetTimestampFrequency(&m_frequency) );\n\n\t\tD3D12_RANGE range = { 0, size };\n\t\tm_readback->Map(0, &range, (void**)&m_queryResult);\n\n\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii)\n\t\t{\n\t\t\tResult& result = m_result[ii];\n\t\t\tresult.reset();\n\t\t}\n\n\t\tm_control.reset();\n\t}\n\n\tvoid TimerQueryD3D12::shutdown()\n\t{\n\t\tD3D12_RANGE range = { 0, 0 };\n\t\tm_readback->Unmap(0, &range);\n\n\t\tDX_RELEASE(m_queryHeap, 0);\n\t\tDX_RELEASE(m_readback, 0);\n\t}\n\n\tuint32_t TimerQueryD3D12::begin(uint32_t _resultIdx, uint32_t _frameNum)\n\t{\n\t\twhile (0 == m_control.reserve(1) )\n\t\t{\n\t\t\tm_control.consume(1);\n\t\t}\n\n\t\tResult& result = m_result[_resultIdx];\n\t\t++result.m_pending;\n\n\t\tconst uint32_t idx = m_control.m_current;\n\t\tQuery& query = m_query[idx];\n\t\tquery.m_resultIdx = _resultIdx;\n\t\tquery.m_ready     = false;\n\t\tquery.m_frameNum  = _frameNum;\n\n\t\tID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;\n\n\t\tuint32_t offset = idx * 2 + 0;\n\t\tcommandList->EndQuery(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_TIMESTAMP\n\t\t\t, offset\n\t\t\t);\n\n\t\tm_control.commit(1);\n\n\t\treturn idx;\n\t}\n\n\tvoid TimerQueryD3D12::end(uint32_t _idx)\n\t{\n\t\tQuery& query = m_query[_idx];\n\t\tquery.m_ready = true;\n\t\tquery.m_fence = s_renderD3D12->m_cmd.m_currentFence - 1;\n\t\tuint32_t offset = _idx * 2;\n\n\t\tID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList;\n\n\t\tcommandList->EndQuery(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_TIMESTAMP\n\t\t\t, offset + 1\n\t\t\t);\n\t\tcommandList->ResolveQueryData(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_TIMESTAMP\n\t\t\t, offset\n\t\t\t, 2\n\t\t\t, m_readback\n\t\t\t, offset * sizeof(uint64_t)\n\t\t\t);\n\n\t\twhile (update() )\n\t\t{\n\t\t}\n\t}\n\n\tbool TimerQueryD3D12::update()\n\t{\n\t\tif (0 != m_control.available() )\n\t\t{\n\t\t\tuint32_t idx = m_control.m_read;\n\t\t\tQuery& query = m_query[idx];\n\n\t\t\tif (!query.m_ready)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (query.m_fence > s_renderD3D12->m_cmd.m_completedFence)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tm_control.consume(1);\n\n\t\t\tResult& result = m_result[query.m_resultIdx];\n\t\t\t--result.m_pending;\n\t\t\tresult.m_frameNum = query.m_frameNum;\n\n\t\t\tuint32_t offset = idx * 2;\n\t\t\tresult.m_begin  = m_queryResult[offset+0];\n\t\t\tresult.m_end    = m_queryResult[offset+1];\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tvoid OcclusionQueryD3D12::init()\n\t{\n\t\tD3D12_QUERY_HEAP_DESC queryHeapDesc;\n\t\tqueryHeapDesc.Count    = BX_COUNTOF(m_handle);\n\t\tqueryHeapDesc.NodeMask = 1;\n\t\tqueryHeapDesc.Type     = D3D12_QUERY_HEAP_TYPE_OCCLUSION;\n\t\tDX_CHECK(s_renderD3D12->m_device->CreateQueryHeap(&queryHeapDesc\n\t\t\t, IID_ID3D12QueryHeap\n\t\t\t, (void**)&m_queryHeap\n\t\t\t) );\n\n\t\tconst uint32_t size = BX_COUNTOF(m_handle)*sizeof(uint64_t);\n\t\tm_readback = createCommittedResource(s_renderD3D12->m_device\n\t\t\t\t\t\t, HeapProperty::ReadBack\n\t\t\t\t\t\t, size\n\t\t\t\t\t\t);\n\n\t\tD3D12_RANGE range = { 0, size };\n\t\tm_readback->Map(0, &range, (void**)&m_result);\n\t}\n\n\tvoid OcclusionQueryD3D12::shutdown()\n\t{\n\t\tD3D12_RANGE range = { 0, 0 };\n\t\tm_readback->Unmap(0, &range);\n\n\t\tDX_RELEASE(m_queryHeap, 0);\n\t\tDX_RELEASE(m_readback, 0);\n\t}\n\n\tvoid OcclusionQueryD3D12::begin(ID3D12GraphicsCommandList* _commandList, Frame* _render, OcclusionQueryHandle _handle)\n\t{\n\t\twhile (0 == m_control.reserve(1) )\n\t\t{\n\t\t\tOcclusionQueryHandle handle = m_handle[m_control.m_read];\n\t\t\tif (isValid(handle) )\n\t\t\t{\n\t\t\t\t_render->m_occlusion[handle.idx] = int32_t(m_result[handle.idx]);\n\t\t\t}\n\t\t\tm_control.consume(1);\n\t\t}\n\n\t\tm_handle[m_control.m_current] = _handle;\n\t\t_commandList->BeginQuery(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_BINARY_OCCLUSION\n\t\t\t, _handle.idx\n\t\t\t);\n\t}\n\n\tvoid OcclusionQueryD3D12::end(ID3D12GraphicsCommandList* _commandList)\n\t{\n\t\tOcclusionQueryHandle handle = m_handle[m_control.m_current];\n\t\t_commandList->EndQuery(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_BINARY_OCCLUSION\n\t\t\t, handle.idx\n\t\t\t);\n\t\t_commandList->ResolveQueryData(m_queryHeap\n\t\t\t, D3D12_QUERY_TYPE_BINARY_OCCLUSION\n\t\t\t, handle.idx\n\t\t\t, 1\n\t\t\t, m_readback\n\t\t\t, handle.idx * sizeof(uint64_t)\n\t\t\t);\n\t\tm_control.commit(1);\n\t}\n\n\tvoid OcclusionQueryD3D12::invalidate(OcclusionQueryHandle _handle)\n\t{\n\t\tconst uint32_t size = m_control.m_size;\n\n\t\tfor (uint32_t ii = 0, num = m_control.available(); ii < num; ++ii)\n\t\t{\n\t\t\tOcclusionQueryHandle& handle = m_handle[(m_control.m_read + ii) % size];\n\t\t\tif (handle.idx == _handle.idx)\n\t\t\t{\n\t\t\t\thandle.idx = bgfx::kInvalidHandle;\n\t\t\t}\n\t\t}\n\t}\n\n\tstruct Bind\n\t{\n\t\tD3D12_GPU_DESCRIPTOR_HANDLE m_srvHandle;\n\t\tuint16_t m_samplerStateIdx;\n\t};\n\n\tvoid RendererContextD3D12::submitBlit(BlitState& _bs, uint16_t _view)\n\t{\n\t\tTextureHandle currentSrc = { kInvalidHandle };\n\t\tD3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATES(UINT32_MAX);\n\n\t\twhile (_bs.hasItem(_view) )\n\t\t{\n\t\t\tconst BlitItem& blit = _bs.advance();\n\n\t\t\t      TextureD3D12& src = m_textures[blit.m_src.idx];\n\t\t\tconst TextureD3D12& dst = m_textures[blit.m_dst.idx];\n\n\t\t\tif (currentSrc.idx != blit.m_src.idx)\n\t\t\t{\n\t\t\t\tif (D3D12_RESOURCE_STATES(UINT32_MAX) != state)\n\t\t\t\t{\n\t\t\t\t\tm_textures[currentSrc.idx].setState(m_commandList, state);\n\t\t\t\t}\n\n\t\t\t\tcurrentSrc = blit.m_src.to<TextureHandle>();\n\n\t\t\t\tif (NULL != src.m_singleMsaa)\n\t\t\t\t{\n\t\t\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t\t\t, src.m_singleMsaa\n\t\t\t\t\t\t, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE\n\t\t\t\t\t\t, D3D12_RESOURCE_STATE_COPY_SOURCE\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tstate = src.setState(m_commandList, D3D12_RESOURCE_STATE_COPY_SOURCE);\n\t\t\t}\n\n\t\t\tif (TextureD3D12::Texture3D == src.m_type)\n\t\t\t{\n\t\t\t\tD3D12_BOX box;\n\t\t\t\tbox.left   = blit.m_srcX;\n\t\t\t\tbox.top    = blit.m_srcY;\n\t\t\t\tbox.front  = blit.m_srcZ;\n\t\t\t\tbox.right  = blit.m_srcX + blit.m_width;\n\t\t\t\tbox.bottom = blit.m_srcY + blit.m_height;\n\t\t\t\tbox.back   = blit.m_srcZ + bx::uint32_imax(1, blit.m_depth);\n\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION dstLocation;\n\t\t\t\tdstLocation.pResource = dst.m_ptr;\n\t\t\t\tdstLocation.Type      = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\n\t\t\t\tdstLocation.SubresourceIndex = blit.m_dstMip;\n\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION srcLocation;\n\t\t\t\tsrcLocation.pResource = src.m_ptr;\n\t\t\t\tsrcLocation.Type      = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\n\t\t\t\tsrcLocation.SubresourceIndex = blit.m_srcMip;\n\n\t\t\t\tm_commandList->CopyTextureRegion(&dstLocation\n\t\t\t\t\t, blit.m_dstX\n\t\t\t\t\t, blit.m_dstY\n\t\t\t\t\t, blit.m_dstZ\n\t\t\t\t\t, &srcLocation\n\t\t\t\t\t, &box\n\t\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tD3D12_BOX box;\n\t\t\t\tbox.left   = blit.m_srcX;\n\t\t\t\tbox.top    = blit.m_srcY;\n\t\t\t\tbox.front  = 0;\n\t\t\t\tbox.right  = blit.m_srcX + blit.m_width;\n\t\t\t\tbox.bottom = blit.m_srcY + blit.m_height;\n\t\t\t\tbox.back   = 1;\n\n\t\t\t\tconst uint32_t srcZ = TextureD3D12::TextureCube == src.m_type\n\t\t\t\t\t? blit.m_srcZ\n\t\t\t\t\t: 0\n\t\t\t\t\t;\n\t\t\t\tconst uint32_t dstZ = TextureD3D12::TextureCube == dst.m_type\n\t\t\t\t\t? blit.m_dstZ\n\t\t\t\t\t: 0\n\t\t\t\t\t;\n\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION dstLocation;\n\t\t\t\tdstLocation.pResource = dst.m_ptr;\n\t\t\t\tdstLocation.Type      = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\n\t\t\t\tdstLocation.SubresourceIndex = dstZ*dst.m_numMips+blit.m_dstMip;\n\n\t\t\t\tD3D12_TEXTURE_COPY_LOCATION srcLocation;\n\t\t\t\tsrcLocation.pResource = NULL != src.m_singleMsaa ? src.m_singleMsaa : src.m_ptr;\n\t\t\t\tsrcLocation.Type      = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;\n\t\t\t\tsrcLocation.SubresourceIndex = srcZ*src.m_numMips+blit.m_srcMip;\n\n\t\t\t\tconst bool depthStencil = bimg::isDepth(bimg::TextureFormat::Enum(src.m_textureFormat) );\n\n\t\t\t\tm_commandList->CopyTextureRegion(\n\t\t\t\t\t  &dstLocation\n\t\t\t\t\t, blit.m_dstX\n\t\t\t\t\t, blit.m_dstY\n\t\t\t\t\t, 0\n\t\t\t\t\t, &srcLocation\n\t\t\t\t\t, depthStencil ? NULL : &box\n\t\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (NULL != src.m_singleMsaa)\n\t\t\t{\n\t\t\t\tsetResourceBarrier(\n\t\t\t\t\t  m_commandList\n\t\t\t\t\t, src.m_singleMsaa\n\t\t\t\t\t, D3D12_RESOURCE_STATE_COPY_SOURCE\n\t\t\t\t\t, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE\n\t\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (isValid(currentSrc)\n\t\t&&  D3D12_RESOURCE_STATES(UINT32_MAX) != state)\n\t\t{\n\t\t\tm_textures[currentSrc.idx].setState(m_commandList, state);\n\t\t}\n\t}\n\n\tvoid RendererContextD3D12::submit(Frame* _render, ClearQuad& /*_clearQuad*/, TextVideoMemBlitter& _textVideoMemBlitter)\n\t{\n\t\tif (m_lost\n\t\t||  updateResolution(_render->m_resolution) )\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (_render->m_capture)\n\t\t{\n\t\t\trenderDocTriggerCapture();\n\t\t}\n\n\t\tBGFX_D3D12_PROFILER_BEGIN_LITERAL("rendererSubmit", kColorFrame);\n\n\t\tint64_t timeBegin = bx::getHPCounter();\n\t\tint64_t captureElapsed = 0;\n\n\t\tuint32_t frameQueryIdx = m_gpuTimer.begin(BGFX_CONFIG_MAX_VIEWS, _render->m_frameNum);\n\n\t\tif (0 < _render->m_iboffset)\n\t\t{\n\t\t\tBGFX_PROFILER_SCOPE("bgfx/Update transient index buffer", kColorResource);\n\t\t\tTransientIndexBuffer* ib = _render->m_transientIb;\n\t\t\tm_indexBuffers[ib->handle.idx].update(m_commandList, 0, _render->m_iboffset, ib->data);\n\t\t}\n\n\t\tif (0 < _render->m_vboffset)\n\t\t{\n\t\t\tBGFX_PROFILER_SCOPE("bgfx/Update transient vertex buffer", kColorResource);\n\t\t\tTransientVertexBuffer* vb = _render->m_transientVb;\n\t\t\tm_vertexBuffers[vb->handle.idx].update(m_commandList, 0, _render->m_vboffset, vb->data);\n\t\t}\n\n\t\t_render->sort();\n\n\t\tRenderDraw currentState;\n\t\tcurrentState.clear();\n\t\tcurrentState.m_stateFlags = BGFX_STATE_NONE;\n\t\tcurrentState.m_stencil    = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);\n\n\t\tRenderBind currentBind;\n\t\tcurrentBind.clear();\n\n\t\tstatic ViewState viewState;\n\t\tviewState.reset(_render);\n\n// \t\tbool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);\n// \t\tsetDebugWireframe(wireframe);\n\n\t\tuint16_t currentSamplerStateIdx = kInvalidHandle;\n\t\tProgramHandle currentProgram    = BGFX_INVALID_HANDLE;\n\t\tuint32_t currentBindHash        = 0;\n\t\tbool     hasPredefined          = false;\n\t\tbool     commandListChanged     = false;\n\t\tID3D12PipelineState* currentPso = NULL;\n\t\tSortKey key;\n\t\tuint16_t view = UINT16_MAX;\n\t\tFrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS };\n\n\t\tBlitState bs(_render);\n\n\t\tuint32_t blendFactor = 0;\n\n\t\tconst uint64_t primType = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0;\n\t\tuint8_t primIndex = uint8_t(primType >> BGFX_STATE_PT_SHIFT);\n\t\tPrimInfo prim = s_primInfo[primIndex];\n\n\t\tbool wasCompute = false;\n\t\tbool viewHasScissor = false;\n\t\tbool restoreScissor = false;\n\t\tRect viewScissorRect;\n\t\tviewScissorRect.clear();\n\n\t\tconst uint32_t maxComputeBindings = g_caps.limits.maxComputeBindings;\n\n\t\tuint32_t statsNumPrimsSubmitted[BX_COUNTOF(s_primInfo)] = {};\n\t\tuint32_t statsNumPrimsRendered[BX_COUNTOF(s_primInfo)] = {};\n\t\tuint32_t statsNumInstances[BX_COUNTOF(s_primInfo)] = {};\n\t\tuint32_t statsNumIndices = 0;\n\t\tuint32_t statsKeyType[2] = {};\n\n\t\tProfiler<TimerQueryD3D12> profiler(\n\t\t\t  _render\n\t\t\t, m_gpuTimer\n\t\t\t, s_viewName\n\t\t\t);\n\n#if BX_PLATFORM_WINDOWS\n\t\tif (NULL != m_swapChain)\n\t\t{\n\t\t\tm_backBufferColorIdx = m_swapChain->GetCurrentBackBufferIndex();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_backBufferColorIdx = (m_backBufferColorIdx+1) % BX_COUNTOF(m_scratchBuffer);\n\t\t}\n#else\n\t\tm_backBufferColorIdx = (m_backBufferColorIdx+1) % m_scd.bufferCount;\n#endif // BX_PLATFORM_WINDOWS\n\n\t\tconst uint64_t f0 = BGFX_STATE_BLEND_FACTOR;\n\t\tconst uint64_t f1 = BGFX_STATE_BLEND_INV_FACTOR;\n\t\tconst uint64_t f2 = BGFX_STATE_BLEND_FACTOR<<4;\n\t\tconst uint64_t f3 = BGFX_STATE_BLEND_INV_FACTOR<<4;\n\n\t\tD3D12_GPU_DESCRIPTOR_HANDLE gpuHandle;\n\t\tScratchBufferD3D12& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx];\n\t\tscratchBuffer.reset(gpuHandle);\n\n\t\tD3D12_GPU_VIRTUAL_ADDRESS gpuAddress = UINT64_C(0);\n\n\t\tStateCacheLru<Bind, 64> bindLru;\n\n\t\tif (NULL != m_msaaRt)\n\t\t{\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_msaaRt\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_SOURCE\n\t\t\t\t, D3D12_RESOURCE_STATE_RENDER_TARGET\n\t\t\t\t);\n\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_backBufferColor[m_backBufferColorIdx]\n\t\t\t\t, D3D12_RESOURCE_STATE_PRESENT\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_DEST\n\t\t\t\t);\n\t\t}\n\t\telse if (NULL != m_swapChain)\n\t\t{\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_backBufferColor[m_backBufferColorIdx]\n\t\t\t\t, D3D12_RESOURCE_STATE_PRESENT\n\t\t\t\t, D3D12_RESOURCE_STATE_RENDER_TARGET\n\t\t\t\t);\n\t\t}\n\n\t\tif (0 == (_render->m_debug&BGFX_DEBUG_IFH) )\n\t\t{\n\t\t\tsetFrameBuffer(BGFX_INVALID_HANDLE, true);\n\n\t\t\tm_batch.begin();\n\n\t\t\tviewState.m_rect = _render->m_view[0].m_rect;\n\t\t\tint32_t numItems = _render->m_numRenderItems;\n\n\t\t\tfor (int32_t item = 0; item < numItems;)\n\t\t\t{\n\t\t\t\tconst uint64_t encodedKey = _render->m_sortKeys[item];\n\t\t\t\tconst bool isCompute = key.decode(encodedKey, _render->m_viewRemap);\n\t\t\t\tstatsKeyType[isCompute]++;\n\n\t\t\t\tconst bool viewChanged = 0\n\t\t\t\t\t|| key.m_view != view\n\t\t\t\t\t|| item == numItems\n\t\t\t\t\t;\n\n\t\t\t\tconst uint32_t itemIdx       = _render->m_sortValues[item];\n\t\t\t\tconst RenderItem& renderItem = _render->m_renderItem[itemIdx];\n\t\t\t\tconst RenderBind& renderBind = _render->m_renderItemBind[itemIdx];\n\t\t\t\t++item;\n\n\t\t\t\tif (viewChanged)\n\t\t\t\t{\n\t\t\t\t\tm_batch.flush(m_commandList, true);\n\t\t\t\t\tkick();\n\n\t\t\t\t\tcommandListChanged = true;\n\n\t\t\t\t\tview = key.m_view;\n\t\t\t\t\tcurrentPso = NULL;\n\t\t\t\t\tcurrentSamplerStateIdx = kInvalidHandle;\n\t\t\t\t\tcurrentProgram         = BGFX_INVALID_HANDLE;\n\t\t\t\t\thasPredefined          = false;\n\n\t\t\t\t\tif (item > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tprofiler.end();\n\t\t\t\t\t}\n\n\t\t\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t\t\t\tsetViewType(view, "  ");\n\t\t\t\t\tBGFX_D3D12_PROFILER_BEGIN(view, kColorView);\n\n\t\t\t\t\tprofiler.begin(view);\n\n\t\t\t\t\tfbh = _render->m_view[view].m_fbh;\n\t\t\t\t\tsetFrameBuffer(fbh);\n\n\t\t\t\t\tviewState.m_rect = _render->m_view[view].m_rect;\n\t\t\t\t\tconst Rect& rect        = _render->m_view[view].m_rect;\n\t\t\t\t\tconst Rect& scissorRect = _render->m_view[view].m_scissor;\n\t\t\t\t\tviewHasScissor  = !scissorRect.isZero();\n\t\t\t\t\tviewScissorRect = viewHasScissor ? scissorRect : rect;\n\n\t\t\t\t\tD3D12_VIEWPORT vp;\n\t\t\t\t\tvp.TopLeftX = rect.m_x;\n\t\t\t\t\tvp.TopLeftY = rect.m_y;\n\t\t\t\t\tvp.Width    = rect.m_width;\n\t\t\t\t\tvp.Height   = rect.m_height;\n\t\t\t\t\tvp.MinDepth = 0.0f;\n\t\t\t\t\tvp.MaxDepth = 1.0f;\n\t\t\t\t\tm_commandList->RSSetViewports(1, &vp);\n\n\t\t\t\t\tD3D12_RECT rc;\n\t\t\t\t\trc.left   = viewScissorRect.m_x;\n\t\t\t\t\trc.top    = viewScissorRect.m_y;\n\t\t\t\t\trc.right  = viewScissorRect.m_x + viewScissorRect.m_width;\n\t\t\t\t\trc.bottom = viewScissorRect.m_y + viewScissorRect.m_height;\n\t\t\t\t\tm_commandList->RSSetScissorRects(1, &rc);\n\t\t\t\t\trestoreScissor = false;\n\n\t\t\t\t\tClear& clr = _render->m_view[view].m_clear;\n\t\t\t\t\tif (BGFX_CLEAR_NONE != clr.m_flags)\n\t\t\t\t\t{\n\t\t\t\t\t\tRect clearRect = rect;\n\t\t\t\t\t\tclearRect.setIntersect(rect, viewScissorRect);\n\t\t\t\t\t\tclearQuad(clearRect, clr, _render->m_colorPalette);\n\t\t\t\t\t}\n\n\t\t\t\t\tprim = s_primInfo[Topology::Count]; // Force primitive type update.\n\n\t\t\t\t\tsubmitBlit(bs, view);\n\t\t\t\t}\n\n\t\t\t\tif (isCompute)\n\t\t\t\t{\n\t\t\t\t\tif (!wasCompute)\n\t\t\t\t\t{\n\t\t\t\t\t\twasCompute = true;\n\n\t\t\t\t\t\tsetViewType(view, "C");\n\t\t\t\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t\t\t\t\tBGFX_D3D12_PROFILER_BEGIN(view, kColorCompute);\n\n\t\t\t\t\t\tcommandListChanged = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (commandListChanged)\n\t\t\t\t\t{\n\t\t\t\t\t\tcommandListChanged = false;\n\n\t\t\t\t\t\tm_commandList->SetComputeRootSignature(m_rootSignature);\n\t\t\t\t\t\tID3D12DescriptorHeap* heaps[] = {\n\t\t\t\t\t\t\tm_samplerAllocator.getHeap(),\n\t\t\t\t\t\t\tscratchBuffer.getHeap(),\n\t\t\t\t\t\t};\n\t\t\t\t\t\tm_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst RenderCompute& compute = renderItem.compute;\n\n\t\t\t\t\tID3D12PipelineState* pso = getPipelineState(key.m_program);\n\t\t\t\t\tif (pso != currentPso)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentPso = pso;\n\t\t\t\t\t\tm_commandList->SetPipelineState(pso);\n\t\t\t\t\t\tcurrentBindHash = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tuint32_t bindHash = bx::hash<bx::HashMurmur2A>(renderBind.m_bind, sizeof(renderBind.m_bind) );\n\t\t\t\t\tif (currentBindHash != bindHash)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentBindHash  = bindHash;\n\n\t\t\t\t\t\tBind* bindCached = bindLru.find(bindHash);\n\t\t\t\t\t\tif (NULL == bindCached)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint32_t numSet = 0;\n\t\t\t\t\t\t\tD3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_MAX_COMPUTE_BINDINGS] = {};\n\t\t\t\t\t\t\tuint32_t samplerFlags[BGFX_MAX_COMPUTE_BINDINGS] = {};\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (uint8_t stage = 0; stage < maxComputeBindings; ++stage)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tconst Binding& bind = renderBind.m_bind[stage];\n\t\t\t\t\t\t\t\t\tif (kInvalidHandle != bind.m_idx)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tswitch (bind.m_type)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tcase Binding::Image:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tTextureD3D12& texture = m_textures[bind.m_idx];\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (Access::Read != bind.m_access)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocUav(srvHandle[stage], texture, bind.m_mip);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_mip);\n\t\t\t\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = uint32_t(texture.m_flags);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase Binding::Texture:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tTextureD3D12& texture = m_textures[bind.m_idx];\n\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], texture);\n\t\t\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? bind.m_samplerFlags\n\t\t\t\t\t\t\t\t\t\t\t\t\t: texture.m_flags\n\t\t\t\t\t\t\t\t\t\t\t\t\t) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK)\n\t\t\t\t\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase Binding::IndexBuffer:\n\t\t\t\t\t\t\t\t\t\tcase Binding::VertexBuffer:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tBufferD3D12& buffer = Binding::IndexBuffer == bind.m_type\n\t\t\t\t\t\t\t\t\t\t\t\t\t? m_indexBuffers[bind.m_idx]\n\t\t\t\t\t\t\t\t\t\t\t\t\t: m_vertexBuffers[bind.m_idx]\n\t\t\t\t\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (Access::Read != bind.m_access)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tbuffer.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocUav(srvHandle[stage], buffer);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tbuffer.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], buffer);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = 0;\n\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocEmpty(srvHandle[stage]);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (0 != numSet)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tBind bind;\n\t\t\t\t\t\t\t\t\tbind.m_srvHandle = srvHandle[0];\n\t\t\t\t\t\t\t\t\tbind.m_samplerStateIdx = getSamplerState(samplerFlags, maxComputeBindings, _render->m_colorPalette);\n\t\t\t\t\t\t\t\t\tbindCached = bindLru.add(bindHash, bind, 0);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (NULL != bindCached)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint16_t samplerStateIdx = bindCached->m_samplerStateIdx;\n\t\t\t\t\t\t\tif (samplerStateIdx != currentSamplerStateIdx)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcurrentSamplerStateIdx = samplerStateIdx;\n\t\t\t\t\t\t\t\tm_commandList->SetComputeRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_commandList->SetComputeRootDescriptorTable(Rdt::SRV, bindCached->m_srvHandle);\n\t\t\t\t\t\t\tm_commandList->SetComputeRootDescriptorTable(Rdt::UAV, bindCached->m_srvHandle);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbool constantsChanged = false;\n\t\t\t\t\tif (compute.m_uniformBegin < compute.m_uniformEnd\n\t\t\t\t\t||  currentProgram.idx != key.m_program.idx)\n\t\t\t\t\t{\n\t\t\t\t\t\trendererUpdateUniforms(this, _render->m_uniformBuffer[compute.m_uniformIdx], compute.m_uniformBegin, compute.m_uniformEnd);\n\n\t\t\t\t\t\tcurrentProgram = key.m_program;\n\t\t\t\t\t\tProgramD3D12& program = m_program[currentProgram.idx];\n\n\t\t\t\t\t\tUniformBuffer* vcb = program.m_vsh->m_constantBuffer;\n\t\t\t\t\t\tif (NULL != vcb)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommit(*vcb);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thasPredefined = 0 < program.m_numPredefined;\n\t\t\t\t\t\tconstantsChanged = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (constantsChanged\n\t\t\t\t\t||  hasPredefined)\n\t\t\t\t\t{\n\t\t\t\t\t\tProgramD3D12& program = m_program[currentProgram.idx];\n\t\t\t\t\t\tviewState.setPredefined<4>(this, view, program, _render, compute);\n\t\t\t\t\t\tcommitShaderConstants(key.m_program, gpuAddress);\n\t\t\t\t\t\tm_commandList->SetComputeRootConstantBufferView(Rdt::CBV, gpuAddress);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isValid(compute.m_indirectBuffer) )\n\t\t\t\t\t{\n\t\t\t\t\t\tconst VertexBufferD3D12& indirect = m_vertexBuffers[compute.m_indirectBuffer.idx];\n\n\t\t\t\t\t\tuint32_t numDrawIndirect = UINT16_MAX == compute.m_numIndirect\n\t\t\t\t\t\t\t? indirect.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE\n\t\t\t\t\t\t\t: compute.m_numIndirect\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\tm_commandList->ExecuteIndirect(\n\t\t\t\t\t\t\t  s_renderD3D12->m_commandSignature[0]\n\t\t\t\t\t\t\t, numDrawIndirect\n\t\t\t\t\t\t\t, indirect.m_ptr\n\t\t\t\t\t\t\t, compute.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE\n\t\t\t\t\t\t\t, NULL\n\t\t\t\t\t\t\t, 0\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_commandList->Dispatch(compute.m_numX, compute.m_numY, compute.m_numZ);\n\t\t\t\t\t}\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tbool resetState = viewChanged || wasCompute;\n\n\t\t\t\tif (wasCompute)\n\t\t\t\t{\n\t\t\t\t\twasCompute = false;\n\n\t\t\t\t\tsetViewType(view, " ");\n\t\t\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t\t\t\tBGFX_D3D12_PROFILER_BEGIN(view, kColorDraw);\n\n\t\t\t\t\tcommandListChanged = true;\n\t\t\t\t}\n\n\t\t\t\tconst RenderDraw& draw = renderItem.draw;\n\n\t\t\t\tconst bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);\n\t\t\t\t{\n\t\t\t\t\tconst bool occluded = true\n\t\t\t\t\t\t&& isValid(draw.m_occlusionQuery)\n\t\t\t\t\t\t&& !hasOcclusionQuery\n\t\t\t\t\t\t&& !isVisible(_render, draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) )\n\t\t\t\t\t\t;\n\n\t\t\t\t\tif (occluded\n\t\t\t\t\t||  _render->m_frameCache.isZeroArea(viewScissorRect, draw.m_scissor) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif (resetState)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcurrentState.clear();\n\t\t\t\t\t\t\tcurrentState.m_scissor = !draw.m_scissor;\n\t\t\t\t\t\t\tcurrentBind.clear();\n\t\t\t\t\t\t\tcommandListChanged = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst uint64_t newFlags = draw.m_stateFlags;\n\t\t\t\tuint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;\n\t\t\t\tcurrentState.m_stateFlags = newFlags;\n\n\t\t\t\tif (0 != (BGFX_STATE_PT_MASK & changedFlags) )\n\t\t\t\t{\n\t\t\t\t\tprimIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT);\n\t\t\t\t}\n\n\t\t\t\tconst uint64_t newStencil = draw.m_stencil;\n\t\t\t\tuint64_t changedStencil = (currentState.m_stencil ^ draw.m_stencil) & BGFX_STENCIL_FUNC_REF_MASK;\n\t\t\t\tcurrentState.m_stencil = newStencil;\n\n\t\t\t\tif (resetState)\n\t\t\t\t{\n\t\t\t\t\twasCompute = false;\n\n\t\t\t\t\tcurrentState.clear();\n\t\t\t\t\tcurrentState.m_scissor = !draw.m_scissor;\n\t\t\t\t\tchangedFlags = BGFX_STATE_MASK;\n\t\t\t\t\tchangedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);\n\t\t\t\t\tcurrentState.m_stateFlags = newFlags;\n\t\t\t\t\tcurrentState.m_stencil    = newStencil;\n\n\t\t\t\t\tcurrentBind.clear();\n\n\t\t\t\t\tcommandListChanged = true;\n\t\t\t\t}\n\n\t\t\t\tif (commandListChanged)\n\t\t\t\t{\n\t\t\t\t\tcommandListChanged = false;\n\n\t\t\t\t\tm_commandList->SetGraphicsRootSignature(m_rootSignature);\n\t\t\t\t\tID3D12DescriptorHeap* heaps[] = {\n\t\t\t\t\t\tm_samplerAllocator.getHeap(),\n\t\t\t\t\t\tscratchBuffer.getHeap(),\n\t\t\t\t\t};\n\t\t\t\t\tm_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);\n\n\t\t\t\t\tcurrentPso             = NULL;\n\t\t\t\t\tcurrentBindHash        = 0;\n\t\t\t\t\tcurrentSamplerStateIdx = kInvalidHandle;\n\t\t\t\t\tcurrentProgram         = BGFX_INVALID_HANDLE;\n\t\t\t\t\tcurrentState.clear();\n\t\t\t\t\tcurrentState.m_scissor = !draw.m_scissor;\n\t\t\t\t\tchangedFlags = BGFX_STATE_MASK;\n\t\t\t\t\tchangedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);\n\t\t\t\t\tcurrentState.m_stateFlags = newFlags;\n\t\t\t\t\tcurrentState.m_stencil    = newStencil;\n\n\t\t\t\t\tcurrentBind.clear();\n\n\t\t\t\t\tconst uint64_t pt = newFlags&BGFX_STATE_PT_MASK;\n\t\t\t\t\tprimIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);\n\t\t\t\t}\n\n\t\t\t\tbool constantsChanged = draw.m_uniformBegin < draw.m_uniformEnd;\n\t\t\t\trendererUpdateUniforms(this, _render->m_uniformBuffer[draw.m_uniformIdx], draw.m_uniformBegin, draw.m_uniformEnd);\n\n\t\t\t\tif (0 != draw.m_streamMask)\n\t\t\t\t{\n\t\t\t\t\tcurrentState.m_streamMask             = draw.m_streamMask;\n\t\t\t\t\tcurrentState.m_instanceDataBuffer.idx = draw.m_instanceDataBuffer.idx;\n\t\t\t\t\tcurrentState.m_instanceDataOffset     = draw.m_instanceDataOffset;\n\t\t\t\t\tcurrentState.m_instanceDataStride     = draw.m_instanceDataStride;\n\n\t\t\t\t\tconst uint64_t state = draw.m_stateFlags;\n\t\t\t\t\tbool hasFactor = 0\n\t\t\t\t\t\t|| f0 == (state & f0)\n\t\t\t\t\t\t|| f1 == (state & f1)\n\t\t\t\t\t\t|| f2 == (state & f2)\n\t\t\t\t\t\t|| f3 == (state & f3)\n\t\t\t\t\t\t;\n\n\t\t\t\t\tconst VertexLayout* layouts[BGFX_CONFIG_MAX_VERTEX_STREAMS];\n\n\t\t\t\t\tuint8_t numStreams = 0;\n\t\t\t\t\tif (UINT8_MAX != draw.m_streamMask)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (uint32_t idx = 0, streamMask = draw.m_streamMask\n\t\t\t\t\t\t\t; 0 != streamMask\n\t\t\t\t\t\t\t; streamMask >>= 1, idx += 1, ++numStreams\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst uint32_t ntz = bx::uint32_cnttz(streamMask);\n\t\t\t\t\t\t\tstreamMask >>= ntz;\n\t\t\t\t\t\t\tidx         += ntz;\n\n\t\t\t\t\t\t\tcurrentState.m_stream[idx].m_layoutHandle = draw.m_stream[idx].m_layoutHandle;\n\t\t\t\t\t\t\tcurrentState.m_stream[idx].m_handle       = draw.m_stream[idx].m_handle;\n\t\t\t\t\t\t\tcurrentState.m_stream[idx].m_startVertex  = draw.m_stream[idx].m_startVertex;\n\n\t\t\t\t\t\t\tuint16_t handle = draw.m_stream[idx].m_handle.idx;\n\t\t\t\t\t\t\tconst VertexBufferD3D12& vb = m_vertexBuffers[handle];\n\t\t\t\t\t\t\tconst uint16_t layoutIdx = isValid(draw.m_stream[idx].m_layoutHandle)\n\t\t\t\t\t\t\t\t? draw.m_stream[idx].m_layoutHandle.idx\n\t\t\t\t\t\t\t\t: vb.m_layoutHandle.idx;\n\t\t\t\t\t\t\tconst VertexLayout& layout = m_vertexLayouts[layoutIdx];\n\n\t\t\t\t\t\t\tlayouts[numStreams] = &layout;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tID3D12PipelineState* pso =\n\t\t\t\t\t\tgetPipelineState(state\n\t\t\t\t\t\t\t, draw.m_stencil\n\t\t\t\t\t\t\t, numStreams\n\t\t\t\t\t\t\t, layouts\n\t\t\t\t\t\t\t, key.m_program\n\t\t\t\t\t\t\t, uint8_t(draw.m_instanceDataStride/16)\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\tuint16_t scissor = draw.m_scissor;\n\t\t\t\t\tuint32_t bindHash = bx::hash<bx::HashMurmur2A>(renderBind.m_bind, sizeof(renderBind.m_bind) );\n\t\t\t\t\tif (currentBindHash != bindHash\n\t\t\t\t\t||  0 != changedStencil\n\t\t\t\t\t|| (hasFactor && blendFactor != draw.m_rgba)\n\t\t\t\t\t|| (0 != (BGFX_STATE_PT_MASK & changedFlags)\n\t\t\t\t\t||  prim.m_topology != s_primInfo[primIndex].m_topology)\n\t\t\t\t\t||  currentState.m_scissor != scissor\n\t\t\t\t\t||  pso != currentPso\n\t\t\t\t\t||  hasOcclusionQuery)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_batch.flush(m_commandList);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (currentBindHash != bindHash)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentBindHash  = bindHash;\n\n\t\t\t\t\t\tBind* bindCached = bindLru.find(bindHash);\n\t\t\t\t\t\tif (NULL == bindCached)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint32_t numSet = 0;\n\t\t\t\t\t\t\tD3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS] = {};\n\t\t\t\t\t\t\tuint32_t samplerFlags[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS] = {};\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (uint32_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tconst Binding& bind = renderBind.m_bind[stage];\n\t\t\t\t\t\t\t\t\tif (kInvalidHandle != bind.m_idx)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tswitch (bind.m_type)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tcase Binding::Image:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tTextureD3D12& texture = m_textures[bind.m_idx];\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (Access::Read != bind.m_access)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocUav(srvHandle[stage], texture, bind.m_mip);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_mip);\n\t\t\t\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = uint32_t(texture.m_flags);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase Binding::Texture:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tTextureD3D12& texture = m_textures[bind.m_idx];\n\t\t\t\t\t\t\t\t\t\t\t\ttexture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], texture);\n\t\t\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? bind.m_samplerFlags\n\t\t\t\t\t\t\t\t\t\t\t\t\t: texture.m_flags\n\t\t\t\t\t\t\t\t\t\t\t\t\t) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK)\n\t\t\t\t\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase Binding::IndexBuffer:\n\t\t\t\t\t\t\t\t\t\tcase Binding::VertexBuffer:\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = 0;\n\n\t\t\t\t\t\t\t\t\t\t\t\tBufferD3D12& buffer = Binding::IndexBuffer == bind.m_type\n\t\t\t\t\t\t\t\t\t\t\t\t\t? m_indexBuffers[bind.m_idx]\n\t\t\t\t\t\t\t\t\t\t\t\t\t: m_vertexBuffers[bind.m_idx]\n\t\t\t\t\t\t\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (Access::Read != bind.m_access)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tbuffer.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocUav(srvHandle[stage], buffer);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tbuffer.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);\n\t\t\t\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocSrv(srvHandle[stage], buffer);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t++numSet;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tscratchBuffer.allocEmpty(srvHandle[stage]);\n\t\t\t\t\t\t\t\t\t\tsamplerFlags[stage] = 0;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (0 != numSet)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tBind bind;\n\t\t\t\t\t\t\t\tbind.m_srvHandle       = srvHandle[0];\n\t\t\t\t\t\t\t\tbind.m_samplerStateIdx = getSamplerState(samplerFlags, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, _render->m_colorPalette);\n\t\t\t\t\t\t\t\tbindCached = bindLru.add(bindHash, bind, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (NULL != bindCached)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint16_t samplerStateIdx = bindCached->m_samplerStateIdx;\n\t\t\t\t\t\t\tif (samplerStateIdx != currentSamplerStateIdx)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcurrentSamplerStateIdx = samplerStateIdx;\n\t\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::Sampler, m_samplerAllocator.get(samplerStateIdx) );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::SRV, bindCached->m_srvHandle);\n\t\t\t\t\t\t\tm_commandList->SetGraphicsRootDescriptorTable(Rdt::UAV, bindCached->m_srvHandle);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 != changedStencil)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst uint32_t fstencil = unpackStencil(0, draw.m_stencil);\n\t\t\t\t\t\tconst uint32_t ref = (fstencil&BGFX_STENCIL_FUNC_REF_MASK)>>BGFX_STENCIL_FUNC_REF_SHIFT;\n\t\t\t\t\t\tm_commandList->OMSetStencilRef(ref);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (hasFactor\n\t\t\t\t\t&&  blendFactor != draw.m_rgba)\n\t\t\t\t\t{\n\t\t\t\t\t\tblendFactor = draw.m_rgba;\n\n\t\t\t\t\t\tfloat bf[4];\n\t\t\t\t\t\tbf[0] = ( (draw.m_rgba>>24)     )/255.0f;\n\t\t\t\t\t\tbf[1] = ( (draw.m_rgba>>16)&0xff)/255.0f;\n\t\t\t\t\t\tbf[2] = ( (draw.m_rgba>> 8)&0xff)/255.0f;\n\t\t\t\t\t\tbf[3] = ( (draw.m_rgba    )&0xff)/255.0f;\n\t\t\t\t\t\tm_commandList->OMSetBlendFactor(bf);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 != (BGFX_STATE_PT_MASK & changedFlags)\n\t\t\t\t\t||  prim.m_topology != s_primInfo[primIndex].m_topology)\n\t\t\t\t\t{\n\t\t\t\t\t\tconst uint64_t pt = newFlags&BGFX_STATE_PT_MASK;\n\t\t\t\t\t\tprimIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);\n\t\t\t\t\t\tprim = s_primInfo[primIndex];\n\t\t\t\t\t\tm_commandList->IASetPrimitiveTopology(prim.m_topology);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (currentState.m_scissor != scissor)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentState.m_scissor = scissor;\n\n\t\t\t\t\t\tif (UINT16_MAX == scissor)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (restoreScissor\n\t\t\t\t\t\t\t||  viewHasScissor)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trestoreScissor = false;\n\t\t\t\t\t\t\t\tD3D12_RECT rc;\n\t\t\t\t\t\t\t\trc.left   = viewScissorRect.m_x;\n\t\t\t\t\t\t\t\trc.top    = viewScissorRect.m_y;\n\t\t\t\t\t\t\t\trc.right  = viewScissorRect.m_x + viewScissorRect.m_width;\n\t\t\t\t\t\t\t\trc.bottom = viewScissorRect.m_y + viewScissorRect.m_height;\n\t\t\t\t\t\t\t\tm_commandList->RSSetScissorRects(1, &rc);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trestoreScissor = true;\n\t\t\t\t\t\t\tRect scissorRect;\n\t\t\t\t\t\t\tscissorRect.setIntersect(viewScissorRect, _render->m_frameCache.m_rectCache.m_cache[scissor]);\n\t\t\t\t\t\t\tif (scissorRect.isZeroArea() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tD3D12_RECT rc;\n\t\t\t\t\t\t\trc.left   = scissorRect.m_x;\n\t\t\t\t\t\t\trc.top    = scissorRect.m_y;\n\t\t\t\t\t\t\trc.right  = scissorRect.m_x + scissorRect.m_width;\n\t\t\t\t\t\t\trc.bottom = scissorRect.m_y + scissorRect.m_height;\n\t\t\t\t\t\t\tm_commandList->RSSetScissorRects(1, &rc);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pso != currentPso)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentPso = pso;\n\t\t\t\t\t\tm_commandList->SetPipelineState(pso);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (constantsChanged\n\t\t\t\t\t||  currentProgram.idx != key.m_program.idx\n\t\t\t\t\t||  BGFX_STATE_ALPHA_REF_MASK & changedFlags)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentProgram = key.m_program;\n\t\t\t\t\t\tProgramD3D12& program = m_program[currentProgram.idx];\n\n\t\t\t\t\t\tUniformBuffer* vcb = program.m_vsh->m_constantBuffer;\n\t\t\t\t\t\tif (NULL != vcb)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommit(*vcb);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (NULL != program.m_fsh)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tUniformBuffer* fcb = program.m_fsh->m_constantBuffer;\n\t\t\t\t\t\t\tif (NULL != fcb)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcommit(*fcb);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thasPredefined = 0 < program.m_numPredefined;\n\t\t\t\t\t\tconstantsChanged = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (constantsChanged\n\t\t\t\t\t||  hasPredefined)\n\t\t\t\t\t{\n\t\t\t\t\t\tProgramD3D12& program = m_program[currentProgram.idx];\n\t\t\t\t\t\tuint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT;\n\t\t\t\t\t\tviewState.m_alphaRef = ref/255.0f;\n\t\t\t\t\t\tviewState.setPredefined<4>(this, view, program, _render, draw);\n\t\t\t\t\t\tcommitShaderConstants(key.m_program, gpuAddress);\n\t\t\t\t\t}\n\n\t\t\t\t\tuint32_t numIndices        = m_batch.draw(m_commandList, gpuAddress, draw);\n\t\t\t\t\tuint32_t numPrimsSubmitted = numIndices / prim.m_div - prim.m_sub;\n\t\t\t\t\tuint32_t numPrimsRendered  = numPrimsSubmitted*draw.m_numInstances;\n\n\t\t\t\t\tstatsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;\n\t\t\t\t\tstatsNumPrimsRendered[primIndex]  += numPrimsRendered;\n\t\t\t\t\tstatsNumInstances[primIndex]      += draw.m_numInstances;\n\t\t\t\t\tstatsNumIndices                   += numIndices;\n\n\t\t\t\t\tif (hasOcclusionQuery)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_occlusionQuery.begin(m_commandList, _render, draw.m_occlusionQuery);\n\t\t\t\t\t\tm_batch.flush(m_commandList);\n\t\t\t\t\t\tm_occlusionQuery.end(m_commandList);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_batch.end(m_commandList);\n\t\t\tkick();\n\n\t\t\tif (wasCompute)\n\t\t\t{\n\t\t\t\tsetViewType(view, "C");\n\t\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t\t\tBGFX_D3D12_PROFILER_BEGIN(view, kColorCompute);\n\t\t\t}\n\n\t\t\tsubmitBlit(bs, BGFX_CONFIG_MAX_VIEWS);\n\n\t\t\tif (0 < _render->m_numRenderItems)\n\t\t\t{\n\t\t\t\tif (0 != (m_resolution.reset & BGFX_RESET_FLUSH_AFTER_RENDER) )\n\t\t\t\t{\n//\t\t\t\t\tdeviceCtx->Flush();\n\t\t\t\t}\n\n//\t\t\t\tcaptureElapsed = -bx::getHPCounter();\n//\t\t\t\tcapture();\n//\t\t\t\tcaptureElapsed += bx::getHPCounter();\n\n\t\t\t\tprofiler.end();\n\t\t\t}\n\t\t}\n\n\t\tBGFX_D3D12_PROFILER_END();\n\n\t\tint64_t timeEnd   = bx::getHPCounter();\n\t\tint64_t frameTime = timeEnd - timeBegin;\n\n\t\tstatic int64_t min = frameTime;\n\t\tstatic int64_t max = frameTime;\n\t\tmin = bx::min<int64_t>(min, frameTime);\n\t\tmax = bx::max<int64_t>(max, frameTime);\n\n\t\tstatic uint32_t maxGpuLatency = 0;\n\t\tstatic double   maxGpuElapsed = 0.0f;\n\t\tdouble elapsedGpuMs = 0.0;\n\n\t\tstatic int64_t presentMin = m_presentElapsed;\n\t\tstatic int64_t presentMax = m_presentElapsed;\n\t\tpresentMin = bx::min<int64_t>(presentMin, m_presentElapsed);\n\t\tpresentMax = bx::max<int64_t>(presentMax, m_presentElapsed);\n\n\t\tif (UINT32_MAX != frameQueryIdx)\n\t\t{\n\t\t\tm_gpuTimer.end(frameQueryIdx);\n\n\t\t\tconst TimerQueryD3D12::Result& result = m_gpuTimer.m_result[BGFX_CONFIG_MAX_VIEWS];\n\t\t\tdouble toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);\n\t\t\telapsedGpuMs   = (result.m_end - result.m_begin) * toGpuMs;\n\t\t\tmaxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;\n\n\t\t\tmaxGpuLatency = bx::uint32_imax(maxGpuLatency, result.m_pending-1);\n\t\t}\n\n\t\tmaxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);\n\n\t\tconst int64_t timerFreq = bx::getHPFrequency();\n\n\t\tStats& perfStats = _render->m_perfStats;\n\t\tperfStats.cpuTimeBegin  = timeBegin;\n\t\tperfStats.cpuTimeEnd    = timeEnd;\n\t\tperfStats.cpuTimerFreq  = timerFreq;\n\t\tconst TimerQueryD3D12::Result& result = m_gpuTimer.m_result[BGFX_CONFIG_MAX_VIEWS];\n\t\tperfStats.gpuTimeBegin  = result.m_begin;\n\t\tperfStats.gpuTimeEnd    = result.m_end;\n\t\tperfStats.gpuTimerFreq  = m_gpuTimer.m_frequency;\n\t\tperfStats.numDraw       = statsKeyType[0];\n\t\tperfStats.numCompute    = statsKeyType[1];\n\t\tperfStats.numBlit       = _render->m_numBlitItems;\n\t\tperfStats.maxGpuLatency = maxGpuLatency;\n\t\tperfStats.gpuFrameNum   = result.m_frameNum;\n\t\tbx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );\n\t\tperfStats.gpuMemoryMax  = -INT64_MAX;\n\t\tperfStats.gpuMemoryUsed = -INT64_MAX;\n\n#if BX_PLATFORM_WINDOWS\n\t\tDXGI_QUERY_VIDEO_MEMORY_INFO vmi[2];\n\t\tDX_CHECK(m_dxgi.m_adapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL,     &vmi[0]) );\n\t\tDX_CHECK(m_dxgi.m_adapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &vmi[1]) );\n\n\t\tperfStats.gpuMemoryMax  = int64_t(vmi[0].Budget);\n\t\tperfStats.gpuMemoryUsed = int64_t(vmi[0].CurrentUsage);\n#endif // BX_PLATFORM_WINDOWS\n\n\t\tif (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )\n\t\t{\n\t\t\tBGFX_D3D12_PROFILER_BEGIN_LITERAL("debugstats", kColorFrame);\n\n//\t\t\tm_needPresent = true;\n\t\t\tTextVideoMem& tvm = m_textVideoMem;\n\n\t\t\tstatic int64_t next = timeEnd;\n\n\t\t\tif (timeEnd >= next)\n\t\t\t{\n\t\t\t\tnext = timeEnd + timerFreq;\n\n\t\t\t\tdouble freq = double(timerFreq);\n\t\t\t\tdouble toMs = 1000.0 / freq;\n\n\t\t\t\ttvm.clear();\n\t\t\t\tuint16_t pos = 0;\n\t\t\t\ttvm.printf(0, pos++, BGFX_CONFIG_DEBUG ? 0x8c : 0x8f\n\t\t\t\t\t, " %s.%d (FL %d.%d) / " BX_COMPILER_NAME\n\t\t\t\t\t  " / " BX_CPU_NAME\n\t\t\t\t\t  " / " BX_ARCH_NAME\n\t\t\t\t\t  " / " BX_PLATFORM_NAME\n\t\t\t\t\t  " / Version 1.%d.%d (commit: " BGFX_REV_SHA1 ")"\n\t\t\t\t\t, getRendererName()\n\t\t\t\t\t, m_deviceInterfaceVersion\n\t\t\t\t\t, (m_featureLevel >> 12) & 0xf\n\t\t\t\t\t, (m_featureLevel >>  8) & 0xf\n\t\t\t\t\t, BGFX_API_VERSION\n\t\t\t\t\t, BGFX_REV_NUMBER\n\t\t\t\t\t);\n\n#if BX_PLATFORM_LINUX\n\t\t\t\tconst DXGI_ADAPTER_DESC desc = {};\n#else\n\t\t\t\tconst DXGI_ADAPTER_DESC& desc = m_dxgi.m_adapterDesc;\n#endif // BX_PLATFORM_LINUX\n\t\t\t\tchar description[BX_COUNTOF(desc.Description)];\n\t\t\t\twcstombs(description, desc.Description, BX_COUNTOF(desc.Description) );\n\t\t\t\ttvm.printf(0, pos++, 0x8f, " Device: %s", description);\n\n\t\t\t\tchar dedicatedVideo[16];\n\t\t\t\tbx::prettify(dedicatedVideo, BX_COUNTOF(dedicatedVideo), desc.DedicatedVideoMemory);\n\n\t\t\t\tchar dedicatedSystem[16];\n\t\t\t\tbx::prettify(dedicatedSystem, BX_COUNTOF(dedicatedSystem), desc.DedicatedSystemMemory);\n\n\t\t\t\tchar sharedSystem[16];\n\t\t\t\tbx::prettify(sharedSystem, BX_COUNTOF(sharedSystem), desc.SharedSystemMemory);\n\n\t\t\t\tchar processMemoryUsed[16];\n\t\t\t\tbx::prettify(processMemoryUsed, BX_COUNTOF(processMemoryUsed), bx::getProcessMemoryUsed() );\n\n\t\t\t\ttvm.printf(0, pos++, 0x8f, " Memory: %s (video), %s (system), %s (shared), %s (process) "\n\t\t\t\t\t, dedicatedVideo\n\t\t\t\t\t, dedicatedSystem\n\t\t\t\t\t, sharedSystem\n\t\t\t\t\t, processMemoryUsed\n\t\t\t\t\t);\n\n#if BX_PLATFORM_WINDOWS\n\t\t\t\tfor (uint32_t ii = 0; ii < BX_COUNTOF(vmi); ++ii)\n\t\t\t\t{\n\t\t\t\t\tconst DXGI_QUERY_VIDEO_MEMORY_INFO& memInfo = vmi[ii];\n\n\t\t\t\t\tchar budget[16];\n\t\t\t\t\tbx::prettify(budget, BX_COUNTOF(budget), memInfo.Budget);\n\n\t\t\t\t\tchar currentUsage[16];\n\t\t\t\t\tbx::prettify(currentUsage, BX_COUNTOF(currentUsage), memInfo.CurrentUsage);\n\n\t\t\t\t\tchar availableForReservation[16];\n\t\t\t\t\tbx::prettify(availableForReservation, BX_COUNTOF(currentUsage), memInfo.AvailableForReservation);\n\n\t\t\t\t\tchar currentReservation[16];\n\t\t\t\t\tbx::prettify(currentReservation, BX_COUNTOF(currentReservation), memInfo.CurrentReservation);\n\n\t\t\t\t\ttvm.printf(0, pos++, 0x8f, "   %s - Budget: %10s, Usage: %10s, AvailRes: %10s, CurrRes: %10s "\n\t\t\t\t\t\t, 0 == ii ? "Local    " : "Non-local"\n\t\t\t\t\t\t, budget\n\t\t\t\t\t\t, currentUsage\n\t\t\t\t\t\t, availableForReservation\n\t\t\t\t\t\t, currentReservation\n\t\t\t\t\t\t);\n\t\t\t\t}\n#endif // BX_PLATFORM_WINDOWS\n\n\t\t\t\tpos = 10;\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "       Frame: % 7.3f, % 7.3f \\x1f, % 7.3f \\x1e [ms] / % 6.2f FPS "\n\t\t\t\t\t, double(frameTime)*toMs\n\t\t\t\t\t, double(min)*toMs\n\t\t\t\t\t, double(max)*toMs\n\t\t\t\t\t, freq/frameTime\n\t\t\t\t\t);\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "     Present: % 7.3f, % 7.3f \\x1f, % 7.3f \\x1e [ms] "\n\t\t\t\t\t, double(m_presentElapsed)*toMs\n\t\t\t\t\t, double(presentMin)*toMs\n\t\t\t\t\t, double(presentMax)*toMs\n\t\t\t\t\t);\n\n\t\t\t\tconst uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;\n\t\t\t\ttvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy "\n\t\t\t\t\t, !!(m_resolution.reset&BGFX_RESET_VSYNC) ? \'\\xfe\' : \' \'\n\t\t\t\t\t, 0 != msaa ? \'\\xfe\' : \' \'\n\t\t\t\t\t, 1<<msaa\n\t\t\t\t\t, !!(m_resolution.reset&BGFX_RESET_MAXANISOTROPY) ? \'\\xfe\' : \' \'\n\t\t\t\t\t);\n\n\t\t\t\tdouble elapsedCpuMs = double(frameTime)*toMs;\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "   Submitted: %5d (draw %5d, compute %4d) / CPU %7.4f [ms] "\n\t\t\t\t\t, _render->m_numRenderItems\n\t\t\t\t\t, statsKeyType[0]\n\t\t\t\t\t, statsKeyType[1]\n\t\t\t\t\t, elapsedCpuMs\n\t\t\t\t\t);\n\n\t\t\t\tfor (uint32_t ii = 0; ii < Topology::Count; ++ii)\n\t\t\t\t{\n\t\t\t\t\ttvm.printf(10, pos++, 0x8b, "   %9s: %7d (#inst: %5d), submitted: %7d "\n\t\t\t\t\t\t, getName(Topology::Enum(ii) )\n\t\t\t\t\t\t, statsNumPrimsRendered[ii]\n\t\t\t\t\t\t, statsNumInstances[ii]\n\t\t\t\t\t\t, statsNumPrimsSubmitted[ii]\n\t\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "       Batch: %7dx%d indirect, %7d immediate "\n\t\t\t\t\t, m_batch.m_stats.m_numIndirect[BatchD3D12::Draw]\n\t\t\t\t\t, m_batch.m_maxDrawPerBatch\n\t\t\t\t\t, m_batch.m_stats.m_numImmediate[BatchD3D12::Draw]\n\t\t\t\t\t);\n\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "              %7dx%d indirect, %7d immediate "\n\t\t\t\t\t, m_batch.m_stats.m_numIndirect[BatchD3D12::DrawIndexed]\n\t\t\t\t\t, m_batch.m_maxDrawPerBatch\n\t\t\t\t\t, m_batch.m_stats.m_numImmediate[BatchD3D12::DrawIndexed]\n\t\t\t\t\t);\n\n\t\t\t\tif (NULL != m_renderDocDll)\n\t\t\t\t{\n\t\t\t\t\ttvm.printf(tvm.m_width-27, 0, 0x4f, " [F11 - RenderDoc capture] ");\n\t\t\t\t}\n\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "      Indices: %7d ", statsNumIndices);\n//\t\t\t\ttvm.printf(10, pos++, 0x8b, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "     DVB size: %7d ", _render->m_vboffset);\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "     DIB size: %7d ", _render->m_iboffset);\n\n\t\t\t\tpos++;\n\t\t\t\ttvm.printf(10, pos++, 0x8b, " State cache:                        ");\n\t\t\t\ttvm.printf(10, pos++, 0x8b, " PSO    | Sampler | Bind   | Queued  ");\n\t\t\t\ttvm.printf(10, pos++, 0x8b, " %6d |  %6d | %6d | %6d  "\n\t\t\t\t\t, m_pipelineStateCache.getCount()\n\t\t\t\t\t, m_samplerStateCache.getCount()\n\t\t\t\t\t, bindLru.getCount()\n\t\t\t\t\t, m_cmd.m_control.available()\n\t\t\t\t\t);\n\t\t\t\tpos++;\n\n\t\t\t\tdouble captureMs = double(captureElapsed)*toMs;\n\t\t\t\ttvm.printf(10, pos++, 0x8b, "     Capture: %7.4f [ms] ", captureMs);\n\n\t\t\t\tuint8_t attr[2] = { 0x8c, 0x8a };\n\t\t\t\tuint8_t attrIndex = _render->m_waitSubmit < _render->m_waitRender;\n\n\t\t\t\ttvm.printf(10, pos++, attr[attrIndex&1], " Submit wait: %7.4f [ms] ", _render->m_waitSubmit*toMs);\n\t\t\t\ttvm.printf(10, pos++, attr[(attrIndex+1)&1], " Render wait: %7.4f [ms] ", _render->m_waitRender*toMs);\n\n\t\t\t\tmin = frameTime;\n\t\t\t\tmax = frameTime;\n\t\t\t\tpresentMin = m_presentElapsed;\n\t\t\t\tpresentMax = m_presentElapsed;\n\t\t\t}\n\n\t\t\tblit(this, _textVideoMemBlitter, tvm);\n\n\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t}\n\t\telse if (_render->m_debug & BGFX_DEBUG_TEXT)\n\t\t{\n\t\t\tBGFX_D3D12_PROFILER_BEGIN_LITERAL("debugtext", kColorFrame);\n\n\t\t\tblit(this, _textVideoMemBlitter, _render->m_textVideoMem);\n\n\t\t\tBGFX_D3D12_PROFILER_END();\n\t\t}\n\n\t\tm_commandList->OMSetRenderTargets(0, NULL, false, NULL);\n\n\t\tif (NULL != m_msaaRt)\n\t\t{\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_msaaRt\n\t\t\t\t, D3D12_RESOURCE_STATE_RENDER_TARGET\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_SOURCE\n\t\t\t\t);\n\n\t\t\tm_commandList->ResolveSubresource(m_backBufferColor[m_backBufferColorIdx], 0, m_msaaRt, 0, m_scd.format);\n\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_backBufferColor[m_backBufferColorIdx]\n\t\t\t\t, D3D12_RESOURCE_STATE_RESOLVE_DEST\n\t\t\t\t, D3D12_RESOURCE_STATE_PRESENT\n\t\t\t\t);\n\t\t}\n\t\telse if (NULL != m_swapChain)\n\t\t{\n\t\t\tsetResourceBarrier(m_commandList\n\t\t\t\t, m_backBufferColor[m_backBufferColorIdx]\n\t\t\t\t, D3D12_RESOURCE_STATE_RENDER_TARGET\n\t\t\t\t, D3D12_RESOURCE_STATE_PRESENT\n\t\t\t\t);\n\t\t}\n\n#if BX_PLATFORM_WINDOWS\n\t\tfor (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii)\n\t\t{\n\t\t\tFrameBufferD3D12& frameBuffer = m_frameBuffers[m_windows[ii].idx];\n\t\t\tif (NULL != frameBuffer.m_swapChain)\n\t\t\t{\n\t\t\t\tuint8_t idx = uint8_t(frameBuffer.m_swapChain->GetCurrentBackBufferIndex() );\n\t\t\t\tframeBuffer.setState(m_commandList, idx, D3D12_RESOURCE_STATE_PRESENT);\n\t\t\t}\n\t\t}\n#endif // BX_PLATFORM_WINDOWS\n\n\t\tm_backBufferColorFence[m_backBufferColorIdx] = kick();\n\t}\n\n} /* namespace d3d12 */ } // namespace bgfx\n\n#else\n\nnamespace bgfx { namespace d3d12\n{\n\tRendererContextI* rendererCreate(const Init& _init)\n\t{\n\t\tBX_UNUSED(_init);\n\t\treturn NULL;\n\t}\n\n\tvoid rendererDestroy()\n\t{\n\t}\n} /* namespace d3d12 */ } // namespace bgfx\n\n#endif // BGFX_CONFIG_RENDERER_DIRECT3D12\n', 'message': 'D3D11: Fixed compute image mip selection.\n', 'author_name': 'Branimir Karadžić', 'lang': 'cpp'}