duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

d3d11_device.h (9701B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
      3 
      4 #pragma once
      5 
      6 #include "d3d11_stream_buffer.h"
      7 #include "gpu_device.h"
      8 
      9 #include "common/windows_headers.h"
     10 
     11 #include <d3d11_1.h>
     12 #include <dxgi1_5.h>
     13 #include <memory>
     14 #include <string>
     15 #include <string_view>
     16 #include <unordered_map>
     17 #include <vector>
     18 #include <wrl/client.h>
     19 
     20 class D3D11Pipeline;
     21 class D3D11Shader;
     22 class D3D11Texture;
     23 class D3D11TextureBuffer;
     24 
     25 class D3D11Device final : public GPUDevice
     26 {
     27 public:
     28   template<typename T>
     29   using ComPtr = Microsoft::WRL::ComPtr<T>;
     30 
     31   D3D11Device();
     32   ~D3D11Device();
     33 
     34   ALWAYS_INLINE static D3D11Device& GetInstance() { return *static_cast<D3D11Device*>(g_gpu_device.get()); }
     35   ALWAYS_INLINE static ID3D11Device* GetD3DDevice() { return GetInstance().m_device.Get(); }
     36   ALWAYS_INLINE static ID3D11DeviceContext1* GetD3DContext() { return GetInstance().m_context.Get(); }
     37   ALWAYS_INLINE static D3D_FEATURE_LEVEL GetMaxFeatureLevel() { return GetInstance().m_max_feature_level; }
     38 
     39   RenderAPI GetRenderAPI() const override;
     40 
     41   bool HasSurface() const override;
     42 
     43   bool UpdateWindow() override;
     44   void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
     45   bool SupportsExclusiveFullscreen() const override;
     46   void DestroySurface() override;
     47 
     48   std::string GetDriverInfo() const override;
     49 
     50   void ExecuteAndWaitForGPUIdle() override;
     51 
     52   std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
     53                                             GPUTexture::Type type, GPUTexture::Format format,
     54                                             const void* data = nullptr, u32 data_stride = 0) override;
     55   std::unique_ptr<GPUSampler> CreateSampler(const GPUSampler::Config& config) override;
     56   std::unique_ptr<GPUTextureBuffer> CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements) override;
     57 
     58   std::unique_ptr<GPUDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GPUTexture::Format format) override;
     59   std::unique_ptr<GPUDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GPUTexture::Format format,
     60                                                             void* memory, size_t memory_size,
     61                                                             u32 memory_stride) override;
     62 
     63   bool SupportsTextureFormat(GPUTexture::Format format) const override;
     64   void CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
     65                          u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
     66   void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
     67                             u32 src_x, u32 src_y, u32 width, u32 height) override;
     68   void ClearRenderTarget(GPUTexture* t, u32 c) override;
     69   void ClearDepth(GPUTexture* t, float d) override;
     70   void InvalidateRenderTarget(GPUTexture* t) override;
     71 
     72   std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, std::span<const u8> data,
     73                                                     Error* error) override;
     74   std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language,
     75                                                     std::string_view source, const char* entry_point,
     76                                                     DynamicHeapArray<u8>* out_binary, Error* error) override;
     77   std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override;
     78 
     79   void PushDebugGroup(const char* name) override;
     80   void PopDebugGroup() override;
     81   void InsertDebugMessage(const char* msg) override;
     82 
     83   void MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space,
     84                        u32* map_base_vertex) override;
     85   void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
     86   void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
     87   void UnmapIndexBuffer(u32 used_index_count) override;
     88   void PushUniformBuffer(const void* data, u32 data_size) override;
     89   void* MapUniformBuffer(u32 size) override;
     90   void UnmapUniformBuffer(u32 size) override;
     91   void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
     92                         GPUPipeline::RenderPassFlag flags = GPUPipeline::NoRenderPassFlags) override;
     93   void SetPipeline(GPUPipeline* pipeline) override;
     94   void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler) override;
     95   void SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer) override;
     96   void SetViewport(const GSVector4i rc) override;
     97   void SetScissor(const GSVector4i rc) override;
     98   void Draw(u32 vertex_count, u32 base_vertex) override;
     99   void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
    100   void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
    101 
    102   void SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) override;
    103 
    104   bool SetGPUTimingEnabled(bool enabled) override;
    105   float GetAndResetAccumulatedGPUTime() override;
    106 
    107   bool BeginPresent(bool skip_present, u32 clear_color) override;
    108   void EndPresent(bool explicit_present) override;
    109   void SubmitPresent() override;
    110 
    111   void UnbindPipeline(D3D11Pipeline* pl);
    112   void UnbindTexture(D3D11Texture* tex);
    113 
    114 protected:
    115   bool CreateDevice(std::string_view adapter, bool threaded_presentation,
    116                     std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features,
    117                     Error* error) override;
    118   void DestroyDevice() override;
    119 
    120 private:
    121   using BlendStateMapKey = std::pair<u64, u32>;
    122   struct BlendStateMapHash
    123   {
    124     size_t operator()(const BlendStateMapKey& key) const;
    125   };
    126   using RasterizationStateMap = std::unordered_map<u8, ComPtr<ID3D11RasterizerState>>;
    127   using DepthStateMap = std::unordered_map<u8, ComPtr<ID3D11DepthStencilState>>;
    128   using BlendStateMap = std::unordered_map<BlendStateMapKey, ComPtr<ID3D11BlendState>, BlendStateMapHash>;
    129   using InputLayoutMap =
    130     std::unordered_map<GPUPipeline::InputLayout, ComPtr<ID3D11InputLayout>, GPUPipeline::InputLayoutHash>;
    131 
    132   static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024;
    133   static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024;
    134   static constexpr u32 MAX_UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024;
    135   static constexpr u32 MIN_UNIFORM_BUFFER_SIZE = 16;
    136   static constexpr u32 UNIFORM_BUFFER_ALIGNMENT = 256;
    137   static constexpr u32 UNIFORM_BUFFER_ALIGNMENT_DISCARD = 16;
    138   static constexpr u8 NUM_TIMESTAMP_QUERIES = 3;
    139 
    140   void SetFeatures(FeatureMask disabled_features);
    141 
    142   u32 GetSwapChainBufferCount() const;
    143   bool CreateSwapChain();
    144   bool CreateSwapChainRTV();
    145   void DestroySwapChain();
    146 
    147   bool CreateBuffers();
    148   void DestroyBuffers();
    149 
    150   bool IsRenderTargetBound(const D3D11Texture* tex) const;
    151 
    152   ComPtr<ID3D11RasterizerState> GetRasterizationState(const GPUPipeline::RasterizationState& rs, Error* error);
    153   ComPtr<ID3D11DepthStencilState> GetDepthState(const GPUPipeline::DepthState& ds, Error* error);
    154   ComPtr<ID3D11BlendState> GetBlendState(const GPUPipeline::BlendState& bs, u32 num_rts, Error* error);
    155   ComPtr<ID3D11InputLayout> GetInputLayout(const GPUPipeline::InputLayout& il, const D3D11Shader* vs, Error* error);
    156 
    157   bool CreateTimestampQueries();
    158   void DestroyTimestampQueries();
    159   void PopTimestampQuery();
    160   void KickTimestampQuery();
    161 
    162   ComPtr<ID3D11Device1> m_device;
    163   ComPtr<ID3D11DeviceContext1> m_context;
    164   ComPtr<ID3DUserDefinedAnnotation> m_annotation;
    165 
    166   ComPtr<IDXGIFactory5> m_dxgi_factory;
    167   ComPtr<IDXGISwapChain1> m_swap_chain;
    168   ComPtr<ID3D11RenderTargetView> m_swap_chain_rtv;
    169 
    170   RasterizationStateMap m_rasterization_states;
    171   DepthStateMap m_depth_states;
    172   BlendStateMap m_blend_states;
    173   InputLayoutMap m_input_layouts;
    174 
    175   D3D_FEATURE_LEVEL m_max_feature_level = D3D_FEATURE_LEVEL_10_0;
    176   bool m_allow_tearing_supported = false;
    177   bool m_using_flip_model_swap_chain = true;
    178   bool m_using_allow_tearing = false;
    179   bool m_is_exclusive_fullscreen = false;
    180 
    181   D3D11StreamBuffer m_vertex_buffer;
    182   D3D11StreamBuffer m_index_buffer;
    183   D3D11StreamBuffer m_uniform_buffer;
    184 
    185   D3D11Pipeline* m_current_pipeline = nullptr;
    186   std::array<D3D11Texture*, MAX_RENDER_TARGETS> m_current_render_targets = {};
    187   u32 m_num_current_render_targets = 0;
    188   GPUPipeline::RenderPassFlag m_current_render_pass_flags = GPUPipeline::NoRenderPassFlags;
    189   D3D11Texture* m_current_depth_target = nullptr;
    190 
    191   ID3D11InputLayout* m_current_input_layout = nullptr;
    192   ID3D11VertexShader* m_current_vertex_shader = nullptr;
    193   ID3D11GeometryShader* m_current_geometry_shader = nullptr;
    194   ID3D11PixelShader* m_current_pixel_shader = nullptr;
    195   ID3D11RasterizerState* m_current_rasterizer_state = nullptr;
    196   ID3D11DepthStencilState* m_current_depth_state = nullptr;
    197   ID3D11BlendState* m_current_blend_state = nullptr;
    198   D3D_PRIMITIVE_TOPOLOGY m_current_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
    199   u32 m_current_vertex_stride = 0;
    200   u32 m_current_blend_factor = 0;
    201 
    202   std::array<ID3D11ShaderResourceView*, MAX_TEXTURE_SAMPLERS> m_current_textures = {};
    203   std::array<ID3D11SamplerState*, MAX_TEXTURE_SAMPLERS> m_current_samplers = {};
    204 
    205   std::array<std::array<ComPtr<ID3D11Query>, 3>, NUM_TIMESTAMP_QUERIES> m_timestamp_queries = {};
    206   u8 m_read_timestamp_query = 0;
    207   u8 m_write_timestamp_query = 0;
    208   u8 m_waiting_timestamp_queries = 0;
    209   bool m_timestamp_query_started = false;
    210   float m_accumulated_gpu_time = 0.0f;
    211 };
    212 
    213 void SetD3DDebugObjectName(ID3D11DeviceChild* obj, std::string_view name);