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