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.
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")
26 size_t CD3DHelper::BitsPerPixel(DXGI_FORMAT 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
:
36 case DXGI_FORMAT_R32G32B32_TYPELESS
:
37 case DXGI_FORMAT_R32G32B32_FLOAT
:
38 case DXGI_FORMAT_R32G32B32_UINT
:
39 case DXGI_FORMAT_R32G32B32_SINT
:
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
:
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
:
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
:
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
:
120 case DXGI_FORMAT_R1_UNORM
:
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
:
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
:
153 void ID3DResource::Register()
156 DX::Windowing()->Register(this);
157 m_bRegistered
= true;
160 void ID3DResource::Unregister()
163 DX::Windowing()->Unregister(this);
164 m_bRegistered
= false;
167 CD3DTexture::CD3DTexture()
172 m_usage
= D3D11_USAGE_DEFAULT
;
173 m_format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
175 m_renderTargets
[0] = nullptr;
176 m_renderTargets
[1] = nullptr;
185 CD3DTexture::~CD3DTexture()
191 bool CD3DTexture::Create(UINT width
, UINT height
, UINT mipLevels
, D3D11_USAGE usage
, DXGI_FORMAT format
, const void* pixels
/* nullptr */, unsigned int srcPitch
/* 0 */)
195 m_mipLevels
= mipLevels
;
196 // create the texture
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
));
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
;
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.");
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();
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
;
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);
277 return SUCCEEDED(hr
);
280 ID3D11ShaderResourceView
* CD3DTexture::GetShaderResource(DXGI_FORMAT format
/* = DXGI_FORMAT_UNKNOWN */)
285 if (format
== DXGI_FORMAT_UNKNOWN
)
288 if (!DX::Windowing()->IsFormatSupport(format
, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
)
289 && !DX::Windowing()->IsFormatSupport(format
, D3D11_FORMAT_SUPPORT_SHADER_LOAD
))
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());
298 m_views
.insert_or_assign(format
, view
);
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
)
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()
334 m_renderTargets
[0] = nullptr;
335 m_renderTargets
[1] = nullptr;
339 bool CD3DTexture::GetDesc(D3D11_TEXTURE2D_DESC
*desc
) const
343 m_texture
->GetDesc(desc
);
349 bool CD3DTexture::LockRect(UINT subresource
, D3D11_MAPPED_SUBRESOURCE
*res
, D3D11_MAP mapType
) const
353 if (m_usage
== D3D11_USAGE_DEFAULT
)
355 if ((mapType
== D3D11_MAP_READ
|| mapType
== D3D11_MAP_READ_WRITE
) && m_usage
== D3D11_USAGE_DYNAMIC
)
358 return (S_OK
== DX::DeviceResources::Get()->GetImmediateContext()->Map(m_texture
.Get(), subresource
, mapType
, 0, res
));
363 bool CD3DTexture::UnlockRect(UINT subresource
) const
367 DX::DeviceResources::Get()->GetImmediateContext()->Unmap(m_texture
.Get(), subresource
);
373 void CD3DTexture::SaveTexture()
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
)))
397 // copy contents to new texture
398 pContext
->CopyResource(texture
.Get(), m_texture
.Get());
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);
414 CLog::LogF(LOGERROR
, "Failed to store resource.");
418 void CD3DTexture::OnDestroyDevice(bool fatal
)
423 m_renderTargets
[0] = nullptr;
424 m_renderTargets
[1] = 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");
444 void CD3DTexture::OnCreateDevice()
449 ID3D11RenderTargetView
* CD3DTexture::GetRenderTargetInternal(unsigned idx
)
457 if (!DX::Windowing()->IsFormatSupport(m_format
, D3D11_FORMAT_SUPPORT_RENDER_TARGET
))
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
476 case DXGI_FORMAT_BC1_UNORM
:
477 case DXGI_FORMAT_BC2_UNORM
:
478 case DXGI_FORMAT_BC3_UNORM
:
479 return pitch
* m_height
/ 4;
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
);
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;
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
)
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
,
533 ID3D11ShaderResourceView
** view
,
534 const CRect
* texCoords
,
535 SHADER_METHOD options
)
538 CD3DHelper::XMStoreColor(&xcolor
, color
);
539 CRect coords
= texCoords
? *texCoords
: CRect(0.0f
, 0.0f
, 1.0f
, 1.0f
);
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
,
559 ID3D11ShaderResourceView
** view
,
560 const CRect
* texCoords
,
561 SHADER_METHOD options
)
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()
576 m_techniquie
= nullptr;
577 m_currentPass
= nullptr;
580 CD3DEffect::~CD3DEffect()
585 bool CD3DEffect::Create(const std::string
&effectString
, DefinesMap
* defines
)
588 m_effectString
= effectString
;
590 if (defines
!= nullptr)
591 m_defines
= *defines
; //FIXME: is this a copy of all members?
600 void CD3DEffect::Release()
603 OnDestroyDevice(false);
606 void CD3DEffect::OnDestroyDevice(bool fatal
)
609 m_techniquie
= nullptr;
610 m_currentPass
= nullptr;
613 void CD3DEffect::OnCreateDevice()
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
);
631 int64_t length
= includeFile
.GetLength();
632 void *pData
= malloc(length
);
633 if (includeFile
.Read(pData
, length
) != length
)
644 HRESULT
CD3DEffect::Close(LPCVOID pData
)
650 bool CD3DEffect::SetFloatArray(LPCSTR handle
, const float* val
, unsigned int count
)
654 return S_OK
== m_effect
->GetVariableByName(handle
)->SetRawValue(val
, 0, sizeof(float) * count
);
659 bool CD3DEffect::SetMatrix(LPCSTR handle
, const float* mat
)
663 return S_OK
== m_effect
->GetVariableByName(handle
)->AsMatrix()->SetMatrix(mat
);
668 bool CD3DEffect::SetTechnique(LPCSTR handle
)
672 m_techniquie
= m_effect
->GetTechniqueByName(handle
);
673 if (!m_techniquie
->IsValid())
674 m_techniquie
= nullptr;
676 return nullptr != m_techniquie
;
681 bool CD3DEffect::SetTexture(LPCSTR handle
, CD3DTexture
&texture
)
685 ID3DX11EffectShaderResourceVariable
* var
= m_effect
->GetVariableByName(handle
)->AsShaderResource();
687 return SUCCEEDED(var
->SetResource(texture
.GetShaderResource()));
692 bool CD3DEffect::SetResources(LPCSTR handle
, ID3D11ShaderResourceView
** ppSRViews
, size_t count
)
696 ID3DX11EffectShaderResourceVariable
* var
= m_effect
->GetVariableByName(handle
)->AsShaderResource();
698 return SUCCEEDED(var
->SetResourceArray(ppSRViews
, 0, count
));
703 bool CD3DEffect::SetConstantBuffer(LPCSTR handle
, ID3D11Buffer
*buffer
)
707 ID3DX11EffectConstantBuffer
* effectbuffer
= m_effect
->GetConstantBufferByName(handle
);
708 if (effectbuffer
->IsValid())
709 return (S_OK
== effectbuffer
->SetConstantBuffer(buffer
));
714 bool CD3DEffect::SetScalar(LPCSTR handle
, float value
)
718 ID3DX11EffectScalarVariable
* scalar
= m_effect
->GetVariableByName(handle
)->AsScalar();
719 if (scalar
->IsValid())
720 return (S_OK
== scalar
->SetFloat(value
));
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
;
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;
748 return (S_OK
== m_currentPass
->Apply(0, DX::DeviceResources::Get()->GetD3DContext()));
753 bool CD3DEffect::EndPass()
755 if (m_effect
&& m_currentPass
)
757 m_currentPass
= nullptr;
763 bool CD3DEffect::End()
765 if (m_effect
&& m_techniquie
)
767 m_techniquie
= nullptr;
773 bool CD3DEffect::CreateEffect()
776 ID3DBlob
* pError
= nullptr;
778 std::vector
<D3D_SHADER_MACRO
> definemacros
;
780 for (const auto& it
: m_defines
)
783 m
.Name
= it
.first
.c_str();
784 if (it
.second
.empty())
785 m
.Definition
= nullptr;
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;
798 //dwShaderFlags |= D3DCOMPILE_DEBUG;
799 // Disable optimizations to further improve shader debugging
800 //dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
803 hr
= D3DX11CompileEffectFromMemory(m_effectString
.c_str(), m_effectString
.length(), "", &definemacros
[0], this,
804 dwShaderFlags
, 0, DX::DeviceResources::Get()->GetD3DDevice(), m_effect
.ReleaseAndGetAddressOf(), &pError
);
811 error
.assign((const char*)pError
->GetBufferPointer(), pError
->GetBufferSize());
812 CLog::Log(LOGERROR
, "CD3DEffect::CreateEffect(): {}", error
);
815 CLog::Log(LOGERROR
, "CD3DEffect::CreateEffect(): call to D3DXCreateEffect() failed with {}",
820 CD3DBuffer::CD3DBuffer()
824 m_usage
= D3D11_USAGE_DEFAULT
;
825 m_format
= DXGI_FORMAT_UNKNOWN
;
830 CD3DBuffer::~CD3DBuffer()
836 bool CD3DBuffer::Create(D3D11_BIND_FLAG type
, UINT count
, UINT stride
, DXGI_FORMAT format
, D3D11_USAGE usage
, const void* data
)
839 m_stride
= stride
? stride
: CD3DHelper::BitsPerPixel(format
);
841 m_length
= count
* m_stride
;
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
;
854 // create the vertex buffer
855 if (CreateBuffer(data
))
863 void CD3DBuffer::Release()
869 bool CD3DBuffer::Map(void **data
)
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
;
883 bool CD3DBuffer::Unmap()
887 DX::DeviceResources::Get()->GetD3DContext()->Unmap(m_buffer
.Get(), 0);
893 void CD3DBuffer::OnDestroyDevice(bool fatal
)
901 ComPtr
<ID3D11Device
> pDevice
= DX::DeviceResources::Get()->GetD3DDevice();
902 ComPtr
<ID3D11DeviceContext
> pContext
= DX::DeviceResources::Get()->GetImmediateContext();
904 if (!pDevice
|| !pContext
|| !m_buffer
)
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());
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);
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
);
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()
962 m_vertexLayout
= nullptr;
963 m_VSBuffer
= nullptr;
964 m_inputLayout
= nullptr;
965 m_vertexLayoutSize
= 0;
969 CD3DVertexShader::~CD3DVertexShader()
974 void CD3DVertexShader::Release()
978 m_VSBuffer
= nullptr;
981 delete[] m_vertexLayout
;
982 m_vertexLayout
= nullptr;
986 void CD3DVertexShader::ReleaseShader()
991 m_inputLayout
= nullptr;
995 bool CD3DVertexShader::Create(const std::wstring
& vertexFile
, D3D11_INPUT_ELEMENT_DESC
* vertexLayout
, unsigned int vertexLayoutSize
)
999 ComPtr
<ID3D11Device
> pDevice
= DX::DeviceResources::Get()->GetD3DDevice();
1004 if (FAILED(D3DReadFileToBlob(vertexFile
.c_str(), m_VSBuffer
.ReleaseAndGetAddressOf())))
1006 CLog::LogF(LOGERROR
, "failed to load the vertex shader.");
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
];
1020 m_inited
= CreateInternal();
1028 bool CD3DVertexShader::Create(const void* code
, size_t codeLength
, D3D11_INPUT_ELEMENT_DESC
* vertexLayout
, unsigned int vertexLayoutSize
)
1032 ComPtr
<ID3D11Device
> pDevice
= DX::DeviceResources::Get()->GetD3DDevice();
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.");
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
];
1054 m_inited
= CreateInternal();
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;
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.");
1087 void CD3DVertexShader::BindShader()
1092 ComPtr
<ID3D11DeviceContext
> pContext
= DX::DeviceResources::Get()->GetD3DContext();
1096 pContext
->IASetInputLayout(m_inputLayout
.Get());
1097 pContext
->VSSetShader(m_VS
.Get(), nullptr, 0);
1100 void CD3DVertexShader::UnbindShader()
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
)
1121 /****************************************************/
1122 /* D3D Pixel Shader Class */
1123 /****************************************************/
1124 CD3DPixelShader::CD3DPixelShader()
1127 m_PSBuffer
= nullptr;
1131 CD3DPixelShader::~CD3DPixelShader()
1136 void CD3DPixelShader::Release()
1140 m_PSBuffer
= nullptr;
1143 void CD3DPixelShader::ReleaseShader()
1149 bool CD3DPixelShader::Create(const std::wstring
& wstrFile
)
1153 ComPtr
<ID3D11Device
> pDevice
= DX::DeviceResources::Get()->GetD3DDevice();
1158 if (FAILED(D3DReadFileToBlob(wstrFile
.c_str(), m_PSBuffer
.ReleaseAndGetAddressOf())))
1160 CLog::LogF(LOGERROR
, "Failed to load the vertex shader.");
1164 m_inited
= CreateInternal();
1172 bool CD3DPixelShader::Create(const void* code
, size_t codeLength
)
1176 ComPtr
<ID3D11Device
> pDevice
= DX::DeviceResources::Get()->GetD3DDevice();
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.");
1188 m_inited
= CreateInternal();
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;
1213 void CD3DPixelShader::BindShader()
1218 ComPtr
<ID3D11DeviceContext
> pContext
= DX::DeviceResources::Get()->GetD3DContext();
1222 pContext
->PSSetShader(m_PS
.Get(), nullptr, 0);
1225 void CD3DPixelShader::UnbindShader()
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
)