[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / guilib / D3DResource.cpp
blobcd6e0d2a86b1ba5e7607b92ea9dee058770aa4a2
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "D3DResource.h"
11 #include "GUIShaderDX.h"
12 #include "filesystem/File.h"
13 #include "rendering/dx/DeviceResources.h"
14 #include "rendering/dx/RenderContext.h"
15 #include "utils/log.h"
17 #include <d3dcompiler.h>
19 using namespace DirectX;
20 using namespace Microsoft::WRL;
22 #ifdef TARGET_WINDOWS_DESKTOP
23 #pragma comment(lib, "d3dcompiler.lib")
24 #endif
26 size_t CD3DHelper::BitsPerPixel(DXGI_FORMAT fmt)
28 switch (fmt)
30 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
31 case DXGI_FORMAT_R32G32B32A32_FLOAT:
32 case DXGI_FORMAT_R32G32B32A32_UINT:
33 case DXGI_FORMAT_R32G32B32A32_SINT:
34 return 128;
36 case DXGI_FORMAT_R32G32B32_TYPELESS:
37 case DXGI_FORMAT_R32G32B32_FLOAT:
38 case DXGI_FORMAT_R32G32B32_UINT:
39 case DXGI_FORMAT_R32G32B32_SINT:
40 return 96;
42 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
43 case DXGI_FORMAT_R16G16B16A16_FLOAT:
44 case DXGI_FORMAT_R16G16B16A16_UNORM:
45 case DXGI_FORMAT_R16G16B16A16_UINT:
46 case DXGI_FORMAT_R16G16B16A16_SNORM:
47 case DXGI_FORMAT_R16G16B16A16_SINT:
48 case DXGI_FORMAT_R32G32_TYPELESS:
49 case DXGI_FORMAT_R32G32_FLOAT:
50 case DXGI_FORMAT_R32G32_UINT:
51 case DXGI_FORMAT_R32G32_SINT:
52 case DXGI_FORMAT_R32G8X24_TYPELESS:
53 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
54 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
55 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
56 return 64;
58 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
59 case DXGI_FORMAT_R10G10B10A2_UNORM:
60 case DXGI_FORMAT_R10G10B10A2_UINT:
61 case DXGI_FORMAT_R11G11B10_FLOAT:
62 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
63 case DXGI_FORMAT_R8G8B8A8_UNORM:
64 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
65 case DXGI_FORMAT_R8G8B8A8_UINT:
66 case DXGI_FORMAT_R8G8B8A8_SNORM:
67 case DXGI_FORMAT_R8G8B8A8_SINT:
68 case DXGI_FORMAT_R16G16_TYPELESS:
69 case DXGI_FORMAT_R16G16_FLOAT:
70 case DXGI_FORMAT_R16G16_UNORM:
71 case DXGI_FORMAT_R16G16_UINT:
72 case DXGI_FORMAT_R16G16_SNORM:
73 case DXGI_FORMAT_R16G16_SINT:
74 case DXGI_FORMAT_R32_TYPELESS:
75 case DXGI_FORMAT_D32_FLOAT:
76 case DXGI_FORMAT_R32_FLOAT:
77 case DXGI_FORMAT_R32_UINT:
78 case DXGI_FORMAT_R32_SINT:
79 case DXGI_FORMAT_R24G8_TYPELESS:
80 case DXGI_FORMAT_D24_UNORM_S8_UINT:
81 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
82 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
83 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
84 case DXGI_FORMAT_R8G8_B8G8_UNORM:
85 case DXGI_FORMAT_G8R8_G8B8_UNORM:
86 case DXGI_FORMAT_B8G8R8A8_UNORM:
87 case DXGI_FORMAT_B8G8R8X8_UNORM:
88 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
89 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
90 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
91 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
92 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
93 return 32;
95 case DXGI_FORMAT_R8G8_TYPELESS:
96 case DXGI_FORMAT_R8G8_UNORM:
97 case DXGI_FORMAT_R8G8_UINT:
98 case DXGI_FORMAT_R8G8_SNORM:
99 case DXGI_FORMAT_R8G8_SINT:
100 case DXGI_FORMAT_R16_TYPELESS:
101 case DXGI_FORMAT_R16_FLOAT:
102 case DXGI_FORMAT_D16_UNORM:
103 case DXGI_FORMAT_R16_UNORM:
104 case DXGI_FORMAT_R16_UINT:
105 case DXGI_FORMAT_R16_SNORM:
106 case DXGI_FORMAT_R16_SINT:
107 case DXGI_FORMAT_B5G6R5_UNORM:
108 case DXGI_FORMAT_B5G5R5A1_UNORM:
109 case DXGI_FORMAT_B4G4R4A4_UNORM:
110 return 16;
112 case DXGI_FORMAT_R8_TYPELESS:
113 case DXGI_FORMAT_R8_UNORM:
114 case DXGI_FORMAT_R8_UINT:
115 case DXGI_FORMAT_R8_SNORM:
116 case DXGI_FORMAT_R8_SINT:
117 case DXGI_FORMAT_A8_UNORM:
118 return 8;
120 case DXGI_FORMAT_R1_UNORM:
121 return 1;
123 case DXGI_FORMAT_BC1_TYPELESS:
124 case DXGI_FORMAT_BC1_UNORM:
125 case DXGI_FORMAT_BC1_UNORM_SRGB:
126 case DXGI_FORMAT_BC4_TYPELESS:
127 case DXGI_FORMAT_BC4_UNORM:
128 case DXGI_FORMAT_BC4_SNORM:
129 return 4;
131 case DXGI_FORMAT_BC2_TYPELESS:
132 case DXGI_FORMAT_BC2_UNORM:
133 case DXGI_FORMAT_BC2_UNORM_SRGB:
134 case DXGI_FORMAT_BC3_TYPELESS:
135 case DXGI_FORMAT_BC3_UNORM:
136 case DXGI_FORMAT_BC3_UNORM_SRGB:
137 case DXGI_FORMAT_BC5_TYPELESS:
138 case DXGI_FORMAT_BC5_UNORM:
139 case DXGI_FORMAT_BC5_SNORM:
140 case DXGI_FORMAT_BC6H_TYPELESS:
141 case DXGI_FORMAT_BC6H_UF16:
142 case DXGI_FORMAT_BC6H_SF16:
143 case DXGI_FORMAT_BC7_TYPELESS:
144 case DXGI_FORMAT_BC7_UNORM:
145 case DXGI_FORMAT_BC7_UNORM_SRGB:
146 return 8;
148 default:
149 return 0;
153 void ID3DResource::Register()
155 if (!m_bRegistered)
156 DX::Windowing()->Register(this);
157 m_bRegistered = true;
160 void ID3DResource::Unregister()
162 if (m_bRegistered)
163 DX::Windowing()->Unregister(this);
164 m_bRegistered = false;
167 CD3DTexture::CD3DTexture()
169 m_width = 0;
170 m_height = 0;
171 m_mipLevels = 0;
172 m_usage = D3D11_USAGE_DEFAULT;
173 m_format = DXGI_FORMAT_B8G8R8A8_UNORM;
174 m_texture = nullptr;
175 m_renderTargets[0] = nullptr;
176 m_renderTargets[1] = nullptr;
177 m_data = nullptr;
178 m_pitch = 0;
179 m_bindFlags = 0;
180 m_cpuFlags = 0;
181 m_viewIdx = 0;
182 m_views.clear();
185 CD3DTexture::~CD3DTexture()
187 Release();
188 delete[] m_data;
191 bool CD3DTexture::Create(UINT width, UINT height, UINT mipLevels, D3D11_USAGE usage, DXGI_FORMAT format, const void* pixels /* nullptr */, unsigned int srcPitch /* 0 */)
193 m_width = width;
194 m_height = height;
195 m_mipLevels = mipLevels;
196 // create the texture
197 Release();
199 if (format == DXGI_FORMAT_UNKNOWN)
200 format = DXGI_FORMAT_B8G8R8A8_UNORM; // DXGI_FORMAT_UNKNOWN
202 if (!DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_TEXTURE2D))
204 CLog::LogF(LOGERROR, "unsupported texture format {}", DX::DXGIFormatToString(format));
205 return false;
208 m_cpuFlags = 0;
209 if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
211 m_cpuFlags |= D3D11_CPU_ACCESS_WRITE;
212 if (usage == D3D11_USAGE_STAGING)
213 m_cpuFlags |= D3D11_CPU_ACCESS_READ;
216 m_format = format;
217 m_usage = usage;
219 m_bindFlags = 0; // D3D11_BIND_SHADER_RESOURCE;
220 if (D3D11_USAGE_DEFAULT == usage && DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_RENDER_TARGET))
221 m_bindFlags |= D3D11_BIND_RENDER_TARGET;
222 if ( D3D11_USAGE_STAGING != m_usage )
224 if (DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_SHADER_LOAD)
225 || DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
227 m_bindFlags |= D3D11_BIND_SHADER_RESOURCE;
229 if (DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_DECODER_OUTPUT))
231 m_bindFlags |= D3D11_BIND_DECODER;
235 if (!CreateInternal(pixels, srcPitch))
237 CLog::LogF(LOGERROR, "failed to create texture.");
238 return false;
241 Register();
243 return true;
246 bool CD3DTexture::CreateInternal(const void* pixels /* nullptr */, unsigned int srcPitch /* 0 */)
248 ComPtr<ID3D11Device> pD3DDevice = DX::DeviceResources::Get()->GetD3DDevice();
249 ComPtr<ID3D11DeviceContext> pD3D11Context = DX::DeviceResources::Get()->GetD3DContext();
251 UINT miscFlags = 0;
252 bool autogenmm = false;
253 if (m_mipLevels == 0 && DX::Windowing()->IsFormatSupport(m_format, D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
255 autogenmm = pixels != nullptr;
256 miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
258 else
259 m_mipLevels = 1;
261 CD3D11_TEXTURE2D_DESC textureDesc(m_format, m_width, m_height, 1, m_mipLevels, m_bindFlags, m_usage, m_cpuFlags, 1, 0, miscFlags);
262 D3D11_SUBRESOURCE_DATA initData = {};
263 initData.pSysMem = pixels;
264 initData.SysMemPitch = srcPitch ? srcPitch : CD3DHelper::BitsPerPixel(m_format) * m_width / 8;
265 initData.SysMemSlicePitch = 0;
267 HRESULT hr = pD3DDevice->CreateTexture2D(&textureDesc, (!autogenmm && pixels) ? &initData : nullptr, m_texture.ReleaseAndGetAddressOf());
268 if (SUCCEEDED(hr) && autogenmm)
270 pD3D11Context->UpdateSubresource(m_texture.Get(), 0, nullptr, pixels,
271 (srcPitch ? srcPitch : CD3DHelper::BitsPerPixel(m_format) * m_width / 8), 0);
274 if (autogenmm)
275 GenerateMipmaps();
277 return SUCCEEDED(hr);
280 ID3D11ShaderResourceView* CD3DTexture::GetShaderResource(DXGI_FORMAT format /* = DXGI_FORMAT_UNKNOWN */)
282 if (!m_texture)
283 return nullptr;
285 if (format == DXGI_FORMAT_UNKNOWN)
286 format = m_format;
288 if (!DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)
289 && !DX::Windowing()->IsFormatSupport(format, D3D11_FORMAT_SUPPORT_SHADER_LOAD))
290 return nullptr;
292 if (!m_views[format])
294 ComPtr<ID3D11ShaderResourceView> view;
295 CD3D11_SHADER_RESOURCE_VIEW_DESC cSRVDesc(D3D11_SRV_DIMENSION_TEXTURE2D, format);
296 HRESULT hr = DX::DeviceResources::Get()->GetD3DDevice()->CreateShaderResourceView(m_texture.Get(), &cSRVDesc, view.GetAddressOf());
297 if (SUCCEEDED(hr))
298 m_views.insert_or_assign(format, view);
299 else
300 CLog::LogF(LOGWARNING, "cannot create texture view.");
303 return m_views[format].Get();
306 ID3D11ShaderResourceView** CD3DTexture::GetAddressOfSRV(DXGI_FORMAT format)
308 if (format == DXGI_FORMAT_UNKNOWN)
309 format = m_format;
311 if (!m_views[format])
312 GetShaderResource(format);
314 return m_views[format].GetAddressOf();
317 ID3D11RenderTargetView* CD3DTexture::GetRenderTarget()
319 return GetRenderTargetInternal(m_viewIdx);
322 ID3D11RenderTargetView** CD3DTexture::GetAddressOfRTV()
324 if (!m_renderTargets[m_viewIdx])
325 GetRenderTargetInternal(m_viewIdx);
326 return m_renderTargets[m_viewIdx].GetAddressOf();
329 void CD3DTexture::Release()
331 Unregister();
333 m_views.clear();
334 m_renderTargets[0] = nullptr;
335 m_renderTargets[1] = nullptr;
336 m_texture = nullptr;
339 bool CD3DTexture::GetDesc(D3D11_TEXTURE2D_DESC *desc) const
341 if (m_texture)
343 m_texture->GetDesc(desc);
344 return true;
346 return false;
349 bool CD3DTexture::LockRect(UINT subresource, D3D11_MAPPED_SUBRESOURCE *res, D3D11_MAP mapType) const
351 if (m_texture)
353 if (m_usage == D3D11_USAGE_DEFAULT)
354 return false;
355 if ((mapType == D3D11_MAP_READ || mapType == D3D11_MAP_READ_WRITE) && m_usage == D3D11_USAGE_DYNAMIC)
356 return false;
358 return (S_OK == DX::DeviceResources::Get()->GetImmediateContext()->Map(m_texture.Get(), subresource, mapType, 0, res));
360 return false;
363 bool CD3DTexture::UnlockRect(UINT subresource) const
365 if (m_texture)
367 DX::DeviceResources::Get()->GetImmediateContext()->Unmap(m_texture.Get(), subresource);
368 return true;
370 return false;
373 void CD3DTexture::SaveTexture()
375 if (m_texture)
377 delete[] m_data;
378 m_data = nullptr;
380 ID3D11DeviceContext* pContext = DX::DeviceResources::Get()->GetImmediateContext();
382 D3D11_TEXTURE2D_DESC textureDesc;
383 m_texture->GetDesc(&textureDesc);
385 ComPtr<ID3D11Texture2D> texture = nullptr;
386 if (textureDesc.Usage != D3D11_USAGE_STAGING || 0 == (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
388 // create texture which can be readed by CPU - D3D11_USAGE_STAGING
389 CD3D11_TEXTURE2D_DESC stagingDesc(textureDesc);
390 stagingDesc.Usage = D3D11_USAGE_STAGING;
391 stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
392 stagingDesc.BindFlags = 0;
394 if (FAILED(DX::DeviceResources::Get()->GetD3DDevice()->CreateTexture2D(&stagingDesc, NULL, &texture)))
395 return;
397 // copy contents to new texture
398 pContext->CopyResource(texture.Get(), m_texture.Get());
400 else
401 texture = m_texture;
403 // read data from texture
404 D3D11_MAPPED_SUBRESOURCE res;
405 if (SUCCEEDED(pContext->Map(texture.Get(), 0, D3D11_MAP_READ, 0, &res)))
407 m_pitch = res.RowPitch;
408 unsigned int memUsage = GetMemoryUsage(res.RowPitch);
409 m_data = new unsigned char[memUsage];
410 memcpy(m_data, res.pData, memUsage);
411 pContext->Unmap(texture.Get(), 0);
413 else
414 CLog::LogF(LOGERROR, "Failed to store resource.");
418 void CD3DTexture::OnDestroyDevice(bool fatal)
420 if (!fatal)
421 SaveTexture();
422 m_views.clear();
423 m_renderTargets[0] = nullptr;
424 m_renderTargets[1] = nullptr;
425 m_texture = nullptr;
428 void CD3DTexture::RestoreTexture()
430 // yay, we're back - make a new copy of the texture
431 if (!m_texture && m_data)
433 if (!CreateInternal(m_data, m_pitch))
435 CLog::LogF(LOGERROR, "failed restore texture");
438 delete[] m_data;
439 m_data = NULL;
440 m_pitch = 0;
444 void CD3DTexture::OnCreateDevice()
446 RestoreTexture();
449 ID3D11RenderTargetView* CD3DTexture::GetRenderTargetInternal(unsigned idx)
451 if (idx > 1)
452 return nullptr;
454 if (!m_texture)
455 return nullptr;
457 if (!DX::Windowing()->IsFormatSupport(m_format, D3D11_FORMAT_SUPPORT_RENDER_TARGET))
458 return nullptr;
460 if (!m_renderTargets[idx])
462 CD3D11_RENDER_TARGET_VIEW_DESC cRTVDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_UNKNOWN, 0, idx, 1);
463 if (FAILED(DX::DeviceResources::Get()->GetD3DDevice()->CreateRenderTargetView(m_texture.Get(), &cRTVDesc, m_renderTargets[idx].ReleaseAndGetAddressOf())))
465 CLog::LogF(LOGWARNING, "cannot create texture view.");
469 return m_renderTargets[idx].Get();
472 unsigned int CD3DTexture::GetMemoryUsage(unsigned int pitch) const
474 switch (m_format)
476 case DXGI_FORMAT_BC1_UNORM:
477 case DXGI_FORMAT_BC2_UNORM:
478 case DXGI_FORMAT_BC3_UNORM:
479 return pitch * m_height / 4;
480 default:
481 return pitch * m_height;
485 void CD3DTexture::GenerateMipmaps()
487 if (m_mipLevels == 0)
489 ID3D11ShaderResourceView* pSRView = GetShaderResource();
490 if (pSRView != nullptr)
491 DX::DeviceResources::Get()->GetD3DContext()->GenerateMips(pSRView);
495 // static methods
496 void CD3DTexture::DrawQuad(const CPoint points[4],
497 KODI::UTILS::COLOR::Color color,
498 CD3DTexture* texture,
499 const CRect* texCoords,
500 SHADER_METHOD options)
502 unsigned numViews = 0;
503 ID3D11ShaderResourceView* views = nullptr;
505 if (texture)
507 numViews = 1;
508 views = texture->GetShaderResource();
511 DrawQuad(points, color, numViews, &views, texCoords, options);
514 void CD3DTexture::DrawQuad(const CRect& rect,
515 KODI::UTILS::COLOR::Color color,
516 CD3DTexture* texture,
517 const CRect* texCoords,
518 SHADER_METHOD options)
520 CPoint points[] =
522 { rect.x1, rect.y1 },
523 { rect.x2, rect.y1 },
524 { rect.x2, rect.y2 },
525 { rect.x1, rect.y2 },
527 DrawQuad(points, color, texture, texCoords, options);
530 void CD3DTexture::DrawQuad(const CPoint points[4],
531 KODI::UTILS::COLOR::Color color,
532 unsigned numViews,
533 ID3D11ShaderResourceView** view,
534 const CRect* texCoords,
535 SHADER_METHOD options)
537 XMFLOAT4 xcolor;
538 CD3DHelper::XMStoreColor(&xcolor, color);
539 CRect coords = texCoords ? *texCoords : CRect(0.0f, 0.0f, 1.0f, 1.0f);
541 Vertex verts[4] = {
542 { XMFLOAT3(points[0].x, points[0].y, 0), xcolor, XMFLOAT2(coords.x1, coords.y1), XMFLOAT2(0.0f, 0.0f) },
543 { XMFLOAT3(points[1].x, points[1].y, 0), xcolor, XMFLOAT2(coords.x2, coords.y1), XMFLOAT2(0.0f, 0.0f) },
544 { XMFLOAT3(points[2].x, points[2].y, 0), xcolor, XMFLOAT2(coords.x2, coords.y2), XMFLOAT2(0.0f, 0.0f) },
545 { XMFLOAT3(points[3].x, points[3].y, 0), xcolor, XMFLOAT2(coords.x1, coords.y2), XMFLOAT2(0.0f, 0.0f) },
548 CGUIShaderDX* pGUIShader = DX::Windowing()->GetGUIShader();
550 pGUIShader->Begin(view && numViews > 0 ? options : SHADER_METHOD_RENDER_DEFAULT);
551 if (view && numViews > 0)
552 pGUIShader->SetShaderViews(numViews, view);
553 pGUIShader->DrawQuad(verts[0], verts[1], verts[2], verts[3]);
556 void CD3DTexture::DrawQuad(const CRect& rect,
557 KODI::UTILS::COLOR::Color color,
558 unsigned numViews,
559 ID3D11ShaderResourceView** view,
560 const CRect* texCoords,
561 SHADER_METHOD options)
563 CPoint points[] =
565 { rect.x1, rect.y1 },
566 { rect.x2, rect.y1 },
567 { rect.x2, rect.y2 },
568 { rect.x1, rect.y2 },
570 DrawQuad(points, color, numViews, view, texCoords, options);
573 CD3DEffect::CD3DEffect()
575 m_effect = nullptr;
576 m_techniquie = nullptr;
577 m_currentPass = nullptr;
580 CD3DEffect::~CD3DEffect()
582 Release();
585 bool CD3DEffect::Create(const std::string &effectString, DefinesMap* defines)
587 Release();
588 m_effectString = effectString;
589 m_defines.clear();
590 if (defines != nullptr)
591 m_defines = *defines; //FIXME: is this a copy of all members?
592 if (CreateEffect())
594 Register();
595 return true;
597 return false;
600 void CD3DEffect::Release()
602 Unregister();
603 OnDestroyDevice(false);
606 void CD3DEffect::OnDestroyDevice(bool fatal)
608 m_effect = nullptr;
609 m_techniquie = nullptr;
610 m_currentPass = nullptr;
613 void CD3DEffect::OnCreateDevice()
615 CreateEffect();
618 HRESULT CD3DEffect::Open(D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes)
620 XFILE::CFile includeFile;
622 std::string fileName("special://xbmc/system/shaders/");
623 fileName.append(pFileName);
625 if (!includeFile.Open(fileName))
627 CLog::LogF(LOGERROR, "Could not open 3DLUT file: {}", fileName);
628 return E_FAIL;
631 int64_t length = includeFile.GetLength();
632 void *pData = malloc(length);
633 if (includeFile.Read(pData, length) != length)
635 free(pData);
636 return E_FAIL;
638 *ppData = pData;
639 *pBytes = length;
641 return S_OK;
644 HRESULT CD3DEffect::Close(LPCVOID pData)
646 free((void*)pData);
647 return S_OK;
650 bool CD3DEffect::SetFloatArray(LPCSTR handle, const float* val, unsigned int count)
652 if (m_effect)
654 return S_OK == m_effect->GetVariableByName(handle)->SetRawValue(val, 0, sizeof(float) * count);
656 return false;
659 bool CD3DEffect::SetMatrix(LPCSTR handle, const float* mat)
661 if (m_effect)
663 return S_OK == m_effect->GetVariableByName(handle)->AsMatrix()->SetMatrix(mat);
665 return false;
668 bool CD3DEffect::SetTechnique(LPCSTR handle)
670 if (m_effect)
672 m_techniquie = m_effect->GetTechniqueByName(handle);
673 if (!m_techniquie->IsValid())
674 m_techniquie = nullptr;
676 return nullptr != m_techniquie;
678 return false;
681 bool CD3DEffect::SetTexture(LPCSTR handle, CD3DTexture &texture)
683 if (m_effect)
685 ID3DX11EffectShaderResourceVariable* var = m_effect->GetVariableByName(handle)->AsShaderResource();
686 if (var->IsValid())
687 return SUCCEEDED(var->SetResource(texture.GetShaderResource()));
689 return false;
692 bool CD3DEffect::SetResources(LPCSTR handle, ID3D11ShaderResourceView** ppSRViews, size_t count)
694 if (m_effect)
696 ID3DX11EffectShaderResourceVariable* var = m_effect->GetVariableByName(handle)->AsShaderResource();
697 if (var->IsValid())
698 return SUCCEEDED(var->SetResourceArray(ppSRViews, 0, count));
700 return false;
703 bool CD3DEffect::SetConstantBuffer(LPCSTR handle, ID3D11Buffer *buffer)
705 if (m_effect)
707 ID3DX11EffectConstantBuffer* effectbuffer = m_effect->GetConstantBufferByName(handle);
708 if (effectbuffer->IsValid())
709 return (S_OK == effectbuffer->SetConstantBuffer(buffer));
711 return false;
714 bool CD3DEffect::SetScalar(LPCSTR handle, float value)
716 if (m_effect)
718 ID3DX11EffectScalarVariable* scalar = m_effect->GetVariableByName(handle)->AsScalar();
719 if (scalar->IsValid())
720 return (S_OK == scalar->SetFloat(value));
723 return false;
726 bool CD3DEffect::Begin(UINT *passes, DWORD flags)
728 if (m_effect && m_techniquie)
730 D3DX11_TECHNIQUE_DESC desc = {};
731 HRESULT hr = m_techniquie->GetDesc(&desc);
732 *passes = desc.Passes;
733 return S_OK == hr;
735 return false;
738 bool CD3DEffect::BeginPass(UINT pass)
740 if (m_effect && m_techniquie)
742 m_currentPass = m_techniquie->GetPassByIndex(pass);
743 if (!m_currentPass || !m_currentPass->IsValid())
745 m_currentPass = nullptr;
746 return false;
748 return (S_OK == m_currentPass->Apply(0, DX::DeviceResources::Get()->GetD3DContext()));
750 return false;
753 bool CD3DEffect::EndPass()
755 if (m_effect && m_currentPass)
757 m_currentPass = nullptr;
758 return true;
760 return false;
763 bool CD3DEffect::End()
765 if (m_effect && m_techniquie)
767 m_techniquie = nullptr;
768 return true;
770 return false;
773 bool CD3DEffect::CreateEffect()
775 HRESULT hr;
776 ID3DBlob* pError = nullptr;
778 std::vector<D3D_SHADER_MACRO> definemacros;
780 for (const auto& it : m_defines)
782 D3D_SHADER_MACRO m;
783 m.Name = it.first.c_str();
784 if (it.second.empty())
785 m.Definition = nullptr;
786 else
787 m.Definition = it.second.c_str();
788 definemacros.push_back( m );
791 definemacros.push_back(D3D_SHADER_MACRO());
792 definemacros.back().Name = nullptr;
793 definemacros.back().Definition = nullptr;
795 UINT dwShaderFlags = 0;
797 #ifdef _DEBUG
798 //dwShaderFlags |= D3DCOMPILE_DEBUG;
799 // Disable optimizations to further improve shader debugging
800 //dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
801 #endif
803 hr = D3DX11CompileEffectFromMemory(m_effectString.c_str(), m_effectString.length(), "", &definemacros[0], this,
804 dwShaderFlags, 0, DX::DeviceResources::Get()->GetD3DDevice(), m_effect.ReleaseAndGetAddressOf(), &pError);
806 if(hr == S_OK)
807 return true;
808 else if(pError)
810 std::string error;
811 error.assign((const char*)pError->GetBufferPointer(), pError->GetBufferSize());
812 CLog::Log(LOGERROR, "CD3DEffect::CreateEffect(): {}", error);
814 else
815 CLog::Log(LOGERROR, "CD3DEffect::CreateEffect(): call to D3DXCreateEffect() failed with {}",
816 hr);
817 return false;
820 CD3DBuffer::CD3DBuffer()
822 m_length = 0;
823 m_stride = 0;
824 m_usage = D3D11_USAGE_DEFAULT;
825 m_format = DXGI_FORMAT_UNKNOWN;
826 m_buffer = nullptr;
827 m_data = nullptr;
830 CD3DBuffer::~CD3DBuffer()
832 Release();
833 delete[] m_data;
836 bool CD3DBuffer::Create(D3D11_BIND_FLAG type, UINT count, UINT stride, DXGI_FORMAT format, D3D11_USAGE usage, const void* data)
838 m_type = type;
839 m_stride = stride ? stride : CD3DHelper::BitsPerPixel(format);
840 m_format = format;
841 m_length = count * m_stride;
842 m_usage = usage;
843 m_cpuFlags = 0;
845 if (m_usage == D3D11_USAGE_DYNAMIC || m_usage == D3D11_USAGE_STAGING)
847 m_cpuFlags |= D3D11_CPU_ACCESS_WRITE;
848 if (m_usage == D3D11_USAGE_STAGING)
849 m_cpuFlags |= D3D11_CPU_ACCESS_READ;
852 Release();
854 // create the vertex buffer
855 if (CreateBuffer(data))
857 Register();
858 return true;
860 return false;
863 void CD3DBuffer::Release()
865 Unregister();
866 m_buffer = nullptr;
869 bool CD3DBuffer::Map(void **data)
871 if (m_buffer)
873 D3D11_MAPPED_SUBRESOURCE resource;
874 if (SUCCEEDED(DX::DeviceResources::Get()->GetD3DContext()->Map(m_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &resource)))
876 *data = resource.pData;
877 return true;
880 return false;
883 bool CD3DBuffer::Unmap()
885 if (m_buffer)
887 DX::DeviceResources::Get()->GetD3DContext()->Unmap(m_buffer.Get(), 0);
888 return true;
890 return false;
893 void CD3DBuffer::OnDestroyDevice(bool fatal)
895 if (fatal)
897 m_buffer = nullptr;
898 return;
901 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
902 ComPtr<ID3D11DeviceContext> pContext = DX::DeviceResources::Get()->GetImmediateContext();
904 if (!pDevice || !pContext || !m_buffer)
905 return;
907 D3D11_BUFFER_DESC srcDesc;
908 m_buffer->GetDesc(&srcDesc);
910 ComPtr<ID3D11Buffer> buffer;
911 if (srcDesc.Usage != D3D11_USAGE_STAGING || 0 == (srcDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
913 CD3D11_BUFFER_DESC trgDesc(srcDesc);
914 trgDesc.Usage = D3D11_USAGE_STAGING;
915 trgDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
916 trgDesc.BindFlags = 0;
918 if (SUCCEEDED(pDevice->CreateBuffer(&trgDesc, NULL, &buffer)))
919 pContext->CopyResource(buffer.Get(), m_buffer.Get());
921 else
922 buffer = m_buffer;
924 if (buffer != nullptr)
926 D3D11_MAPPED_SUBRESOURCE res;
927 if (SUCCEEDED(pContext->Map(buffer.Get(), 0, D3D11_MAP_READ, 0, &res)))
929 m_data = new unsigned char[srcDesc.ByteWidth];
930 memcpy(m_data, res.pData, srcDesc.ByteWidth);
931 pContext->Unmap(buffer.Get(), 0);
934 m_buffer = nullptr;
937 void CD3DBuffer::OnCreateDevice()
939 // yay, we're back - make a new copy of the vertices
940 if (!m_buffer && m_data)
942 CreateBuffer(m_data);
943 delete[] m_data;
944 m_data = nullptr;
948 bool CD3DBuffer::CreateBuffer(const void* pData)
950 CD3D11_BUFFER_DESC bDesc(m_length, m_type, m_usage, m_cpuFlags);
951 D3D11_SUBRESOURCE_DATA initData;
952 initData.pSysMem = pData;
953 return (S_OK == DX::DeviceResources::Get()->GetD3DDevice()->CreateBuffer(&bDesc, (pData ? &initData : nullptr), m_buffer.ReleaseAndGetAddressOf()));
956 /****************************************************/
957 /* D3D Vertex Shader Class */
958 /****************************************************/
959 CD3DVertexShader::CD3DVertexShader()
961 m_VS = nullptr;
962 m_vertexLayout = nullptr;
963 m_VSBuffer = nullptr;
964 m_inputLayout = nullptr;
965 m_vertexLayoutSize = 0;
966 m_inited = false;
969 CD3DVertexShader::~CD3DVertexShader()
971 Release();
974 void CD3DVertexShader::Release()
976 Unregister();
977 ReleaseShader();
978 m_VSBuffer = nullptr;
979 if (m_vertexLayout)
981 delete[] m_vertexLayout;
982 m_vertexLayout = nullptr;
986 void CD3DVertexShader::ReleaseShader()
988 UnbindShader();
990 m_VS = nullptr;
991 m_inputLayout = nullptr;
992 m_inited = false;
995 bool CD3DVertexShader::Create(const std::wstring& vertexFile, D3D11_INPUT_ELEMENT_DESC* vertexLayout, unsigned int vertexLayoutSize)
997 ReleaseShader();
999 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1001 if (!pDevice)
1002 return false;
1004 if (FAILED(D3DReadFileToBlob(vertexFile.c_str(), m_VSBuffer.ReleaseAndGetAddressOf())))
1006 CLog::LogF(LOGERROR, "failed to load the vertex shader.");
1007 return false;
1010 if (vertexLayout && vertexLayoutSize)
1012 m_vertexLayoutSize = vertexLayoutSize;
1013 m_vertexLayout = new D3D11_INPUT_ELEMENT_DESC[vertexLayoutSize];
1014 for (unsigned int i = 0; i < vertexLayoutSize; ++i)
1015 m_vertexLayout[i] = vertexLayout[i];
1017 else
1018 return false;
1020 m_inited = CreateInternal();
1022 if (m_inited)
1023 Register();
1025 return m_inited;
1028 bool CD3DVertexShader::Create(const void* code, size_t codeLength, D3D11_INPUT_ELEMENT_DESC* vertexLayout, unsigned int vertexLayoutSize)
1030 ReleaseShader();
1032 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1034 if (!pDevice)
1035 return false;
1037 // trick to load bytecode into ID3DBlob
1038 if (FAILED(D3DStripShader(code, codeLength, D3DCOMPILER_STRIP_REFLECTION_DATA, m_VSBuffer.ReleaseAndGetAddressOf())))
1040 CLog::LogF(LOGERROR, "failed to load the vertex shader.");
1041 return false;
1044 if (vertexLayout && vertexLayoutSize)
1046 m_vertexLayoutSize = vertexLayoutSize;
1047 m_vertexLayout = new D3D11_INPUT_ELEMENT_DESC[vertexLayoutSize];
1048 for (unsigned int i = 0; i < vertexLayoutSize; ++i)
1049 m_vertexLayout[i] = vertexLayout[i];
1051 else
1052 return false;
1054 m_inited = CreateInternal();
1056 if (m_inited)
1057 Register();
1059 return m_inited;
1062 bool CD3DVertexShader::CreateInternal()
1064 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1066 CLog::LogF(LOGDEBUG, "creating vertex shader.");
1068 // Create the vertex shader
1069 if (FAILED(pDevice->CreateVertexShader(m_VSBuffer->GetBufferPointer(), m_VSBuffer->GetBufferSize(), nullptr, m_VS.ReleaseAndGetAddressOf())))
1071 CLog::LogF(LOGERROR, "failed to Create the vertex shader.");
1072 m_VSBuffer = nullptr;
1073 return false;
1076 CLog::LogF(LOGDEBUG, "creating input layout.");
1078 if (FAILED(pDevice->CreateInputLayout(m_vertexLayout, m_vertexLayoutSize, m_VSBuffer->GetBufferPointer(), m_VSBuffer->GetBufferSize(), m_inputLayout.ReleaseAndGetAddressOf())))
1080 CLog::LogF(LOGERROR, "failed to create the input layout.");
1081 return false;
1084 return true;
1087 void CD3DVertexShader::BindShader()
1089 if (!m_inited)
1090 return;
1092 ComPtr<ID3D11DeviceContext> pContext = DX::DeviceResources::Get()->GetD3DContext();
1093 if (!pContext)
1094 return;
1096 pContext->IASetInputLayout(m_inputLayout.Get());
1097 pContext->VSSetShader(m_VS.Get(), nullptr, 0);
1100 void CD3DVertexShader::UnbindShader()
1102 if (!m_inited)
1103 return;
1105 ComPtr<ID3D11DeviceContext> pContext = DX::DeviceResources::Get()->GetD3DContext();
1106 pContext->IASetInputLayout(nullptr);
1107 pContext->VSSetShader(nullptr, nullptr, 0);
1110 void CD3DVertexShader::OnCreateDevice()
1112 if (m_VSBuffer && !m_VS)
1113 m_inited = CreateInternal();
1116 void CD3DVertexShader::OnDestroyDevice(bool fatal)
1118 ReleaseShader();
1121 /****************************************************/
1122 /* D3D Pixel Shader Class */
1123 /****************************************************/
1124 CD3DPixelShader::CD3DPixelShader()
1126 m_PS = nullptr;
1127 m_PSBuffer = nullptr;
1128 m_inited = false;
1131 CD3DPixelShader::~CD3DPixelShader()
1133 Release();
1136 void CD3DPixelShader::Release()
1138 Unregister();
1139 ReleaseShader();
1140 m_PSBuffer = nullptr;
1143 void CD3DPixelShader::ReleaseShader()
1145 m_inited = false;
1146 m_PS = nullptr;
1149 bool CD3DPixelShader::Create(const std::wstring& wstrFile)
1151 ReleaseShader();
1153 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1155 if (!pDevice)
1156 return false;
1158 if (FAILED(D3DReadFileToBlob(wstrFile.c_str(), m_PSBuffer.ReleaseAndGetAddressOf())))
1160 CLog::LogF(LOGERROR, "Failed to load the vertex shader.");
1161 return false;
1164 m_inited = CreateInternal();
1166 if (m_inited)
1167 Register();
1169 return m_inited;
1172 bool CD3DPixelShader::Create(const void* code, size_t codeLength)
1174 ReleaseShader();
1176 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1178 if (!pDevice)
1179 return false;
1181 // trick to load bytecode into ID3DBlob
1182 if (FAILED(D3DStripShader(code, codeLength, D3DCOMPILER_STRIP_REFLECTION_DATA, m_PSBuffer.ReleaseAndGetAddressOf())))
1184 CLog::LogF(LOGERROR, "Failed to load the vertex shader.");
1185 return false;
1188 m_inited = CreateInternal();
1190 if (m_inited)
1191 Register();
1193 return m_inited;
1196 bool CD3DPixelShader::CreateInternal()
1198 ComPtr<ID3D11Device> pDevice = DX::DeviceResources::Get()->GetD3DDevice();
1200 CLog::LogF(LOGDEBUG, "Create the pixel shader.");
1202 // Create the vertex shader
1203 if (FAILED(pDevice->CreatePixelShader(m_PSBuffer->GetBufferPointer(), m_PSBuffer->GetBufferSize(), nullptr, m_PS.ReleaseAndGetAddressOf())))
1205 CLog::LogF(LOGERROR, "Failed to Create the pixel shader.");
1206 m_PSBuffer = nullptr;
1207 return false;
1210 return true;
1213 void CD3DPixelShader::BindShader()
1215 if (!m_inited)
1216 return;
1218 ComPtr<ID3D11DeviceContext> pContext = DX::DeviceResources::Get()->GetD3DContext();
1219 if (!pContext)
1220 return;
1222 pContext->PSSetShader(m_PS.Get(), nullptr, 0);
1225 void CD3DPixelShader::UnbindShader()
1227 if (!m_inited)
1228 return;
1230 ComPtr<ID3D11DeviceContext> pContext = DX::DeviceResources::Get()->GetD3DContext();
1231 pContext->IASetInputLayout(nullptr);
1232 pContext->VSSetShader(nullptr, nullptr, 0);
1235 void CD3DPixelShader::OnCreateDevice()
1237 if (m_PSBuffer && !m_PS)
1238 m_inited = CreateInternal();
1241 void CD3DPixelShader::OnDestroyDevice(bool fatal)
1243 ReleaseShader();