D3DState.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2014 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <bitset>
  6. #include <cstddef>
  7. #include <memory>
  8. #include <mutex>
  9. #include <unordered_map>
  10. #include "Common/BitField.h"
  11. #include "Common/CommonTypes.h"
  12. #include "VideoBackends/D3D/D3DBase.h"
  13. #include "VideoCommon/Constants.h"
  14. #include "VideoCommon/RenderState.h"
  15. namespace DX11
  16. {
  17. class DXFramebuffer;
  18. class StateCache
  19. {
  20. public:
  21. ~StateCache();
  22. // Get existing or create new render state.
  23. // Returned objects is owned by the cache and does not need to be released.
  24. ID3D11SamplerState* Get(SamplerState state);
  25. ID3D11BlendState* Get(BlendingState state);
  26. ID3D11RasterizerState* Get(RasterizationState state);
  27. ID3D11DepthStencilState* Get(DepthState state);
  28. // Convert RasterState primitive type to D3D11 primitive topology.
  29. static D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology(PrimitiveType primitive);
  30. private:
  31. std::unordered_map<u32, ComPtr<ID3D11DepthStencilState>> m_depth;
  32. std::unordered_map<u32, ComPtr<ID3D11RasterizerState>> m_raster;
  33. std::unordered_map<u32, ComPtr<ID3D11BlendState>> m_blend;
  34. std::unordered_map<SamplerState, ComPtr<ID3D11SamplerState>> m_sampler;
  35. std::mutex m_lock;
  36. };
  37. namespace D3D
  38. {
  39. class StateManager
  40. {
  41. public:
  42. StateManager();
  43. ~StateManager();
  44. void SetBlendState(ID3D11BlendState* state)
  45. {
  46. if (m_current.blendState != state)
  47. m_dirtyFlags.set(DirtyFlag_BlendState);
  48. m_pending.blendState = state;
  49. }
  50. void SetDepthState(ID3D11DepthStencilState* state)
  51. {
  52. if (m_current.depthState != state)
  53. m_dirtyFlags.set(DirtyFlag_DepthState);
  54. m_pending.depthState = state;
  55. }
  56. void SetRasterizerState(ID3D11RasterizerState* state)
  57. {
  58. if (m_current.rasterizerState != state)
  59. m_dirtyFlags.set(DirtyFlag_RasterizerState);
  60. m_pending.rasterizerState = state;
  61. }
  62. void SetTexture(size_t index, ID3D11ShaderResourceView* texture)
  63. {
  64. if (m_current.textures[index] != texture)
  65. m_dirtyFlags.set(DirtyFlag_Texture0 + index);
  66. m_pending.textures[index] = texture;
  67. }
  68. void SetSampler(size_t index, ID3D11SamplerState* sampler)
  69. {
  70. if (m_current.samplers[index] != sampler)
  71. m_dirtyFlags.set(DirtyFlag_Sampler0 + index);
  72. m_pending.samplers[index] = sampler;
  73. }
  74. void SetPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr,
  75. ID3D11Buffer* buffer2 = nullptr)
  76. {
  77. if (m_current.pixelConstants[0] != buffer0 || m_current.pixelConstants[1] != buffer1 ||
  78. m_current.pixelConstants[2] != buffer2)
  79. m_dirtyFlags.set(DirtyFlag_PixelConstants);
  80. m_pending.pixelConstants[0] = buffer0;
  81. m_pending.pixelConstants[1] = buffer1;
  82. m_pending.pixelConstants[2] = buffer2;
  83. }
  84. void SetVertexConstants(ID3D11Buffer* buffer)
  85. {
  86. if (m_current.vertexConstants != buffer)
  87. m_dirtyFlags.set(DirtyFlag_VertexConstants);
  88. m_pending.vertexConstants = buffer;
  89. }
  90. void SetGeometryConstants(ID3D11Buffer* buffer)
  91. {
  92. if (m_current.geometryConstants != buffer)
  93. m_dirtyFlags.set(DirtyFlag_GeometryConstants);
  94. m_pending.geometryConstants = buffer;
  95. }
  96. void SetVertexBuffer(ID3D11Buffer* buffer, u32 stride, u32 offset)
  97. {
  98. if (m_current.vertexBuffer != buffer || m_current.vertexBufferStride != stride ||
  99. m_current.vertexBufferOffset != offset)
  100. m_dirtyFlags.set(DirtyFlag_VertexBuffer);
  101. m_pending.vertexBuffer = buffer;
  102. m_pending.vertexBufferStride = stride;
  103. m_pending.vertexBufferOffset = offset;
  104. }
  105. void SetIndexBuffer(ID3D11Buffer* buffer)
  106. {
  107. if (m_current.indexBuffer != buffer)
  108. m_dirtyFlags.set(DirtyFlag_IndexBuffer);
  109. m_pending.indexBuffer = buffer;
  110. }
  111. void SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
  112. {
  113. if (m_current.topology != topology)
  114. m_dirtyFlags.set(DirtyFlag_InputAssembler);
  115. m_pending.topology = topology;
  116. }
  117. void SetInputLayout(ID3D11InputLayout* layout)
  118. {
  119. if (m_current.inputLayout != layout)
  120. m_dirtyFlags.set(DirtyFlag_InputAssembler);
  121. m_pending.inputLayout = layout;
  122. }
  123. void SetPixelShader(ID3D11PixelShader* shader)
  124. {
  125. if (m_current.pixelShader != shader)
  126. m_dirtyFlags.set(DirtyFlag_PixelShader);
  127. m_pending.pixelShader = shader;
  128. }
  129. void SetPixelShaderDynamic(ID3D11PixelShader* shader, ID3D11ClassInstance* const* classInstances,
  130. u32 classInstancesCount)
  131. {
  132. D3D::context->PSSetShader(shader, classInstances, classInstancesCount);
  133. m_current.pixelShader = shader;
  134. m_pending.pixelShader = shader;
  135. }
  136. void SetVertexShader(ID3D11VertexShader* shader)
  137. {
  138. if (m_current.vertexShader != shader)
  139. m_dirtyFlags.set(DirtyFlag_VertexShader);
  140. m_pending.vertexShader = shader;
  141. }
  142. void SetGeometryShader(ID3D11GeometryShader* shader)
  143. {
  144. if (m_current.geometryShader != shader)
  145. m_dirtyFlags.set(DirtyFlag_GeometryShader);
  146. m_pending.geometryShader = shader;
  147. }
  148. void SetFramebuffer(DXFramebuffer* fb)
  149. {
  150. if (m_current.framebuffer != fb)
  151. m_dirtyFlags.set(DirtyFlag_Framebuffer);
  152. m_pending.framebuffer = fb;
  153. }
  154. void SetOMUAV(ID3D11UnorderedAccessView* uav)
  155. {
  156. if (m_current.uav != uav)
  157. m_dirtyFlags.set(DirtyFlag_Framebuffer);
  158. m_pending.uav = uav;
  159. }
  160. void SetIntegerRTV(bool enable)
  161. {
  162. if (m_current.use_integer_rtv != enable)
  163. m_dirtyFlags.set(DirtyFlag_Framebuffer);
  164. m_pending.use_integer_rtv = enable;
  165. }
  166. // removes currently set texture from all slots, returns mask of previously bound slots
  167. u32 UnsetTexture(ID3D11ShaderResourceView* srv);
  168. void SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceView* srv);
  169. void ApplyTextures();
  170. // call this immediately before any drawing operation or to explicitly apply pending resource
  171. // state changes
  172. void Apply();
  173. // Binds constant buffers/textures/samplers to the compute shader stage.
  174. // We don't track these explicitly because it's not often-used.
  175. void SetComputeUAV(u32 index, ID3D11UnorderedAccessView* uav);
  176. void SetComputeShader(ID3D11ComputeShader* shader);
  177. void SyncComputeBindings();
  178. private:
  179. enum DirtyFlags
  180. {
  181. DirtyFlag_Texture0 = 0,
  182. DirtyFlag_Sampler0 = DirtyFlag_Texture0 + VideoCommon::MAX_PIXEL_SHADER_SAMPLERS,
  183. DirtyFlag_PixelConstants = DirtyFlag_Sampler0 + VideoCommon::MAX_PIXEL_SHADER_SAMPLERS,
  184. DirtyFlag_VertexConstants,
  185. DirtyFlag_GeometryConstants,
  186. DirtyFlag_VertexBuffer,
  187. DirtyFlag_IndexBuffer,
  188. DirtyFlag_PixelShader,
  189. DirtyFlag_VertexShader,
  190. DirtyFlag_GeometryShader,
  191. DirtyFlag_InputAssembler,
  192. DirtyFlag_BlendState,
  193. DirtyFlag_DepthState,
  194. DirtyFlag_RasterizerState,
  195. DirtyFlag_Framebuffer,
  196. DirtyFlag_Max
  197. };
  198. std::bitset<DirtyFlags::DirtyFlag_Max> m_dirtyFlags;
  199. struct Resources
  200. {
  201. std::array<ID3D11ShaderResourceView*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures;
  202. std::array<ID3D11SamplerState*, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> samplers;
  203. std::array<ID3D11Buffer*, 3> pixelConstants;
  204. ID3D11Buffer* vertexConstants;
  205. ID3D11Buffer* geometryConstants;
  206. ID3D11Buffer* vertexBuffer;
  207. ID3D11Buffer* indexBuffer;
  208. u32 vertexBufferStride;
  209. u32 vertexBufferOffset;
  210. D3D11_PRIMITIVE_TOPOLOGY topology;
  211. ID3D11InputLayout* inputLayout;
  212. ID3D11PixelShader* pixelShader;
  213. ID3D11VertexShader* vertexShader;
  214. ID3D11GeometryShader* geometryShader;
  215. ID3D11BlendState* blendState;
  216. ID3D11DepthStencilState* depthState;
  217. ID3D11RasterizerState* rasterizerState;
  218. DXFramebuffer* framebuffer;
  219. ID3D11UnorderedAccessView* uav;
  220. bool use_integer_rtv;
  221. };
  222. Resources m_pending = {};
  223. Resources m_current = {};
  224. // Compute resources are synced with the graphics resources when we need them.
  225. ID3D11Buffer* m_compute_constants = nullptr;
  226. std::array<ID3D11ShaderResourceView*, VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS>
  227. m_compute_textures{};
  228. std::array<ID3D11SamplerState*, VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS> m_compute_samplers{};
  229. std::array<ID3D11UnorderedAccessView*, VideoCommon::MAX_COMPUTE_SHADER_SAMPLERS>
  230. m_compute_images{};
  231. ID3D11ComputeShader* m_compute_shader = nullptr;
  232. };
  233. extern std::unique_ptr<StateManager> stateman;
  234. } // namespace D3D
  235. } // namespace DX11