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);