BCDirectCompute.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. //-------------------------------------------------------------------------------------
  2. // BCDirectCompute.cpp
  3. //
  4. // Direct3D 11 Compute Shader BC Compressor
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //-------------------------------------------------------------------------------------
  13. #include "directxtexp.h"
  14. #include "BCDirectCompute.h"
  15. #if defined(_DEBUG) || defined(PROFILE)
  16. #pragma comment(lib,"dxguid.lib")
  17. #endif
  18. using Microsoft::WRL::ComPtr;
  19. namespace
  20. {
  21. #include "Shaders\Compiled\BC7Encode_EncodeBlockCS.inc"
  22. #include "Shaders\Compiled\BC7Encode_TryMode02CS.inc"
  23. #include "Shaders\Compiled\BC7Encode_TryMode137CS.inc"
  24. #include "Shaders\Compiled\BC7Encode_TryMode456CS.inc"
  25. #include "Shaders\Compiled\BC6HEncode_EncodeBlockCS.inc"
  26. #include "Shaders\Compiled\BC6HEncode_TryModeG10CS.inc"
  27. #include "Shaders\Compiled\BC6HEncode_TryModeLE10CS.inc"
  28. struct BufferBC6HBC7
  29. {
  30. UINT color[4];
  31. };
  32. struct ConstantsBC6HBC7
  33. {
  34. UINT tex_width;
  35. UINT num_block_x;
  36. UINT format;
  37. UINT mode_id;
  38. UINT start_block_id;
  39. UINT num_total_blocks;
  40. float alpha_weight;
  41. UINT reserved;
  42. };
  43. static_assert( sizeof(ConstantsBC6HBC7) == sizeof(UINT)*8, "Constant buffer size mismatch" );
  44. inline void RunComputeShader( ID3D11DeviceContext* pContext,
  45. ID3D11ComputeShader* shader,
  46. ID3D11ShaderResourceView** pSRVs,
  47. UINT srvCount,
  48. ID3D11Buffer* pCB,
  49. ID3D11UnorderedAccessView* pUAV,
  50. UINT X )
  51. {
  52. // Force UAV to nullptr before setting SRV since we are swapping buffers
  53. ID3D11UnorderedAccessView* nullUAV = nullptr;
  54. pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr );
  55. pContext->CSSetShader( shader, nullptr, 0 );
  56. pContext->CSSetShaderResources( 0, srvCount, pSRVs );
  57. pContext->CSSetUnorderedAccessViews( 0, 1, &pUAV, nullptr );
  58. pContext->CSSetConstantBuffers( 0, 1, &pCB );
  59. pContext->Dispatch( X, 1, 1 );
  60. }
  61. inline void ResetContext( ID3D11DeviceContext* pContext )
  62. {
  63. ID3D11UnorderedAccessView* nullUAV = nullptr;
  64. pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr );
  65. ID3D11ShaderResourceView* nullSRV[3] = { nullptr, nullptr, nullptr };
  66. pContext->CSSetShaderResources( 0, 3, nullSRV );
  67. ID3D11Buffer* nullBuffer[1] = { nullptr };
  68. pContext->CSSetConstantBuffers( 0, 1, nullBuffer );
  69. }
  70. };
  71. namespace DirectX
  72. {
  73. GPUCompressBC::GPUCompressBC() :
  74. m_bcformat(DXGI_FORMAT_UNKNOWN),
  75. m_srcformat(DXGI_FORMAT_UNKNOWN),
  76. m_alphaWeight(1.f),
  77. m_width(0),
  78. m_height(0)
  79. {
  80. }
  81. //-------------------------------------------------------------------------------------
  82. _Use_decl_annotations_
  83. HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
  84. {
  85. if ( !pDevice )
  86. return E_INVALIDARG;
  87. // Check for DirectCompute support
  88. D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
  89. if ( fl < D3D_FEATURE_LEVEL_10_0 )
  90. {
  91. // DirectCompute not supported on Feature Level 9.x hardware
  92. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  93. }
  94. if ( fl < D3D_FEATURE_LEVEL_11_0 )
  95. {
  96. // DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
  97. D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
  98. HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
  99. if ( FAILED(hr) )
  100. {
  101. memset( &hwopts, 0, sizeof(hwopts) );
  102. }
  103. if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x )
  104. {
  105. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  106. }
  107. }
  108. // Save a device reference and obtain immediate context
  109. m_device = pDevice;
  110. pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
  111. assert( m_context );
  112. //--- Create compute shader library: BC6H -----------------------------------------
  113. // Modes 11-14
  114. HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
  115. if ( FAILED(hr) )
  116. return hr;
  117. // Modes 1-10
  118. hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
  119. if ( FAILED(hr) )
  120. return hr;
  121. // Encode
  122. hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
  123. if ( FAILED(hr) )
  124. return hr;
  125. //--- Create compute shader library: BC7 ------------------------------------------
  126. // Modes 4, 5, 6
  127. hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
  128. if ( FAILED(hr) )
  129. return hr;
  130. // Modes 1, 3, 7
  131. hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
  132. if ( FAILED(hr) )
  133. return hr;
  134. // Modes 0, 2
  135. hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
  136. if ( FAILED(hr) )
  137. return hr;
  138. // Encode
  139. hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
  140. if ( FAILED(hr) )
  141. return hr;
  142. return S_OK;
  143. }
  144. //-------------------------------------------------------------------------------------
  145. _Use_decl_annotations_
  146. HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight )
  147. {
  148. if ( !width || !height || alphaWeight < 0.f )
  149. return E_INVALIDARG;
  150. #ifdef _M_X64
  151. if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
  152. return E_INVALIDARG;
  153. #endif
  154. m_width = width;
  155. m_height = height;
  156. m_alphaWeight = alphaWeight;
  157. size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 );
  158. size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 );
  159. size_t num_blocks = xblocks * yblocks;
  160. switch( format )
  161. {
  162. // BC6H GPU compressor takes RGBAF32 as input
  163. case DXGI_FORMAT_BC6H_TYPELESS:
  164. case DXGI_FORMAT_BC6H_UF16:
  165. case DXGI_FORMAT_BC6H_SF16:
  166. m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT;
  167. break;
  168. // BC7 GPU compressor takes RGBA32 as input
  169. case DXGI_FORMAT_BC7_TYPELESS:
  170. case DXGI_FORMAT_BC7_UNORM:
  171. m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM;
  172. break;
  173. case DXGI_FORMAT_BC7_UNORM_SRGB:
  174. m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  175. break;
  176. default:
  177. m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
  178. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  179. }
  180. m_bcformat = format;
  181. auto pDevice = m_device.Get();
  182. if ( !pDevice )
  183. return E_POINTER;
  184. // Create structured buffers
  185. size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
  186. {
  187. D3D11_BUFFER_DESC desc;
  188. memset( &desc, 0, sizeof(desc) );
  189. desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
  190. desc.Usage = D3D11_USAGE_DEFAULT;
  191. desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
  192. desc.StructureByteStride = sizeof( BufferBC6HBC7 );
  193. desc.ByteWidth = static_cast<UINT>( bufferSize );
  194. HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
  195. if ( FAILED(hr) )
  196. {
  197. return hr;
  198. }
  199. hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
  200. if ( FAILED(hr) )
  201. {
  202. return hr;
  203. }
  204. hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
  205. if ( FAILED(hr) )
  206. {
  207. return hr;
  208. }
  209. }
  210. // Create staging output buffer
  211. {
  212. D3D11_BUFFER_DESC desc;
  213. memset( &desc, 0, sizeof(desc) );
  214. desc.Usage = D3D11_USAGE_STAGING;
  215. desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  216. desc.ByteWidth = static_cast<UINT>( bufferSize );
  217. HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() );
  218. if ( FAILED(hr) )
  219. {
  220. return hr;
  221. }
  222. }
  223. // Create constant buffer
  224. {
  225. D3D11_BUFFER_DESC desc;
  226. memset( &desc, 0, sizeof(desc) );
  227. desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  228. desc.Usage = D3D11_USAGE_DYNAMIC;
  229. desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  230. desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
  231. HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
  232. if ( FAILED(hr) )
  233. {
  234. return hr;
  235. }
  236. }
  237. // Create shader resource views
  238. {
  239. D3D11_SHADER_RESOURCE_VIEW_DESC desc;
  240. memset( &desc, 0, sizeof(desc) );
  241. desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
  242. desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
  243. HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
  244. if ( FAILED(hr) )
  245. {
  246. return hr;
  247. }
  248. hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
  249. if ( FAILED(hr) )
  250. {
  251. return hr;
  252. }
  253. }
  254. // Create unordered access views
  255. {
  256. D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
  257. memset( &desc, 0, sizeof(desc) );
  258. desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
  259. desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
  260. HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
  261. if ( FAILED(hr) )
  262. {
  263. return hr;
  264. }
  265. hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
  266. if ( FAILED(hr) )
  267. {
  268. return hr;
  269. }
  270. hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
  271. if ( FAILED(hr) )
  272. {
  273. return hr;
  274. }
  275. }
  276. return S_OK;
  277. }
  278. //-------------------------------------------------------------------------------------
  279. _Use_decl_annotations_
  280. HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
  281. {
  282. if ( !srcImage.pixels || !destImage.pixels )
  283. return E_INVALIDARG;
  284. if ( srcImage.width != destImage.width
  285. || srcImage.height != destImage.height
  286. || srcImage.width != m_width
  287. || srcImage.height != m_height
  288. || srcImage.format != m_srcformat
  289. || destImage.format != m_bcformat )
  290. {
  291. return E_UNEXPECTED;
  292. }
  293. //--- Create input texture --------------------------------------------------------
  294. auto pDevice = m_device.Get();
  295. if ( !pDevice )
  296. return E_POINTER;
  297. // We need to avoid the hardware doing additional colorspace conversion
  298. DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
  299. ComPtr<ID3D11Texture2D> sourceTex;
  300. {
  301. D3D11_TEXTURE2D_DESC desc;
  302. memset( &desc, 0, sizeof(desc) );
  303. desc.Width = static_cast<UINT>( srcImage.width );
  304. desc.Height = static_cast<UINT>( srcImage.height );
  305. desc.MipLevels = 1;
  306. desc.ArraySize = 1;
  307. desc.Format = inputFormat;
  308. desc.SampleDesc.Count = 1;
  309. desc.Usage = D3D11_USAGE_DEFAULT;
  310. desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  311. D3D11_SUBRESOURCE_DATA initData;
  312. initData.pSysMem = srcImage.pixels;
  313. initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
  314. initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
  315. HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
  316. if ( FAILED(hr) )
  317. {
  318. return hr;
  319. }
  320. }
  321. ComPtr<ID3D11ShaderResourceView> sourceSRV;
  322. {
  323. D3D11_SHADER_RESOURCE_VIEW_DESC desc;
  324. memset( &desc, 0, sizeof(desc) );
  325. desc.Texture2D.MipLevels = 1;
  326. desc.Format = inputFormat;
  327. desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  328. HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
  329. if ( FAILED(hr) )
  330. {
  331. return hr;
  332. }
  333. }
  334. //--- Compress using DirectCompute ------------------------------------------------
  335. bool isbc7 = false;
  336. switch( m_bcformat )
  337. {
  338. case DXGI_FORMAT_BC6H_TYPELESS:
  339. case DXGI_FORMAT_BC6H_UF16:
  340. case DXGI_FORMAT_BC6H_SF16:
  341. break;
  342. case DXGI_FORMAT_BC7_TYPELESS:
  343. case DXGI_FORMAT_BC7_UNORM:
  344. case DXGI_FORMAT_BC7_UNORM_SRGB:
  345. isbc7 = true;
  346. break;
  347. default:
  348. return E_UNEXPECTED;
  349. }
  350. const UINT MAX_BLOCK_BATCH = 64;
  351. auto pContext = m_context.Get();
  352. if ( !pContext )
  353. return E_UNEXPECTED;
  354. size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 );
  355. size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 );
  356. UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks );
  357. UINT num_blocks = num_total_blocks;
  358. int start_block_id = 0;
  359. while (num_blocks > 0)
  360. {
  361. UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH );
  362. UINT uThreadGroupCount = n;
  363. {
  364. D3D11_MAPPED_SUBRESOURCE mapped;
  365. HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
  366. if ( FAILED(hr) )
  367. return hr;
  368. ConstantsBC6HBC7 param;
  369. param.tex_width = static_cast<UINT>( srcImage.width );
  370. param.num_block_x = static_cast<UINT>( xblocks );
  371. param.format = m_bcformat;
  372. param.mode_id = 0;
  373. param.start_block_id = start_block_id;
  374. param.num_total_blocks = num_total_blocks;
  375. param.alpha_weight = m_alphaWeight;
  376. memcpy( mapped.pData, &param, sizeof( param ) );
  377. pContext->Unmap( m_constBuffer.Get(), 0 );
  378. }
  379. if ( isbc7 )
  380. {
  381. //--- BC7 -----------------------------------------------------------------
  382. ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
  383. RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
  384. m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
  385. for ( UINT i = 0; i < 3; ++i )
  386. {
  387. static const UINT modes[] = { 1, 3, 7 };
  388. {
  389. D3D11_MAPPED_SUBRESOURCE mapped;
  390. HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
  391. if ( FAILED(hr) )
  392. {
  393. ResetContext( pContext );
  394. return hr;
  395. }
  396. ConstantsBC6HBC7 param;
  397. param.tex_width = static_cast<UINT>( srcImage.width );
  398. param.num_block_x = static_cast<UINT>( xblocks );
  399. param.format = m_bcformat;
  400. param.mode_id = modes[i];
  401. param.start_block_id = start_block_id;
  402. param.num_total_blocks = num_total_blocks;
  403. param.alpha_weight = m_alphaWeight;
  404. memcpy( mapped.pData, &param, sizeof( param ) );
  405. pContext->Unmap( m_constBuffer.Get(), 0 );
  406. }
  407. pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
  408. RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
  409. (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
  410. }
  411. for ( UINT i = 0; i < 2; ++i )
  412. {
  413. static const UINT modes[] = { 0, 2 };
  414. {
  415. D3D11_MAPPED_SUBRESOURCE mapped;
  416. HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
  417. if ( FAILED(hr) )
  418. {
  419. ResetContext( pContext );
  420. return hr;
  421. }
  422. ConstantsBC6HBC7 param;
  423. param.tex_width = static_cast<UINT>( srcImage.width );
  424. param.num_block_x = static_cast<UINT>( xblocks );
  425. param.format = m_bcformat;
  426. param.mode_id = modes[i];
  427. param.start_block_id = start_block_id;
  428. param.num_total_blocks = num_total_blocks;
  429. param.alpha_weight = m_alphaWeight;
  430. memcpy( mapped.pData, &param, sizeof( param ) );
  431. pContext->Unmap( m_constBuffer.Get(), 0 );
  432. }
  433. pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
  434. RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
  435. (i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
  436. }
  437. pSRVs[1] = m_err2SRV.Get();
  438. RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
  439. m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
  440. }
  441. else
  442. {
  443. //--- BC6H ----------------------------------------------------------------
  444. ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
  445. RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
  446. m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
  447. for ( UINT i = 0; i < 10; ++i )
  448. {
  449. {
  450. D3D11_MAPPED_SUBRESOURCE mapped;
  451. HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
  452. if ( FAILED(hr) )
  453. {
  454. ResetContext( pContext );
  455. return hr;
  456. }
  457. ConstantsBC6HBC7 param;
  458. param.tex_width = static_cast<UINT>( srcImage.width );
  459. param.num_block_x = static_cast<UINT>( xblocks );
  460. param.format = m_bcformat;
  461. param.mode_id = i;
  462. param.start_block_id = start_block_id;
  463. param.num_total_blocks = num_total_blocks;
  464. memcpy( mapped.pData, &param, sizeof( param ) );
  465. pContext->Unmap( m_constBuffer.Get(), 0 );
  466. }
  467. pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
  468. RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
  469. (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
  470. }
  471. pSRVs[1] = m_err1SRV.Get();
  472. RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
  473. m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
  474. }
  475. start_block_id += n;
  476. num_blocks -= n;
  477. }
  478. ResetContext( pContext );
  479. //--- Copy output texture back to CPU ---------------------------------------------
  480. pContext->CopyResource( m_outputCPU.Get(), m_output.Get() );
  481. D3D11_MAPPED_SUBRESOURCE mapped;
  482. HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
  483. if ( SUCCEEDED(hr) )
  484. {
  485. const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData );
  486. uint8_t *pDest = destImage.pixels;
  487. size_t pitch = xblocks * sizeof( BufferBC6HBC7 );
  488. size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 );
  489. for( size_t h = 0; h < rows; ++h )
  490. {
  491. memcpy( pDest, pSrc, destImage.rowPitch );
  492. pSrc += pitch;
  493. pDest += destImage.rowPitch;
  494. }
  495. pContext->Unmap( m_outputCPU.Get(), 0 );
  496. }
  497. return hr;
  498. }
  499. }; // namespace