/* * This file is part of libplacebo. * * libplacebo is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * libplacebo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with libplacebo. If not, see . */ #pragma once #include #include #include #include #include #include "../gpu.h" #include "../glsl/spirv.h" #include "common.h" #include "utils.h" pl_gpu pl_gpu_create_d3d11(struct d3d11_ctx *ctx); // --- pl_gpu internal structs and helpers // Size of one constant in a constant buffer #define CBUF_ELEM (sizeof(float[4])) struct d3d_stream_buf { UINT bind_flags; ID3D11Buffer *buf; size_t size; size_t used; unsigned int align; }; struct pl_gpu_d3d11 { struct pl_gpu_fns impl; struct d3d11_ctx *ctx; ID3D11Device *dev; ID3D11Device1 *dev1; ID3D11Device5 *dev5; ID3D11DeviceContext *imm; ID3D11DeviceContext1 *imm1; ID3D11DeviceContext4 *imm4; // The Direct3D 11 minor version number int minor; pl_spirv spirv; pD3DCompile D3DCompile; struct dll_version d3d_compiler_ver; // Device capabilities D3D_FEATURE_LEVEL fl; bool has_timestamp_queries; bool has_monitored_fences; int max_srvs; int max_uavs; // Streaming vertex and index buffers struct d3d_stream_buf vbuf; struct d3d_stream_buf ibuf; // Shared rasterizer state ID3D11RasterizerState *rstate; // Shared depth-stencil state ID3D11DepthStencilState *dsstate; // Array of ID3D11SamplerStates for every combination of sample/address modes ID3D11SamplerState *samplers[PL_TEX_SAMPLE_MODE_COUNT][PL_TEX_ADDRESS_MODE_COUNT]; // Resources for finish() ID3D11Fence *finish_fence; uint64_t finish_value; HANDLE finish_event; ID3D11Query *finish_query; pl_buf finish_buf_src; pl_buf finish_buf_dst; }; void pl_d3d11_setup_formats(struct pl_gpu_t *gpu); void pl_d3d11_timer_start(pl_gpu gpu, pl_timer timer); void pl_d3d11_timer_end(pl_gpu gpu, pl_timer timer); struct pl_buf_d3d11 { ID3D11Buffer *buf; ID3D11Buffer *staging; ID3D11ShaderResourceView *raw_srv; ID3D11UnorderedAccessView *raw_uav; ID3D11ShaderResourceView *texel_srv; ID3D11UnorderedAccessView *texel_uav; char *data; bool dirty; }; void pl_d3d11_buf_destroy(pl_gpu gpu, pl_buf buf); pl_buf pl_d3d11_buf_create(pl_gpu gpu, const struct pl_buf_params *params); void pl_d3d11_buf_write(pl_gpu gpu, pl_buf buf, size_t offset, const void *data, size_t size); bool pl_d3d11_buf_read(pl_gpu gpu, pl_buf buf, size_t offset, void *dest, size_t size); void pl_d3d11_buf_copy(pl_gpu gpu, pl_buf dst, size_t dst_offset, pl_buf src, size_t src_offset, size_t size); // Ensure a buffer is up-to-date with its system memory mirror before it is used void pl_d3d11_buf_resolve(pl_gpu gpu, pl_buf buf); struct pl_tex_d3d11 { // res mirrors one of tex1d, tex2d or tex3d for convenience. It does not // hold an additional reference to the texture object. ID3D11Resource *res; ID3D11Texture1D *tex1d; ID3D11Texture2D *tex2d; ID3D11Texture3D *tex3d; int array_slice; // Mirrors one of staging1d, staging2d, or staging3d, and doesn't hold a ref ID3D11Resource *staging; // Staging textures for pl_tex_download ID3D11Texture1D *staging1d; ID3D11Texture2D *staging2d; ID3D11Texture3D *staging3d; ID3D11ShaderResourceView *srv; ID3D11RenderTargetView *rtv; ID3D11UnorderedAccessView *uav; // for tex_upload/download fallback code pl_fmt texel_fmt; }; void pl_d3d11_tex_destroy(pl_gpu gpu, pl_tex tex); pl_tex pl_d3d11_tex_create(pl_gpu gpu, const struct pl_tex_params *params); void pl_d3d11_tex_invalidate(pl_gpu gpu, pl_tex tex); void pl_d3d11_tex_clear_ex(pl_gpu gpu, pl_tex tex, const union pl_clear_color color); void pl_d3d11_tex_blit(pl_gpu gpu, const struct pl_tex_blit_params *params); bool pl_d3d11_tex_upload(pl_gpu gpu, const struct pl_tex_transfer_params *params); bool pl_d3d11_tex_download(pl_gpu gpu, const struct pl_tex_transfer_params *params); // Constant buffer layout used for gl_NumWorkGroups emulation struct d3d_num_workgroups_buf { alignas(CBUF_ELEM) uint32_t num_wgs[3]; }; enum { HLSL_BINDING_NOT_USED = -1, // Slot should always be bound as NULL HLSL_BINDING_NUM_WORKGROUPS = -2, // Slot used for gl_NumWorkGroups emulation }; // Represents a specific shader stage in a pl_pass (VS, PS, CS) struct d3d_pass_stage { // Lists for each resource type, to simplify binding in pl_pass_run. Indexes // match the index of the arrays passed to the ID3D11DeviceContext methods. // Entries are the index of pass->params.descriptors which should be bound // in that position, or a HLSL_BINDING_* special value. PL_ARRAY(int) cbvs; PL_ARRAY(int) srvs; PL_ARRAY(int) samplers; }; struct pl_pass_d3d11 { ID3D11PixelShader *ps; ID3D11VertexShader *vs; ID3D11ComputeShader *cs; ID3D11InputLayout *layout; ID3D11BlendState *bstate; // gl_NumWorkGroups emulation struct d3d_num_workgroups_buf last_num_wgs; ID3D11Buffer *num_workgroups_buf; bool num_workgroups_used; // Maximum binding number int max_binding; struct d3d_pass_stage main; // PS and CS struct d3d_pass_stage vertex; // List of resources, as in `struct pass_stage`, except UAVs are shared // between all shader stages PL_ARRAY(int) uavs; // Pre-allocated resource arrays to use in pl_pass_run ID3D11Buffer **cbv_arr; ID3D11ShaderResourceView **srv_arr; ID3D11SamplerState **sampler_arr; ID3D11UnorderedAccessView **uav_arr; }; void pl_d3d11_pass_destroy(pl_gpu gpu, pl_pass pass); const struct pl_pass_t *pl_d3d11_pass_create(pl_gpu gpu, const struct pl_pass_params *params); void pl_d3d11_pass_run(pl_gpu gpu, const struct pl_pass_run_params *params);