D3DGfx.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright 2010 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "VideoBackends/D3D/D3DGfx.h"
  4. #include <algorithm>
  5. #include <array>
  6. #include <cmath>
  7. #include <cstring>
  8. #include <memory>
  9. #include <string>
  10. #include <strsafe.h>
  11. #include <tuple>
  12. #include "Common/Assert.h"
  13. #include "Common/CommonTypes.h"
  14. #include "Common/Logging/Log.h"
  15. #include "Common/MathUtil.h"
  16. #include "Core/Core.h"
  17. #include "VideoBackends/D3D/D3DBase.h"
  18. #include "VideoBackends/D3D/D3DBoundingBox.h"
  19. #include "VideoBackends/D3D/D3DState.h"
  20. #include "VideoBackends/D3D/D3DSwapChain.h"
  21. #include "VideoBackends/D3D/DXPipeline.h"
  22. #include "VideoBackends/D3D/DXShader.h"
  23. #include "VideoBackends/D3D/DXTexture.h"
  24. #include "VideoCommon/BPFunctions.h"
  25. #include "VideoCommon/FramebufferManager.h"
  26. #include "VideoCommon/PostProcessing.h"
  27. #include "VideoCommon/Present.h"
  28. #include "VideoCommon/RenderState.h"
  29. #include "VideoCommon/VideoConfig.h"
  30. #include "VideoCommon/XFMemory.h"
  31. namespace DX11
  32. {
  33. Gfx::Gfx(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale)
  34. : m_backbuffer_scale(backbuffer_scale), m_swap_chain(std::move(swap_chain))
  35. {
  36. }
  37. Gfx::~Gfx() = default;
  38. bool Gfx::IsHeadless() const
  39. {
  40. return !m_swap_chain;
  41. }
  42. std::unique_ptr<AbstractTexture> Gfx::CreateTexture(const TextureConfig& config,
  43. std::string_view name)
  44. {
  45. return DXTexture::Create(config, name);
  46. }
  47. std::unique_ptr<AbstractStagingTexture> Gfx::CreateStagingTexture(StagingTextureType type,
  48. const TextureConfig& config)
  49. {
  50. return DXStagingTexture::Create(type, config);
  51. }
  52. std::unique_ptr<AbstractFramebuffer>
  53. Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
  54. std::vector<AbstractTexture*> additional_color_attachments)
  55. {
  56. return DXFramebuffer::Create(static_cast<DXTexture*>(color_attachment),
  57. static_cast<DXTexture*>(depth_attachment),
  58. std::move(additional_color_attachments));
  59. }
  60. std::unique_ptr<AbstractShader>
  61. Gfx::CreateShaderFromSource(ShaderStage stage, std::string_view source, std::string_view name)
  62. {
  63. auto bytecode = DXShader::CompileShader(D3D::feature_level, stage, source);
  64. if (!bytecode)
  65. return nullptr;
  66. return DXShader::CreateFromBytecode(stage, std::move(*bytecode), name);
  67. }
  68. std::unique_ptr<AbstractShader> Gfx::CreateShaderFromBinary(ShaderStage stage, const void* data,
  69. size_t length, std::string_view name)
  70. {
  71. return DXShader::CreateFromBytecode(stage, DXShader::CreateByteCode(data, length), name);
  72. }
  73. std::unique_ptr<AbstractPipeline> Gfx::CreatePipeline(const AbstractPipelineConfig& config,
  74. const void* cache_data,
  75. size_t cache_data_length)
  76. {
  77. return DXPipeline::Create(config);
  78. }
  79. void Gfx::SetPipeline(const AbstractPipeline* pipeline)
  80. {
  81. const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
  82. if (m_current_pipeline == dx_pipeline)
  83. return;
  84. if (dx_pipeline)
  85. {
  86. D3D::stateman->SetRasterizerState(dx_pipeline->GetRasterizerState());
  87. D3D::stateman->SetDepthState(dx_pipeline->GetDepthState());
  88. D3D::stateman->SetBlendState(dx_pipeline->GetBlendState());
  89. D3D::stateman->SetPrimitiveTopology(dx_pipeline->GetPrimitiveTopology());
  90. D3D::stateman->SetInputLayout(dx_pipeline->GetInputLayout());
  91. D3D::stateman->SetVertexShader(dx_pipeline->GetVertexShader());
  92. D3D::stateman->SetGeometryShader(dx_pipeline->GetGeometryShader());
  93. D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
  94. D3D::stateman->SetIntegerRTV(dx_pipeline->UseLogicOp());
  95. }
  96. else
  97. {
  98. // These will be destroyed at pipeline destruction.
  99. D3D::stateman->SetInputLayout(nullptr);
  100. D3D::stateman->SetVertexShader(nullptr);
  101. D3D::stateman->SetGeometryShader(nullptr);
  102. D3D::stateman->SetPixelShader(nullptr);
  103. }
  104. }
  105. void Gfx::SetScissorRect(const MathUtil::Rectangle<int>& rc)
  106. {
  107. // TODO: Move to stateman
  108. const CD3D11_RECT rect(rc.left, rc.top, std::max(rc.right, rc.left + 1),
  109. std::max(rc.bottom, rc.top + 1));
  110. D3D::context->RSSetScissorRects(1, &rect);
  111. }
  112. void Gfx::SetViewport(float x, float y, float width, float height, float near_depth,
  113. float far_depth)
  114. {
  115. // TODO: Move to stateman
  116. const CD3D11_VIEWPORT vp(x, y, width, height, near_depth, far_depth);
  117. D3D::context->RSSetViewports(1, &vp);
  118. }
  119. void Gfx::Draw(u32 base_vertex, u32 num_vertices)
  120. {
  121. D3D::stateman->Apply();
  122. D3D::context->Draw(num_vertices, base_vertex);
  123. }
  124. void Gfx::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
  125. {
  126. D3D::stateman->Apply();
  127. D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
  128. }
  129. void Gfx::DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y,
  130. u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z)
  131. {
  132. D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());
  133. D3D::stateman->SyncComputeBindings();
  134. D3D::context->Dispatch(groups_x, groups_y, groups_z);
  135. }
  136. bool Gfx::BindBackbuffer(const ClearColor& clear_color)
  137. {
  138. CheckForSwapChainChanges();
  139. SetAndClearFramebuffer(m_swap_chain->GetFramebuffer(), clear_color);
  140. return true;
  141. }
  142. void Gfx::PresentBackbuffer()
  143. {
  144. m_swap_chain->Present();
  145. }
  146. void Gfx::OnConfigChanged(u32 bits)
  147. {
  148. AbstractGfx::OnConfigChanged(bits);
  149. // Quad-buffer changes require swap chain recreation.
  150. if (bits & CONFIG_CHANGE_BIT_STEREO_MODE && m_swap_chain)
  151. m_swap_chain->SetStereo(SwapChain::WantsStereo());
  152. if (bits & CONFIG_CHANGE_BIT_HDR && m_swap_chain)
  153. m_swap_chain->SetHDR(SwapChain::WantsHDR());
  154. }
  155. void Gfx::CheckForSwapChainChanges()
  156. {
  157. const bool surface_changed = g_presenter->SurfaceChangedTestAndClear();
  158. const bool surface_resized =
  159. g_presenter->SurfaceResizedTestAndClear() || m_swap_chain->CheckForFullscreenChange();
  160. if (!surface_changed && !surface_resized)
  161. return;
  162. if (surface_changed)
  163. {
  164. m_swap_chain->ChangeSurface(g_presenter->GetNewSurfaceHandle());
  165. }
  166. else
  167. {
  168. m_swap_chain->ResizeSwapChain();
  169. }
  170. g_presenter->SetBackbuffer(m_swap_chain->GetWidth(), m_swap_chain->GetHeight());
  171. }
  172. void Gfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
  173. {
  174. if (m_current_framebuffer == framebuffer)
  175. return;
  176. // We can't leave the framebuffer bound as a texture and a render target.
  177. DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
  178. fb->Unbind();
  179. D3D::stateman->SetFramebuffer(fb);
  180. m_current_framebuffer = fb;
  181. }
  182. void Gfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
  183. {
  184. SetFramebuffer(framebuffer);
  185. }
  186. void Gfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value,
  187. float depth_value)
  188. {
  189. SetFramebuffer(framebuffer);
  190. D3D::stateman->Apply();
  191. DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
  192. fb->Clear(color_value, depth_value);
  193. }
  194. void Gfx::SetTexture(u32 index, const AbstractTexture* texture)
  195. {
  196. D3D::stateman->SetTexture(index, texture ? static_cast<const DXTexture*>(texture)->GetD3DSRV() :
  197. nullptr);
  198. }
  199. void Gfx::SetSamplerState(u32 index, const SamplerState& state)
  200. {
  201. D3D::stateman->SetSampler(index, m_state_cache.Get(state));
  202. }
  203. void Gfx::SetComputeImageTexture(u32 index, AbstractTexture* texture, bool read, bool write)
  204. {
  205. D3D::stateman->SetComputeUAV(index,
  206. texture ? static_cast<DXTexture*>(texture)->GetD3DUAV() : nullptr);
  207. }
  208. void Gfx::UnbindTexture(const AbstractTexture* texture)
  209. {
  210. if (D3D::stateman->UnsetTexture(static_cast<const DXTexture*>(texture)->GetD3DSRV()) != 0)
  211. D3D::stateman->ApplyTextures();
  212. }
  213. void Gfx::Flush()
  214. {
  215. D3D::context->Flush();
  216. }
  217. void Gfx::WaitForGPUIdle()
  218. {
  219. // There is no glFinish() equivalent in D3D.
  220. D3D::context->Flush();
  221. }
  222. void Gfx::SetFullscreen(bool enable_fullscreen)
  223. {
  224. if (m_swap_chain)
  225. m_swap_chain->SetFullscreen(enable_fullscreen);
  226. }
  227. bool Gfx::IsFullscreen() const
  228. {
  229. return m_swap_chain && m_swap_chain->GetFullscreen();
  230. }
  231. SurfaceInfo Gfx::GetSurfaceInfo() const
  232. {
  233. return {m_swap_chain ? static_cast<u32>(m_swap_chain->GetWidth()) : 0,
  234. m_swap_chain ? static_cast<u32>(m_swap_chain->GetHeight()) : 0, m_backbuffer_scale,
  235. m_swap_chain ? m_swap_chain->GetFormat() : AbstractTextureFormat::Undefined};
  236. }
  237. } // namespace DX11