PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Core/VideoBackends/D3D12/D3DState.h

https://gitlab.com/Hexexpeck/dolphin-emulator
C Header | 192 lines | 152 code | 31 blank | 9 comment | 1 complexity | 386d1788d182c16f406c4b7c56ae7c5f MD5 | raw file
  1. // Copyright 2014 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <stack>
  6. #include <unordered_map>
  7. #include "Common/BitField.h"
  8. #include "Common/CommonTypes.h"
  9. #include "VideoBackends/D3D12/D3DBase.h"
  10. #include "VideoBackends/D3D12/NativeVertexFormat.h"
  11. #include "VideoBackends/D3D12/ShaderCache.h"
  12. #include "VideoCommon/BPMemory.h"
  13. namespace DX12
  14. {
  15. class PipelineStateCacheInserter;
  16. union RasterizerState {
  17. BitField<0, 2, D3D12_CULL_MODE> cull_mode;
  18. u32 hex;
  19. };
  20. union BlendState {
  21. BitField<0, 1, u32> blend_enable;
  22. BitField<1, 3, D3D12_BLEND_OP> blend_op;
  23. BitField<4, 4, u8> write_mask;
  24. BitField<8, 5, D3D12_BLEND> src_blend;
  25. BitField<13, 5, D3D12_BLEND> dst_blend;
  26. BitField<18, 1, u32> use_dst_alpha;
  27. u32 hex;
  28. };
  29. union SamplerState {
  30. BitField<0, 3, u32> min_filter;
  31. BitField<3, 1, u32> mag_filter;
  32. BitField<4, 8, u32> min_lod;
  33. BitField<12, 8, u32> max_lod;
  34. BitField<20, 8, s32> lod_bias;
  35. BitField<28, 2, u32> wrap_s;
  36. BitField<30, 2, u32> wrap_t;
  37. u32 hex;
  38. };
  39. struct SmallPsoDesc
  40. {
  41. D3D12_SHADER_BYTECODE gs_bytecode;
  42. D3D12_SHADER_BYTECODE ps_bytecode;
  43. D3D12_SHADER_BYTECODE vs_bytecode;
  44. D3DVertexFormat* input_layout;
  45. BlendState blend_state;
  46. RasterizerState rasterizer_state;
  47. ZMode depth_stencil_state;
  48. };
  49. // The Bitfield members in BlendState, RasterizerState, and ZMode cause the..
  50. // static_assert(std::is_trivially_copyable<K>::value, "K must be a trivially copyable type");
  51. // .. check in LinearDiskCache to fail. So, just storing the packed u32 values.
  52. struct SmallPsoDiskDesc
  53. {
  54. u32 blend_state_hex;
  55. u32 rasterizer_state_hex;
  56. u32 depth_stencil_state_hex;
  57. PixelShaderUid ps_uid;
  58. VertexShaderUid vs_uid;
  59. GeometryShaderUid gs_uid;
  60. D3D12_PRIMITIVE_TOPOLOGY_TYPE topology;
  61. PortableVertexDeclaration vertex_declaration; // Used to construct the input layout.
  62. };
  63. class StateCache
  64. {
  65. public:
  66. StateCache();
  67. static void Init();
  68. // Get D3D12 descs for the internal state bitfields.
  69. static D3D12_SAMPLER_DESC GetDesc12(SamplerState state);
  70. static D3D12_BLEND_DESC GetDesc12(BlendState state);
  71. static D3D12_RASTERIZER_DESC GetDesc12(RasterizerState state);
  72. static D3D12_DEPTH_STENCIL_DESC GetDesc12(ZMode state);
  73. HRESULT GetPipelineStateObjectFromCache(D3D12_GRAPHICS_PIPELINE_STATE_DESC* pso_desc,
  74. ID3D12PipelineState** pso);
  75. HRESULT GetPipelineStateObjectFromCache(SmallPsoDesc* pso_desc, ID3D12PipelineState** pso,
  76. D3D12_PRIMITIVE_TOPOLOGY_TYPE topology,
  77. const GeometryShaderUid* gs_uid,
  78. const PixelShaderUid* ps_uid,
  79. const VertexShaderUid* vs_uid);
  80. // Called when the MSAA count/quality changes. Invalidates all small PSOs.
  81. void OnMSAASettingsChanged();
  82. // Release all cached states and clear hash tables.
  83. void Clear();
  84. private:
  85. friend DX12::PipelineStateCacheInserter;
  86. D3D12_GRAPHICS_PIPELINE_STATE_DESC m_current_pso_desc;
  87. struct hash_pso_desc
  88. {
  89. size_t operator()(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& pso_desc) const
  90. {
  91. return ((uintptr_t)pso_desc.PS.pShaderBytecode * 1000000) ^
  92. ((uintptr_t)pso_desc.VS.pShaderBytecode * 1000) ^
  93. ((uintptr_t)pso_desc.InputLayout.pInputElementDescs);
  94. }
  95. };
  96. struct equality_pipeline_state_desc
  97. {
  98. bool operator()(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& lhs,
  99. const D3D12_GRAPHICS_PIPELINE_STATE_DESC& rhs) const
  100. {
  101. return std::tie(
  102. lhs.PS.pShaderBytecode, lhs.VS.pShaderBytecode, lhs.GS.pShaderBytecode,
  103. lhs.RasterizerState.CullMode, lhs.DepthStencilState.DepthEnable,
  104. lhs.DepthStencilState.DepthFunc, lhs.DepthStencilState.DepthWriteMask,
  105. lhs.BlendState.RenderTarget[0].BlendEnable, lhs.BlendState.RenderTarget[0].BlendOp,
  106. lhs.BlendState.RenderTarget[0].DestBlend, lhs.BlendState.RenderTarget[0].SrcBlend,
  107. lhs.BlendState.RenderTarget[0].RenderTargetWriteMask, lhs.RTVFormats[0],
  108. lhs.SampleDesc.Count) ==
  109. std::tie(
  110. rhs.PS.pShaderBytecode, rhs.VS.pShaderBytecode, rhs.GS.pShaderBytecode,
  111. rhs.RasterizerState.CullMode, rhs.DepthStencilState.DepthEnable,
  112. rhs.DepthStencilState.DepthFunc, rhs.DepthStencilState.DepthWriteMask,
  113. rhs.BlendState.RenderTarget[0].BlendEnable, rhs.BlendState.RenderTarget[0].BlendOp,
  114. rhs.BlendState.RenderTarget[0].DestBlend, rhs.BlendState.RenderTarget[0].SrcBlend,
  115. rhs.BlendState.RenderTarget[0].RenderTargetWriteMask, rhs.RTVFormats[0],
  116. rhs.SampleDesc.Count);
  117. }
  118. };
  119. std::unordered_map<D3D12_GRAPHICS_PIPELINE_STATE_DESC, ID3D12PipelineState*, hash_pso_desc,
  120. equality_pipeline_state_desc>
  121. m_pso_map;
  122. struct hash_small_pso_desc
  123. {
  124. size_t operator()(const SmallPsoDesc& pso_desc) const
  125. {
  126. return ((uintptr_t)pso_desc.vs_bytecode.pShaderBytecode << 10) ^
  127. ((uintptr_t)pso_desc.ps_bytecode.pShaderBytecode) + pso_desc.blend_state.hex +
  128. pso_desc.depth_stencil_state.hex;
  129. }
  130. };
  131. struct equality_small_pipeline_state_desc
  132. {
  133. bool operator()(const SmallPsoDesc& lhs, const SmallPsoDesc& rhs) const
  134. {
  135. return std::tie(lhs.ps_bytecode.pShaderBytecode, lhs.vs_bytecode.pShaderBytecode,
  136. lhs.gs_bytecode.pShaderBytecode, lhs.input_layout, lhs.blend_state.hex,
  137. lhs.depth_stencil_state.hex, lhs.rasterizer_state.hex) ==
  138. std::tie(rhs.ps_bytecode.pShaderBytecode, rhs.vs_bytecode.pShaderBytecode,
  139. rhs.gs_bytecode.pShaderBytecode, rhs.input_layout, rhs.blend_state.hex,
  140. rhs.depth_stencil_state.hex, rhs.rasterizer_state.hex);
  141. }
  142. };
  143. struct hash_shader_bytecode
  144. {
  145. size_t operator()(const D3D12_SHADER_BYTECODE& shader) const
  146. {
  147. return (uintptr_t)shader.pShaderBytecode;
  148. }
  149. };
  150. struct equality_shader_bytecode
  151. {
  152. bool operator()(const D3D12_SHADER_BYTECODE& lhs, const D3D12_SHADER_BYTECODE& rhs) const
  153. {
  154. return lhs.pShaderBytecode == rhs.pShaderBytecode;
  155. }
  156. };
  157. std::unordered_map<SmallPsoDesc, ID3D12PipelineState*, hash_small_pso_desc,
  158. equality_small_pipeline_state_desc>
  159. m_small_pso_map;
  160. };
  161. } // namespace DX12