1 /* 2 * This file is part of libplacebo. 3 * 4 * libplacebo is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * libplacebo is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #pragma once 19 20 #include <stdalign.h> 21 #include <d3d11_4.h> 22 #include <dxgi1_6.h> 23 #include <d3dcompiler.h> 24 #include <spirv_cross_c.h> 25 26 #include "../gpu.h" 27 28 #include "common.h" 29 #include "utils.h" 30 31 pl_gpu pl_gpu_create_d3d11(struct d3d11_ctx *ctx); 32 33 // --- pl_gpu internal structs and helpers 34 35 // Size of one constant in a constant buffer 36 #define CBUF_ELEM (sizeof(float[4])) 37 38 struct d3d_stream_buf { 39 UINT bind_flags; 40 ID3D11Buffer *buf; 41 size_t size; 42 size_t used; 43 unsigned int align; 44 }; 45 46 struct pl_gpu_d3d11 { 47 struct pl_gpu_fns impl; 48 struct d3d11_ctx *ctx; 49 ID3D11Device *dev; 50 ID3D11Device1 *dev1; 51 ID3D11Device5 *dev5; 52 ID3D11DeviceContext *imm; 53 ID3D11DeviceContext1 *imm1; 54 ID3D11DeviceContext4 *imm4; 55 56 struct spirv_compiler *spirv; 57 58 pD3DCompile D3DCompile; 59 struct dll_version d3d_compiler_ver; 60 61 // Device capabilities 62 D3D_FEATURE_LEVEL fl; 63 bool has_timestamp_queries; 64 bool has_monitored_fences; 65 66 int max_srvs; 67 int max_uavs; 68 69 // This is a pl_dispatch used on ourselves for the purposes of dispatching 70 // shaders for performing various emulation tasks (e.g. blits). 71 // Warning: As in pl_vk, care must be taken to avoid recursive calls. 72 struct pl_dispatch *dp; 73 74 // Streaming vertex and index buffers 75 struct d3d_stream_buf vbuf; 76 struct d3d_stream_buf ibuf; 77 78 // Shared rasterizer state 79 ID3D11RasterizerState *rstate; 80 81 // Shared depth-stencil state 82 ID3D11DepthStencilState *dsstate; 83 84 // Array of ID3D11SamplerStates for every combination of sample/address modes 85 ID3D11SamplerState *samplers[PL_TEX_SAMPLE_MODE_COUNT][PL_TEX_ADDRESS_MODE_COUNT]; 86 87 // Resources for finish() 88 ID3D11Fence *finish_fence; 89 uint64_t finish_value; 90 HANDLE finish_event; 91 ID3D11Query *finish_query; 92 pl_buf finish_buf_src; 93 pl_buf finish_buf_dst; 94 }; 95 96 void pl_d3d11_setup_formats(struct pl_gpu *gpu); 97 98 void pl_d3d11_timer_start(pl_gpu gpu, pl_timer timer); 99 void pl_d3d11_timer_end(pl_gpu gpu, pl_timer timer); 100 101 struct pl_buf_d3d11 { 102 ID3D11Buffer *buf; 103 ID3D11Buffer *staging; 104 ID3D11ShaderResourceView *raw_srv; 105 ID3D11UnorderedAccessView *raw_uav; 106 ID3D11ShaderResourceView *texel_srv; 107 ID3D11UnorderedAccessView *texel_uav; 108 109 char *data; 110 bool dirty; 111 }; 112 113 void pl_d3d11_buf_destroy(pl_gpu gpu, pl_buf buf); 114 pl_buf pl_d3d11_buf_create(pl_gpu gpu, const struct pl_buf_params *params); 115 void pl_d3d11_buf_write(pl_gpu gpu, pl_buf buf, size_t offset, const void *data, 116 size_t size); 117 bool pl_d3d11_buf_read(pl_gpu gpu, pl_buf buf, size_t offset, void *dest, 118 size_t size); 119 void pl_d3d11_buf_copy(pl_gpu gpu, pl_buf dst, size_t dst_offset, pl_buf src, 120 size_t src_offset, size_t size); 121 122 // Ensure a buffer is up-to-date with its system memory mirror before it is used 123 void pl_d3d11_buf_resolve(pl_gpu gpu, pl_buf buf); 124 125 struct pl_tex_d3d11 { 126 // res mirrors one of tex1d, tex2d or tex3d for convenience. It does not 127 // hold an additional reference to the texture object. 128 ID3D11Resource *res; 129 130 ID3D11Texture1D *tex1d; 131 ID3D11Texture2D *tex2d; 132 ID3D11Texture3D *tex3d; 133 int array_slice; 134 135 // Mirrors one of staging1d, staging2d, or staging3d, and doesn't hold a ref 136 ID3D11Resource *staging; 137 138 // Staging textures for pl_tex_download 139 ID3D11Texture1D *staging1d; 140 ID3D11Texture2D *staging2d; 141 ID3D11Texture3D *staging3d; 142 143 ID3D11ShaderResourceView *srv; 144 ID3D11RenderTargetView *rtv; 145 ID3D11UnorderedAccessView *uav; 146 }; 147 148 void pl_d3d11_tex_destroy(pl_gpu gpu, pl_tex tex); 149 pl_tex pl_d3d11_tex_create(pl_gpu gpu, const struct pl_tex_params *params); 150 void pl_d3d11_tex_invalidate(pl_gpu gpu, pl_tex tex); 151 void pl_d3d11_tex_clear_ex(pl_gpu gpu, pl_tex tex, 152 const union pl_clear_color color); 153 void pl_d3d11_tex_blit(pl_gpu gpu, const struct pl_tex_blit_params *params); 154 bool pl_d3d11_tex_upload(pl_gpu gpu, const struct pl_tex_transfer_params *params); 155 bool pl_d3d11_tex_download(pl_gpu gpu, const struct pl_tex_transfer_params *params); 156 157 // Constant buffer layout used for gl_NumWorkGroups emulation 158 struct d3d_num_workgroups_buf { 159 alignas(CBUF_ELEM) uint32_t num_wgs[3]; 160 }; 161 162 // Represents a descriptor binding to a specific shader stage (VS, PS, CS) 163 struct d3d_desc_stage { 164 // The HLSL register number used for this resource 165 int cbv_slot; // register(bN) 166 int srv_slot; // register(tN) 167 int sampler_slot; // register(sN) 168 int uav_slot; // register(uN) 169 170 // Is the resource used in this shader pass? Used to optimize pipeline 171 // binding for resources that are used in the vertex shader but not the 172 // fragment shader or vice versa. 173 bool used; 174 }; 175 176 struct pl_desc_d3d11 { 177 struct d3d_desc_stage main; // PS and CS 178 struct d3d_desc_stage vertex; 179 }; 180 181 enum { 182 HLSL_BINDING_NOT_USED = -1, // Slot should always be bound as NULL 183 HLSL_BINDING_NUM_WORKGROUPS = -2, // Slot used for gl_NumWorkGroups emulation 184 }; 185 186 // Represents a specific shader stage in a pl_pass (VS, PS, CS) 187 struct d3d_pass_stage { 188 // GLSL->HLSL translator state 189 spvc_context sc; 190 spvc_compiler sc_comp; 191 192 // Lists for each resource type, to simplify binding in pl_pass_run. Indexes 193 // match the index of the arrays passed to the ID3D11DeviceContext methods. 194 // Entries are the index of pass->params.descriptors which should be bound 195 // in that position, or a HLSL_BINDING_* special value. 196 PL_ARRAY(int) cbvs; 197 PL_ARRAY(int) srvs; 198 PL_ARRAY(int) samplers; 199 }; 200 201 struct pl_pass_d3d11 { 202 ID3D11PixelShader *ps; 203 ID3D11VertexShader *vs; 204 ID3D11ComputeShader *cs; 205 ID3D11InputLayout *layout; 206 ID3D11BlendState *bstate; 207 208 // gl_NumWorkGroups emulation 209 struct d3d_num_workgroups_buf last_num_wgs; 210 ID3D11Buffer *num_workgroups_buf; 211 bool num_workgroups_used; 212 213 struct pl_desc_d3d11 *descriptors; 214 215 struct d3d_pass_stage main; // PS and CS 216 struct d3d_pass_stage vertex; 217 218 // List of resources, as in `struct pass_stage`, except UAVs are shared 219 // between all shader stages 220 PL_ARRAY(int) uavs; 221 222 // Pre-allocated resource arrays to use in pl_pass_run 223 ID3D11Buffer **cbv_arr; 224 ID3D11ShaderResourceView **srv_arr; 225 ID3D11SamplerState **sampler_arr; 226 ID3D11UnorderedAccessView **uav_arr; 227 }; 228 229 void pl_d3d11_pass_destroy(pl_gpu gpu, pl_pass pass); 230 const struct pl_pass *pl_d3d11_pass_create(pl_gpu gpu, 231 const struct pl_pass_params *params); 232 void pl_d3d11_pass_run(pl_gpu gpu, const struct pl_pass_run_params *params); 233