From c93d8db5231abc03adb419c23c8854d794f8475b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 24 Aug 2015 14:52:21 -0700 Subject: [PATCH 1/7] Added program refcounting. --- src/bgfx_p.h | 54 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 1d75ef87..d192d684 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2733,6 +2733,15 @@ namespace bgfx return invalid; } + ProgramHashMap::const_iterator it = m_programHashMap.find(uint32_t(_fsh.idx<<16)|_vsh.idx); + if (it != m_programHashMap.end() ) + { + ProgramHandle handle = it->second; + ProgramRef& pr = m_programRef[handle.idx]; + ++pr.m_refCount; + return handle; + } + const ShaderRef& vsr = m_shaderRef[_vsh.idx]; const ShaderRef& fsr = m_shaderRef[_fsh.idx]; if (vsr.m_hash != fsr.m_hash) @@ -2753,6 +2762,9 @@ namespace bgfx ProgramRef& pr = m_programRef[handle.idx]; pr.m_vsh = _vsh; pr.m_fsh = _fsh; + pr.m_refCount = 1; + + m_programHashMap.insert(stl::make_pair(uint32_t(_fsh.idx<<16)|_vsh.idx, handle) ); CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateProgram); cmdbuf.write(handle); @@ -2778,6 +2790,15 @@ namespace bgfx return invalid; } + ProgramHashMap::const_iterator it = m_programHashMap.find(_vsh.idx); + if (it != m_programHashMap.end() ) + { + ProgramHandle handle = it->second; + ProgramRef& pr = m_programRef[handle.idx]; + ++pr.m_refCount; + return handle; + } + ProgramHandle handle; handle.idx = m_programHandle.alloc(); @@ -2789,6 +2810,7 @@ namespace bgfx pr.m_vsh = _vsh; ShaderHandle fsh = BGFX_INVALID_HANDLE; pr.m_fsh = fsh; + pr.m_refCount = 1; CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateProgram); cmdbuf.write(handle); @@ -2808,16 +2830,24 @@ namespace bgfx { BGFX_CHECK_HANDLE("destroyProgram", m_programHandle, _handle); - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyProgram); - cmdbuf.write(_handle); - m_submit->free(_handle); - - const ProgramRef& pr = m_programRef[_handle.idx]; - shaderDecRef(pr.m_vsh); - - if (isValid(pr.m_fsh) ) + ProgramRef& pr = m_programRef[_handle.idx]; + int32_t refs = --pr.m_refCount; + if (0 == refs) { - shaderDecRef(pr.m_fsh); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyProgram); + cmdbuf.write(_handle); + m_submit->free(_handle); + + shaderDecRef(pr.m_vsh); + uint32_t hash = pr.m_vsh.idx; + + if (isValid(pr.m_fsh) ) + { + shaderDecRef(pr.m_fsh); + hash |= pr.m_fsh.idx << 16; + } + + m_programHashMap.erase(m_programHashMap.find(hash) ); } } @@ -3593,6 +3623,7 @@ namespace bgfx { ShaderHandle m_vsh; ShaderHandle m_fsh; + int16_t m_refCount; }; struct UniformRef @@ -3623,8 +3654,13 @@ namespace bgfx typedef stl::unordered_map UniformHashMap; UniformHashMap m_uniformHashMap; UniformRef m_uniformRef[BGFX_CONFIG_MAX_UNIFORMS]; + ShaderRef m_shaderRef[BGFX_CONFIG_MAX_SHADERS]; + + typedef stl::unordered_map ProgramHashMap; + ProgramHashMap m_programHashMap; ProgramRef m_programRef[BGFX_CONFIG_MAX_PROGRAMS]; + TextureRef m_textureRef[BGFX_CONFIG_MAX_TEXTURES]; FrameBufferRef m_frameBufferRef[BGFX_CONFIG_MAX_FRAME_BUFFERS]; VertexDeclRef m_declRef; From 7acf2b2616b71caa2b2786aaef2fbd4ea8b41dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 24 Aug 2015 15:40:11 -0700 Subject: [PATCH 2/7] Fixed compute program. --- src/bgfx_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index d192d684..87f54127 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2812,6 +2812,8 @@ namespace bgfx pr.m_fsh = fsh; pr.m_refCount = 1; + m_programHashMap.insert(stl::make_pair(uint32_t(_vsh.idx), handle) ); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateProgram); cmdbuf.write(handle); cmdbuf.write(_vsh); From fa7cd66f71f4d7a6ee42b9d8a85a28ba209a6101 Mon Sep 17 00:00:00 2001 From: Dario Manesku Date: Tue, 25 Aug 2015 02:49:39 +0200 Subject: [PATCH 3/7] Fixing encodeAsInt field. Had two problems: 1# Bit field didn't got updated for Uint10. 2# Shifting by 8 on uint8_t. Problem was introduced on: 8da579ff99a62318682f1e913f5e0d9f6b8f8b2c. --- src/vertexdecl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vertexdecl.cpp b/src/vertexdecl.cpp index f26c5f86..7bc8f616 100644 --- a/src/vertexdecl.cpp +++ b/src/vertexdecl.cpp @@ -111,10 +111,10 @@ namespace bgfx VertexDecl& VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized, bool _asInt) { - const uint8_t encodedNorm = (_normalized&1)<<7; - const uint8_t encodedType = (_type&7)<<3; - const uint8_t encodedNum = (_num-1)&3; - const uint8_t encodeAsInt = (_asInt&(!!"\x1\x1\x0\x0"[_type]) )<<8; + const uint32_t encodedNorm = (_normalized&1)<<7; + const uint32_t encodedType = (_type&7)<<3; + const uint32_t encodedNum = (_num-1)&3; + const uint32_t encodeAsInt = (_asInt&(!!"\x1\x1\x1\x0\x0"[_type]) )<<8; m_attributes[_attrib] = encodedNorm|encodedType|encodedNum|encodeAsInt; m_offset[_attrib] = m_stride; From 3bee406cb5105fbb1f0b7349dec7fdb73dc333da Mon Sep 17 00:00:00 2001 From: Dario Manesku Date: Tue, 25 Aug 2015 03:37:04 +0200 Subject: [PATCH 4/7] Maybe it makes more sense for fields to be uint16_t since the result, m_attributes, is uint16_t. --- src/vertexdecl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vertexdecl.cpp b/src/vertexdecl.cpp index 7bc8f616..470cb567 100644 --- a/src/vertexdecl.cpp +++ b/src/vertexdecl.cpp @@ -111,10 +111,10 @@ namespace bgfx VertexDecl& VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized, bool _asInt) { - const uint32_t encodedNorm = (_normalized&1)<<7; - const uint32_t encodedType = (_type&7)<<3; - const uint32_t encodedNum = (_num-1)&3; - const uint32_t encodeAsInt = (_asInt&(!!"\x1\x1\x1\x0\x0"[_type]) )<<8; + const uint16_t encodedNorm = (_normalized&1)<<7; + const uint16_t encodedType = (_type&7)<<3; + const uint16_t encodedNum = (_num-1)&3; + const uint16_t encodeAsInt = (_asInt&(!!"\x1\x1\x1\x0\x0"[_type]) )<<8; m_attributes[_attrib] = encodedNorm|encodedType|encodedNum|encodeAsInt; m_offset[_attrib] = m_stride; From 631103bfa8f58d8a1de8d9f3ab0b2c9a3ef9c641 Mon Sep 17 00:00:00 2001 From: Richard Gale Date: Mon, 24 Aug 2015 19:12:01 -0700 Subject: [PATCH 5/7] Adds suspend event mapped to application lifecycle On Android WillSuspend and WillResume maps to focus and DidSuspend and DidResume maps to onPause and onResume. On OSX WillSuspend and DidSuspend maps to resign key, WillResume and DidResumg maps to make key. --- examples/common/entry/entry.cpp | 5 ++- examples/common/entry/entry.h | 16 +++++++- examples/common/entry/entry_android.cpp | 16 ++++++++ examples/common/entry/entry_asmjs.cpp | 54 +++++++++++++++++++++---- examples/common/entry/entry_ios.mm | 4 ++ examples/common/entry/entry_osx.mm | 28 +++++++++++++ examples/common/entry/entry_p.h | 15 +++++++ 7 files changed, 129 insertions(+), 9 deletions(-) diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index 94f8e4de..773ec5f4 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -464,7 +464,10 @@ BX_PRAGMA_DIAGNOSTIC_POP(); case Event::Window: break; - default: + case Event::Suspend: + break; + + default: break; } } diff --git a/examples/common/entry/entry.h b/examples/common/entry/entry.h index 373808b6..13b85262 100644 --- a/examples/common/entry/entry.h +++ b/examples/common/entry/entry.h @@ -62,7 +62,8 @@ namespace entry }; struct Modifier - { enum Enum + { + enum Enum { None = 0, LeftAlt = 0x01, @@ -187,6 +188,19 @@ namespace entry }; }; + struct Suspend + { + enum Enum + { + WillSuspend, + DidSuspend, + WillResume, + DidResume, + + Count + }; + }; + const char* getName(Key::Enum _key); struct MouseState diff --git a/examples/common/entry/entry_android.cpp b/examples/common/entry/entry_android.cpp index 2d7c852c..f16b1e5d 100644 --- a/examples/common/entry/entry_android.cpp +++ b/examples/common/entry/entry_android.cpp @@ -181,14 +181,22 @@ namespace entry break; case APP_CMD_GAINED_FOCUS: + { // Command from main thread: the app's activity window has gained // input focus. + WindowHandle defaultWindow = { 0 }; + m_eventQueue.postSuspendEvent(defaultWindow, Suspend::WillResume); break; + } case APP_CMD_LOST_FOCUS: + { // Command from main thread: the app's activity window has lost // input focus. + WindowHandle defaultWindow = { 0 }; + m_eventQueue.postSuspendEvent(defaultWindow, Suspend::WillSuspend); break; + } case APP_CMD_CONFIG_CHANGED: // Command from main thread: the current device configuration has changed. @@ -204,8 +212,12 @@ namespace entry break; case APP_CMD_RESUME: + { // Command from main thread: the app's activity has been resumed. + WindowHandle defaultWindow = { 0 }; + m_eventQueue.postSuspendEvent(defaultWindow, Suspend::DidResume); break; + } case APP_CMD_SAVE_STATE: // Command from main thread: the app should generate a new saved state @@ -216,8 +228,12 @@ namespace entry break; case APP_CMD_PAUSE: + { // Command from main thread: the app's activity has been paused. + WindowHandle defaultWindow = { 0 }; + m_eventQueue.postSuspendEvent(defaultWindow, Suspend::DidSuspend); break; + } case APP_CMD_STOP: // Command from main thread: the app's activity has been stopped. diff --git a/examples/common/entry/entry_asmjs.cpp b/examples/common/entry/entry_asmjs.cpp index 73e7483c..f5c3dc62 100644 --- a/examples/common/entry/entry_asmjs.cpp +++ b/examples/common/entry/entry_asmjs.cpp @@ -109,15 +109,20 @@ namespace entry emscripten_request_fullscreen_strategy("#canvas", false, &fullscreenStrategy); + emscripten_set_focus_callback(NULL, this, true, focusCb); + emscripten_set_focusin_callback(NULL, this, true, focusCb); + emscripten_set_focusout_callback(NULL, this, true, focusCb); + int32_t result = main(_argc, _argv); return result; } - static EM_BOOL mouseCb(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); - static EM_BOOL wheelCb(int eventType, const EmscriptenWheelEvent* wheelEvent, void* userData); - static EM_BOOL keyCb(int eventType, const EmscriptenKeyboardEvent* keyEvent, void* userData); - static EM_BOOL resizeCb(int eventType, const EmscriptenUiEvent* uiEvent, void* userData); - static EM_BOOL canvasResizeCb(int eventType, const void* reserved, void *userData); + static EM_BOOL mouseCb(int eventType, const EmscriptenMouseEvent* event, void* userData); + static EM_BOOL wheelCb(int eventType, const EmscriptenWheelEvent* event, void* userData); + static EM_BOOL keyCb(int eventType, const EmscriptenKeyboardEvent* event, void* userData); + static EM_BOOL resizeCb(int eventType, const EmscriptenUiEvent* event, void* userData); + static EM_BOOL canvasResizeCb(int eventType, const void* reserved, void* userData); + static EM_BOOL focusCb(int eventType, const EmscriptenFocusEvent* event, void* userData); EventQueue m_eventQueue; @@ -284,18 +289,53 @@ namespace entry return false; } - EM_BOOL Context::resizeCb(int eventType, const EmscriptenUiEvent* event, void *userData) + EM_BOOL Context::resizeCb(int eventType, const EmscriptenUiEvent* event, void* userData) { BX_UNUSED(eventType, event, userData); return false; } - EM_BOOL Context::canvasResizeCb(int eventType, const void* reserved, void *userData) + EM_BOOL Context::canvasResizeCb(int eventType, const void* reserved, void* userData) { BX_UNUSED(eventType, reserved, userData); return false; } + EM_BOOL Context::focusCb(int eventType, const EmscriptenFocusEvent* event, void* userData) + { + printf("focusCb %d", eventType); + BX_UNUSED(event, userData); + + if (event) + { + switch (eventType) + { + case EMSCRIPTEN_EVENT_BLUR: + { + s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend); + return true; + } + case EMSCRIPTEN_EVENT_FOCUS: + { + s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume); + return true; + } + case EMSCRIPTEN_EVENT_FOCUSIN: + { + s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume); + return true; + } + case EMSCRIPTEN_EVENT_FOCUSOUT: + { + s_ctx.m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend); + return true; + } + } + } + + return false; + } + const Event* poll() { entry_emscripten_yield(); diff --git a/examples/common/entry/entry_ios.mm b/examples/common/entry/entry_ios.mm index f721bfa0..d2392d89 100644 --- a/examples/common/entry/entry_ios.mm +++ b/examples/common/entry/entry_ios.mm @@ -323,22 +323,26 @@ static void* m_device = NULL; - (void)applicationWillResignActive:(UIApplication *)application { BX_UNUSED(application); + s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend); [m_view stop]; } - (void)applicationDidEnterBackground:(UIApplication *)application { BX_UNUSED(application); + s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend); } - (void)applicationWillEnterForeground:(UIApplication *)application { BX_UNUSED(application); + s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume); } - (void)applicationDidBecomeActive:(UIApplication *)application { BX_UNUSED(application); + s_ctx->m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume); [m_view start]; } diff --git a/examples/common/entry/entry_osx.mm b/examples/common/entry/entry_osx.mm index a43c47ab..6446e425 100644 --- a/examples/common/entry/entry_osx.mm +++ b/examples/common/entry/entry_osx.mm @@ -39,6 +39,8 @@ - (void)windowWillClose:(NSNotification*)notification; - (BOOL)windowShouldClose:(NSWindow*)window; - (void)windowDidResize:(NSNotification*)notification; +- (void)windowDidBecomeKey:(NSNotification *)notification; +- (void)windowDidResignKey:(NSNotification *)notification; @end @@ -384,6 +386,18 @@ namespace entry m_eventQueue.postMouseEvent(s_defaultWindow, m_mx, m_my, m_scroll, MouseButton::Right, false); } + void windowDidBecomeKey() + { + m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillResume); + m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidResume); + } + + void windowDidResignKey() + { + m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::WillSuspend); + m_eventQueue.postSuspendEvent(s_defaultWindow, Suspend::DidSuspend); + } + int32_t run(int _argc, char** _argv) { [NSApplication sharedApplication]; @@ -723,6 +737,20 @@ namespace entry s_ctx.windowDidResize(); } +- (void)windowDidBecomeKey:(NSNotification*)notification +{ + BX_UNUSED(notification); + using namespace entry; + s_ctx.windowDidBecomeKey(); +} + +- (void)windowDidResignKey:(NSNotification*)notification +{ + BX_UNUSED(notification); + using namespace entry; + s_ctx.windowDidResignKey(); +} + @end int main(int _argc, char** _argv) diff --git a/examples/common/entry/entry_p.h b/examples/common/entry/entry_p.h index d0ba7331..e1a1a514 100644 --- a/examples/common/entry/entry_p.h +++ b/examples/common/entry/entry_p.h @@ -75,6 +75,7 @@ namespace entry Mouse, Size, Window, + Suspend, }; Event(Enum _type) @@ -154,6 +155,13 @@ namespace entry void* m_nwh; }; + struct SuspendEvent : public Event + { + ENTRY_IMPLEMENT_EVENT(SuspendEvent, Event::Suspend); + + Suspend::Enum m_state; + }; + const Event* poll(); const Event* poll(WindowHandle _handle); void release(const Event* _event); @@ -248,6 +256,13 @@ namespace entry m_queue.push(ev); } + void postSuspendEvent(WindowHandle _handle, Suspend::Enum _state) + { + SuspendEvent* ev = new SuspendEvent(_handle); + ev->m_state = _state; + m_queue.push(ev); + } + const Event* poll() { return m_queue.pop(); From 32ab287ddc0d1060b656148154c8375e2284af71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 24 Aug 2015 21:38:45 -0700 Subject: [PATCH 6/7] Fixed VS2008 build. --- 3rdparty/dxsdk/include/d3dcommon.h | 51 ++++++++++++++++++++++++++++++ src/renderer_d3d12.cpp | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/3rdparty/dxsdk/include/d3dcommon.h b/3rdparty/dxsdk/include/d3dcommon.h index 16a55572..f1c674c4 100644 --- a/3rdparty/dxsdk/include/d3dcommon.h +++ b/3rdparty/dxsdk/include/d3dcommon.h @@ -37,6 +37,57 @@ #pragma once #endif +#if _MSC_VER <= 1600 +#ifndef VS2008_SAL_COMPAT +#define VS2008_SAL_COMPAT +// BK - SAL compatibility for VS2008 + +#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \ + extern "C++" { \ + inline ENUMTYPE operator | (ENUMTYPE _a, ENUMTYPE _b) { return ENUMTYPE ( ( (int) _a) | ( (int)_b) ); } \ + inline ENUMTYPE operator |= (ENUMTYPE &_a, ENUMTYPE _b) { return (ENUMTYPE &)( ( (int &)_a) |= ( (int)_b) ); } \ + inline ENUMTYPE operator & (ENUMTYPE _a, ENUMTYPE _b) { return ENUMTYPE ( ( (int) _a) & ( (int)_b) ); } \ + inline ENUMTYPE operator &= (ENUMTYPE &_a, ENUMTYPE _b) { return (ENUMTYPE &)( ( (int &)_a) &= ( (int)_b) ); } \ + inline ENUMTYPE operator ~ (ENUMTYPE _a) { return (ENUMTYPE) (~( (int) _a) ); } \ + inline ENUMTYPE operator ^ (ENUMTYPE _a, ENUMTYPE _b) { return ENUMTYPE ( ( (int) _a) ^ ( (int)_b) ); } \ + inline ENUMTYPE operator ^= (ENUMTYPE &_a, ENUMTYPE _b) { return (ENUMTYPE &)( ( (int &)_a) ^= ( (int)_b) ); } \ + } + +#undef _Out_ +#define _Out_ +#undef _In_ +#define _In_ +#undef _Always_ +#define _Always_(annos) +#define _In_reads_(size) +#define _In_reads_opt_(size) +#define _In_reads_bytes_(size) +#define _In_reads_bytes_opt_(size) +#define _Inout_updates_bytes_(size) +#define _Out_writes_(size) +#define _Out_writes_opt_(size) +#define _Out_writes_to_opt_(size,count) +#define _Out_writes_bytes_(size) +#define _Out_writes_bytes_opt_(size) +#define _Out_writes_bytes_to_(size,count) +#define _Outptr_ +#define _Outptr_opt_result_maybenull_ +#define _Outptr_opt_result_bytebuffer_(size) +#define _Outptr_result_maybenull_ +#define _Outptr_result_bytebuffer_(size) +#define _Out_writes_all_opt_(size) +#define _COM_Outptr_ +#define _COM_Outptr_opt_ +#define _COM_Outptr_opt_result_maybenull_ +#define _Field_size_(size) +#define _Field_size_full_(size) +#define _Field_size_opt_(size) +#define _Field_size_bytes_full_(size) +#define nullptr NULL + +#endif // BK - VS2008_SAL_COMPAT +#endif // + /* Forward Declarations */ #ifndef __ID3D10Blob_FWD_DEFINED__ diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index d789a2a5..7d8b3db9 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -4186,7 +4186,7 @@ data.NumQualityLevels = 0; ScratchBufferD3D12& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx]; scratchBuffer.reset(gpuHandle); - D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = {}; + D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = UINT64_C(0); StateCacheLru bindLru; setResourceBarrier(m_commandList From 3853645bf6f3bc0e35469f591d73c3dde4225002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 24 Aug 2015 22:23:39 -0700 Subject: [PATCH 7/7] Cleanup. --- src/image.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/image.cpp b/src/image.cpp index fe1d361b..e48d2cfc 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -12,13 +12,15 @@ namespace bgfx { static const ImageBlockInfo s_imageBlockInfo[] = { - // +------------------ bits per pixel - // | +--------------- block width - // | | +------------ block height - // | | | +-------- block size - // | | | | +----- min blocks x - // | | | | | +-- min blocks y - // | | | | | | + // +--------------------------- bits per pixel + // | +------------------------ block width + // | | +--------------------- block height + // | | | +----------------- block size + // | | | | +-------------- min blocks x + // | | | | | +----------- min blocks y + // | | | | | | +------- depth bits + // | | | | | | | +---- stencil bits + // | | | | | | | | { 4, 4, 4, 8, 1, 1, 0, 0 }, // BC1 { 8, 4, 4, 16, 1, 1, 0, 0 }, // BC2 { 8, 4, 4, 16, 1, 1, 0, 0 }, // BC3