wined3d: Move the stencil pass operation to wined3d_depth_stencil_state.
[wine.git] / dlls / wined3d / adapter_vk.c
blobf950f2a47119c04528484fe7ad3536c663477bbe
1 /*
2 * Copyright 2018 Henri Verbeet for CodeWeavers
4 * This library 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.
9 * This library 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 GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 #include "wine/vulkan_driver.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 static const struct wined3d_state_entry_template misc_state_template_vk[] =
29 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), state_nop}},
30 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL), state_nop}},
31 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
32 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
33 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
34 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
35 {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, {STATE_GRAPHICS_SHADER_RESOURCE_BINDING, state_nop}},
36 {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
37 {STATE_COMPUTE_SHADER_RESOURCE_BINDING, {STATE_COMPUTE_SHADER_RESOURCE_BINDING, state_nop}},
38 {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING, state_nop}},
39 {STATE_STREAM_OUTPUT, {STATE_STREAM_OUTPUT, state_nop}},
40 {STATE_BLEND, {STATE_BLEND, state_nop}},
41 {STATE_BLEND_FACTOR, {STATE_BLEND_FACTOR, state_nop}},
42 {STATE_SAMPLE_MASK, {STATE_SAMPLE_MASK, state_nop}},
43 {STATE_STREAMSRC, {STATE_STREAMSRC, state_nop}},
44 {STATE_VDECL, {STATE_VDECL, state_nop}},
45 {STATE_DEPTH_STENCIL, {STATE_DEPTH_STENCIL, state_nop}},
46 {STATE_RASTERIZER, {STATE_RASTERIZER, state_nop}},
47 {STATE_SCISSORRECT, {STATE_SCISSORRECT, state_nop}},
48 {STATE_POINTSPRITECOORDORIGIN, {STATE_POINTSPRITECOORDORIGIN, state_nop}},
50 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
51 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
52 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
53 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
54 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
55 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
56 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
57 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
58 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
59 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
60 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
61 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
62 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
63 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
64 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
65 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
66 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
67 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
68 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
69 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
70 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
71 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
72 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
73 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
74 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
75 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
76 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
77 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
78 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
79 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
80 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
81 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
82 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
83 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE)}},
84 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
85 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE)}},
86 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
87 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE)}},
88 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
89 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE)}},
90 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
91 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE)}},
92 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
93 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE)}},
94 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
95 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE)}},
96 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
97 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE)}},
99 {STATE_VIEWPORT, {STATE_VIEWPORT, state_nop}},
100 {STATE_INDEXBUFFER, {STATE_INDEXBUFFER, state_nop}},
101 {STATE_RENDER(WINED3D_RS_ANTIALIAS), {STATE_RENDER(WINED3D_RS_ANTIALIAS), state_nop}},
102 {STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE), {STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE), state_nop}},
103 {STATE_RENDER(WINED3D_RS_WRAPU), {STATE_RENDER(WINED3D_RS_WRAPU), state_nop}},
104 {STATE_RENDER(WINED3D_RS_WRAPV), {STATE_RENDER(WINED3D_RS_WRAPV), state_nop}},
105 {STATE_RENDER(WINED3D_RS_LINEPATTERN), {STATE_RENDER(WINED3D_RS_LINEPATTERN), state_nop}},
106 {STATE_RENDER(WINED3D_RS_MONOENABLE), {STATE_RENDER(WINED3D_RS_MONOENABLE), state_nop}},
107 {STATE_RENDER(WINED3D_RS_ROP2), {STATE_RENDER(WINED3D_RS_ROP2), state_nop}},
108 {STATE_RENDER(WINED3D_RS_PLANEMASK), {STATE_RENDER(WINED3D_RS_PLANEMASK), state_nop}},
109 {STATE_RENDER(WINED3D_RS_LASTPIXEL), {STATE_RENDER(WINED3D_RS_LASTPIXEL), state_nop}},
110 {STATE_RENDER(WINED3D_RS_ZFUNC), {STATE_RENDER(WINED3D_RS_ZFUNC), state_nop}},
111 {STATE_RENDER(WINED3D_RS_DITHERENABLE), {STATE_RENDER(WINED3D_RS_DITHERENABLE), state_nop}},
112 {STATE_RENDER(WINED3D_RS_SUBPIXEL), {STATE_RENDER(WINED3D_RS_SUBPIXEL), state_nop}},
113 {STATE_RENDER(WINED3D_RS_SUBPIXELX), {STATE_RENDER(WINED3D_RS_SUBPIXELX), state_nop}},
114 {STATE_RENDER(WINED3D_RS_STIPPLEDALPHA), {STATE_RENDER(WINED3D_RS_STIPPLEDALPHA), state_nop}},
115 {STATE_RENDER(WINED3D_RS_STIPPLEENABLE), {STATE_RENDER(WINED3D_RS_STIPPLEENABLE), state_nop}},
116 {STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS), {STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS), state_nop}},
117 {STATE_RENDER(WINED3D_RS_ANISOTROPY), {STATE_RENDER(WINED3D_RS_ANISOTROPY), state_nop}},
118 {STATE_RENDER(WINED3D_RS_FLUSHBATCH), {STATE_RENDER(WINED3D_RS_FLUSHBATCH), state_nop}},
119 {STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT), {STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT), state_nop}},
120 {STATE_RENDER(WINED3D_RS_STENCILFAIL), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
121 {STATE_RENDER(WINED3D_RS_STENCILZFAIL), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
122 {STATE_RENDER(WINED3D_RS_STENCILREF), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
123 {STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
124 {STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
125 {STATE_RENDER(WINED3D_RS_BACK_STENCILZFAIL), {STATE_RENDER(WINED3D_RS_ZFUNC)}},
126 {STATE_RENDER(WINED3D_RS_WRAP0), {STATE_RENDER(WINED3D_RS_WRAP0), state_nop}},
127 {STATE_RENDER(WINED3D_RS_WRAP1), {STATE_RENDER(WINED3D_RS_WRAP0)}},
128 {STATE_RENDER(WINED3D_RS_WRAP2), {STATE_RENDER(WINED3D_RS_WRAP0)}},
129 {STATE_RENDER(WINED3D_RS_WRAP3), {STATE_RENDER(WINED3D_RS_WRAP0)}},
130 {STATE_RENDER(WINED3D_RS_WRAP4), {STATE_RENDER(WINED3D_RS_WRAP0)}},
131 {STATE_RENDER(WINED3D_RS_WRAP5), {STATE_RENDER(WINED3D_RS_WRAP0)}},
132 {STATE_RENDER(WINED3D_RS_WRAP6), {STATE_RENDER(WINED3D_RS_WRAP0)}},
133 {STATE_RENDER(WINED3D_RS_WRAP7), {STATE_RENDER(WINED3D_RS_WRAP0)}},
134 {STATE_RENDER(WINED3D_RS_WRAP8), {STATE_RENDER(WINED3D_RS_WRAP0)}},
135 {STATE_RENDER(WINED3D_RS_WRAP9), {STATE_RENDER(WINED3D_RS_WRAP0)}},
136 {STATE_RENDER(WINED3D_RS_WRAP10), {STATE_RENDER(WINED3D_RS_WRAP0)}},
137 {STATE_RENDER(WINED3D_RS_WRAP11), {STATE_RENDER(WINED3D_RS_WRAP0)}},
138 {STATE_RENDER(WINED3D_RS_WRAP12), {STATE_RENDER(WINED3D_RS_WRAP0)}},
139 {STATE_RENDER(WINED3D_RS_WRAP13), {STATE_RENDER(WINED3D_RS_WRAP0)}},
140 {STATE_RENDER(WINED3D_RS_WRAP14), {STATE_RENDER(WINED3D_RS_WRAP0)}},
141 {STATE_RENDER(WINED3D_RS_WRAP15), {STATE_RENDER(WINED3D_RS_WRAP0)}},
142 {STATE_RENDER(WINED3D_RS_EXTENTS), {STATE_RENDER(WINED3D_RS_EXTENTS), state_nop}},
143 {STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE), {STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE), state_nop}},
144 {STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING), {STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING), state_nop}},
145 {STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE), {STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE), state_nop}},
146 {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), state_nop}},
147 {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), state_nop}},
148 {STATE_RENDER(WINED3D_RS_NORMALDEGREE), {STATE_RENDER(WINED3D_RS_NORMALDEGREE), state_nop}},
149 {STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
150 {STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
151 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
152 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
153 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
154 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
155 {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), state_nop}},
156 {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), state_nop}},
157 {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), state_nop}},
158 {STATE_RENDER(WINED3D_RS_ZVISIBLE), {STATE_RENDER(WINED3D_RS_ZVISIBLE), state_nop}},
159 /* Samplers */
160 {STATE_SAMPLER(0), {STATE_SAMPLER(0), state_nop}},
161 {STATE_SAMPLER(1), {STATE_SAMPLER(1), state_nop}},
162 {STATE_SAMPLER(2), {STATE_SAMPLER(2), state_nop}},
163 {STATE_SAMPLER(3), {STATE_SAMPLER(3), state_nop}},
164 {STATE_SAMPLER(4), {STATE_SAMPLER(4), state_nop}},
165 {STATE_SAMPLER(5), {STATE_SAMPLER(5), state_nop}},
166 {STATE_SAMPLER(6), {STATE_SAMPLER(6), state_nop}},
167 {STATE_SAMPLER(7), {STATE_SAMPLER(7), state_nop}},
168 {STATE_SAMPLER(8), {STATE_SAMPLER(8), state_nop}},
169 {STATE_SAMPLER(9), {STATE_SAMPLER(9), state_nop}},
170 {STATE_SAMPLER(10), {STATE_SAMPLER(10), state_nop}},
171 {STATE_SAMPLER(11), {STATE_SAMPLER(11), state_nop}},
172 {STATE_SAMPLER(12), {STATE_SAMPLER(12), state_nop}},
173 {STATE_SAMPLER(13), {STATE_SAMPLER(13), state_nop}},
174 {STATE_SAMPLER(14), {STATE_SAMPLER(14), state_nop}},
175 {STATE_SAMPLER(15), {STATE_SAMPLER(15), state_nop}},
176 {STATE_SAMPLER(16), /* Vertex sampler 0 */ {STATE_SAMPLER(16), state_nop}},
177 {STATE_SAMPLER(17), /* Vertex sampler 1 */ {STATE_SAMPLER(17), state_nop}},
178 {STATE_SAMPLER(18), /* Vertex sampler 2 */ {STATE_SAMPLER(18), state_nop}},
179 {STATE_SAMPLER(19), /* Vertex sampler 3 */ {STATE_SAMPLER(19), state_nop}},
180 {STATE_BASEVERTEXINDEX, {STATE_STREAMSRC}},
181 {STATE_FRAMEBUFFER, {STATE_FRAMEBUFFER, state_nop}},
182 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
183 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), state_nop}},
184 {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
185 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
186 {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
187 {0}, /* Terminate */
190 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
192 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
195 static const char *debug_vk_version(uint32_t version)
197 return wine_dbg_sprintf("%u.%u.%u",
198 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
201 static HRESULT hresult_from_vk_result(VkResult vr)
203 switch (vr)
205 case VK_SUCCESS:
206 return S_OK;
207 case VK_ERROR_OUT_OF_HOST_MEMORY:
208 WARN("Out of host memory.\n");
209 return E_OUTOFMEMORY;
210 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
211 WARN("Out of device memory.\n");
212 return E_OUTOFMEMORY;
213 case VK_ERROR_DEVICE_LOST:
214 WARN("Device lost.\n");
215 return E_FAIL;
216 case VK_ERROR_EXTENSION_NOT_PRESENT:
217 WARN("Extension not present.\n");
218 return E_FAIL;
219 default:
220 FIXME("Unhandled VkResult %d.\n", vr);
221 return E_FAIL;
225 #ifdef USE_WIN32_VULKAN
226 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
228 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
230 if (!(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
232 WARN("Failed to load vulkan-1.dll.\n");
233 return FALSE;
236 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
237 if (!vk_ops->vkGetInstanceProcAddr)
239 FreeLibrary(vk_info->vulkan_lib);
240 return FALSE;
243 return TRUE;
246 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
248 if (vk_info->vulkan_lib)
250 FreeLibrary(vk_info->vulkan_lib);
251 vk_info->vulkan_lib = NULL;
254 #else
255 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
257 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
258 const struct vulkan_funcs *vk_funcs;
259 HDC dc;
261 dc = GetDC(0);
262 vk_funcs = __wine_get_vulkan_driver(dc, WINE_VULKAN_DRIVER_VERSION);
263 ReleaseDC(0, dc);
265 if (!vk_funcs)
266 return FALSE;
268 vk_ops->vkGetInstanceProcAddr = (void *)vk_funcs->p_vkGetInstanceProcAddr;
269 return TRUE;
272 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info) {}
273 #endif
275 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
277 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
278 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
280 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
281 wined3d_unload_vulkan(vk_info);
282 wined3d_adapter_cleanup(&adapter_vk->a);
283 heap_free(adapter_vk);
286 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
287 uint32_t *queue_family_index, uint32_t *timestamp_bits)
289 VkPhysicalDevice physical_device = adapter_vk->physical_device;
290 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
291 VkQueueFamilyProperties *queue_properties;
292 uint32_t count, i;
294 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
296 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
297 return E_OUTOFMEMORY;
299 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
301 for (i = 0; i < count; ++i)
303 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
305 *queue_family_index = i;
306 *timestamp_bits = queue_properties[i].timestampValidBits;
307 heap_free(queue_properties);
308 return WINED3D_OK;
311 heap_free(queue_properties);
313 WARN("Failed to find graphics queue.\n");
314 return E_FAIL;
317 struct wined3d_physical_device_info
319 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
321 VkPhysicalDeviceFeatures2 features2;
324 static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info)
326 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features;
327 VkPhysicalDeviceFeatures *features = &info->features2.features;
329 vertex_divisor_features->vertexAttributeInstanceRateZeroDivisor = VK_FALSE;
331 features->depthBounds = VK_FALSE;
332 features->alphaToOne = VK_FALSE;
333 features->textureCompressionETC2 = VK_FALSE;
334 features->textureCompressionASTC_LDR = VK_FALSE;
335 features->shaderStorageImageMultisample = VK_FALSE;
336 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
337 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
338 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
339 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
340 features->shaderInt16 = VK_FALSE;
341 features->shaderResourceResidency = VK_FALSE;
342 features->shaderResourceMinLod = VK_FALSE;
343 features->sparseBinding = VK_FALSE;
344 features->sparseResidencyBuffer = VK_FALSE;
345 features->sparseResidencyImage2D = VK_FALSE;
346 features->sparseResidencyImage3D = VK_FALSE;
347 features->sparseResidency2Samples = VK_FALSE;
348 features->sparseResidency4Samples = VK_FALSE;
349 features->sparseResidency8Samples = VK_FALSE;
350 features->sparseResidency16Samples = VK_FALSE;
351 features->sparseResidencyAliased = VK_FALSE;
352 features->inheritedQueries = VK_FALSE;
355 static struct wined3d_allocator_chunk *wined3d_allocator_vk_create_chunk(struct wined3d_allocator *allocator,
356 struct wined3d_context *context, unsigned int memory_type, size_t chunk_size)
358 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
359 struct wined3d_allocator_chunk_vk *chunk_vk;
361 if (!(chunk_vk = heap_alloc(sizeof(*chunk_vk))))
362 return NULL;
364 if (!wined3d_allocator_chunk_init(&chunk_vk->c, allocator))
366 heap_free(chunk_vk);
367 return NULL;
370 if (!(chunk_vk->vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, chunk_size)))
372 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
373 heap_free(chunk_vk);
374 return NULL;
376 list_add_head(&allocator->pools[memory_type].chunks, &chunk_vk->c.entry);
378 return &chunk_vk->c;
381 static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *chunk)
383 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(chunk);
384 const struct wined3d_vk_info *vk_info;
385 struct wined3d_device_vk *device_vk;
387 TRACE("chunk %p.\n", chunk);
389 device_vk = CONTAINING_RECORD(chunk_vk->c.allocator, struct wined3d_device_vk, allocator);
390 vk_info = &device_vk->vk_info;
392 if (chunk_vk->c.map_ptr)
393 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
394 VK_CALL(vkFreeMemory(device_vk->vk_device, chunk_vk->vk_memory, NULL));
395 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk->vk_memory));
396 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
397 heap_free(chunk_vk);
400 static const struct wined3d_allocator_ops wined3d_allocator_vk_ops =
402 .allocator_create_chunk = wined3d_allocator_vk_create_chunk,
403 .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk,
406 static const struct
408 const char *name;
409 unsigned int core_since_version;
411 vulkan_device_extensions[] =
413 {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
414 {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
415 {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
416 {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
419 static bool enable_vulkan_device_extensions(VkPhysicalDevice physical_device, uint32_t *extension_count,
420 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
422 VkExtensionProperties *extensions = NULL;
423 bool success = false, found;
424 unsigned int i, j, count;
425 VkResult vr;
427 *extension_count = 0;
429 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
431 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
432 goto done;
434 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
436 WARN("Out of memory.\n");
437 goto done;
439 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
441 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
442 goto done;
445 for (i = 0; i < ARRAY_SIZE(vulkan_device_extensions); ++i)
447 if (vulkan_device_extensions[i].core_since_version <= vk_info->api_version)
448 continue;
450 for (j = 0, found = false; j < count; ++j)
452 if (!strcmp(extensions[j].extensionName, vulkan_device_extensions[i].name))
454 found = true;
455 break;
459 if (!found)
461 WARN("Required extension '%s' is not available.\n", vulkan_device_extensions[i].name);
462 goto done;
465 TRACE("Enabling instance extension '%s'.\n", vulkan_device_extensions[i].name);
466 enabled_extensions[(*extension_count)++] = vulkan_device_extensions[i].name;
468 success = true;
470 done:
471 heap_free(extensions);
472 return success;
475 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
476 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
477 const enum wined3d_feature_level *levels, unsigned int level_count,
478 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
480 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
481 const char *enabled_device_extensions[ARRAY_SIZE(vulkan_device_extensions)];
482 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
483 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
484 struct wined3d_physical_device_info physical_device_info;
485 static const float priorities[] = {1.0f};
486 VkPhysicalDeviceFeatures2 *features2;
487 struct wined3d_device_vk *device_vk;
488 VkDevice vk_device = VK_NULL_HANDLE;
489 VkDeviceQueueCreateInfo queue_info;
490 VkPhysicalDevice physical_device;
491 VkDeviceCreateInfo device_info;
492 uint32_t queue_family_index;
493 uint32_t timestamp_bits;
494 VkResult vr;
495 HRESULT hr;
497 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
498 return E_OUTOFMEMORY;
500 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, &timestamp_bits)))
501 goto fail;
503 physical_device = adapter_vk->physical_device;
505 memset(&physical_device_info, 0, sizeof(physical_device_info));
507 vertex_divisor_features = &physical_device_info.vertex_divisor_features;
508 vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
510 features2 = &physical_device_info.features2;
511 features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
512 features2->pNext = vertex_divisor_features;
514 if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2)
515 VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2));
516 else
517 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features));
519 if (!vertex_divisor_features->vertexAttributeInstanceRateDivisor)
521 WARN("Vertex attribute divisors not supported.\n");
522 hr = E_FAIL;
523 goto fail;
526 wined3d_disable_vulkan_features(&physical_device_info);
528 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
529 queue_info.pNext = NULL;
530 queue_info.flags = 0;
531 queue_info.queueFamilyIndex = queue_family_index;
532 queue_info.queueCount = ARRAY_SIZE(priorities);
533 queue_info.pQueuePriorities = priorities;
535 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
536 device_info.pNext = features2->pNext;
537 device_info.flags = 0;
538 device_info.queueCreateInfoCount = 1;
539 device_info.pQueueCreateInfos = &queue_info;
540 device_info.enabledLayerCount = 0;
541 device_info.ppEnabledLayerNames = NULL;
542 device_info.ppEnabledExtensionNames = enabled_device_extensions;
543 if (!enable_vulkan_device_extensions(physical_device,
544 &device_info.enabledExtensionCount, enabled_device_extensions, vk_info))
546 hr = E_FAIL;
547 goto fail;
549 device_info.pEnabledFeatures = &features2->features;
551 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
553 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr));
554 vk_device = VK_NULL_HANDLE;
555 hr = hresult_from_vk_result(vr);
556 goto fail;
559 device_vk->vk_device = vk_device;
560 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
561 device_vk->vk_queue_family_index = queue_family_index;
562 device_vk->timestamp_bits = timestamp_bits;
564 device_vk->vk_info = *vk_info;
565 #define LOAD_DEVICE_PFN(name) \
566 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
568 WARN("Could not get device proc addr for '" #name "'.\n"); \
569 hr = E_FAIL; \
570 goto fail; \
572 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
573 VK_DEVICE_FUNCS()
574 #undef VK_DEVICE_PFN
576 if (!wined3d_allocator_init(&device_vk->allocator,
577 adapter_vk->memory_properties.memoryTypeCount, &wined3d_allocator_vk_ops))
579 WARN("Failed to initialise allocator.\n");
580 hr = E_FAIL;
581 goto fail;
584 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, focus_window,
585 flags, surface_alignment, levels, level_count, vk_info->supported, device_parent)))
587 WARN("Failed to initialize device, hr %#x.\n", hr);
588 wined3d_allocator_cleanup(&device_vk->allocator);
589 goto fail;
592 *device = &device_vk->d;
594 return WINED3D_OK;
596 fail:
597 VK_CALL(vkDestroyDevice(vk_device, NULL));
598 heap_free(device_vk);
599 return hr;
602 static void adapter_vk_destroy_device(struct wined3d_device *device)
604 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
605 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
607 wined3d_device_cleanup(&device_vk->d);
608 wined3d_allocator_cleanup(&device_vk->allocator);
609 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
610 heap_free(device_vk);
613 struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
614 struct wined3d_texture *texture, unsigned int sub_resource_idx)
616 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
618 wined3d_from_cs(device->cs);
620 if (!device->context_count)
621 return NULL;
623 return &wined3d_device_vk(device)->context_vk.c;
626 void adapter_vk_release_context(struct wined3d_context *context)
628 TRACE("context %p.\n", context);
631 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
633 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
634 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
635 BOOL sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
637 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_BACKBUFFER
638 | WINEDDSCAPS_COMPLEX
639 | WINEDDSCAPS_FRONTBUFFER
640 | WINEDDSCAPS_3DDEVICE
641 | WINEDDSCAPS_VIDEOMEMORY
642 | WINEDDSCAPS_OWNDC
643 | WINEDDSCAPS_LOCALVIDMEM
644 | WINEDDSCAPS_NONLOCALVIDMEM;
645 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
647 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
649 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
650 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
651 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
652 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
653 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
655 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
657 if (sampler_anisotropy)
659 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
661 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
662 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
664 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
667 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
668 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
669 | WINED3DPBLENDCAPS_SRCALPHASAT;
671 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
672 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
673 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
674 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
675 | WINED3DPTFILTERCAPS_MAGFPOINT
676 | WINED3DPTFILTERCAPS_MINFLINEAR
677 | WINED3DPTFILTERCAPS_MINFPOINT
678 | WINED3DPTFILTERCAPS_MIPFLINEAR
679 | WINED3DPTFILTERCAPS_MIPFPOINT
680 | WINED3DPTFILTERCAPS_LINEAR
681 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
682 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
683 | WINED3DPTFILTERCAPS_MIPLINEAR
684 | WINED3DPTFILTERCAPS_MIPNEAREST
685 | WINED3DPTFILTERCAPS_NEAREST;
686 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
687 | WINED3DPTADDRESSCAPS_CLAMP
688 | WINED3DPTADDRESSCAPS_WRAP;
689 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
690 | WINED3DPTADDRESSCAPS_MIRROR
691 | WINED3DPTADDRESSCAPS_MIRRORONCE;
693 caps->MaxVolumeExtent = limits->maxImageDimension3D;
695 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
696 | WINED3DPTEXTURECAPS_MIPCUBEMAP
697 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
698 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
699 | WINED3DPTFILTERCAPS_MAGFPOINT
700 | WINED3DPTFILTERCAPS_MINFLINEAR
701 | WINED3DPTFILTERCAPS_MINFPOINT
702 | WINED3DPTFILTERCAPS_MIPFLINEAR
703 | WINED3DPTFILTERCAPS_MIPFPOINT
704 | WINED3DPTFILTERCAPS_LINEAR
705 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
706 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
707 | WINED3DPTFILTERCAPS_MIPLINEAR
708 | WINED3DPTFILTERCAPS_MIPNEAREST
709 | WINED3DPTFILTERCAPS_NEAREST;
711 if (sampler_anisotropy)
713 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
714 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
717 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
718 | WINED3DPTADDRESSCAPS_MIRROR
719 | WINED3DPTADDRESSCAPS_MIRRORONCE;
721 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
722 | WINED3DSTENCILCAPS_INCR
723 | WINED3DSTENCILCAPS_TWOSIDED;
725 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
727 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
728 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
729 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
730 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
733 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
734 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
735 const struct wined3d_format *ds_format)
737 return TRUE;
740 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
742 struct wined3d_context_vk *context_vk;
743 struct wined3d_device_vk *device_vk;
744 HRESULT hr;
746 TRACE("device %p.\n", device);
748 device_vk = wined3d_device_vk(device);
749 context_vk = &device_vk->context_vk;
750 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
752 WARN("Failed to initialise context.\n");
753 return hr;
756 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
757 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
759 ERR("Failed to allocate shader private data, hr %#x.\n", hr);
760 wined3d_context_vk_cleanup(context_vk);
761 return hr;
764 if (!device_context_add(device, &context_vk->c))
766 ERR("Failed to add the newly created context to the context list.\n");
767 device->shader_backend->shader_free_private(device, NULL);
768 wined3d_context_vk_cleanup(context_vk);
769 return E_FAIL;
772 TRACE("Initialised context %p.\n", context_vk);
774 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
776 ERR("Failed to create CPU blitter.\n");
777 device_context_remove(device, &context_vk->c);
778 device->shader_backend->shader_free_private(device, NULL);
779 wined3d_context_vk_cleanup(context_vk);
780 return E_FAIL;
782 wined3d_vk_blitter_create(&device_vk->d.blitter);
784 wined3d_device_create_default_samplers(device, &context_vk->c);
785 wined3d_device_vk_create_null_resources(device_vk, context_vk);
786 wined3d_device_vk_create_null_views(device_vk, context_vk);
788 return WINED3D_OK;
791 static void adapter_vk_uninit_3d_cs(void *object)
793 struct wined3d_device_vk *device_vk = object;
794 struct wined3d_context_vk *context_vk;
795 struct wined3d_device *device;
796 struct wined3d_shader *shader;
798 TRACE("device_vk %p.\n", device_vk);
800 context_vk = &device_vk->context_vk;
801 device = &device_vk->d;
803 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
805 device->shader_backend->shader_destroy(shader);
808 device->blitter->ops->blitter_destroy(device->blitter, NULL);
809 device->shader_backend->shader_free_private(device, &context_vk->c);
810 wined3d_device_vk_destroy_null_views(device_vk, context_vk);
811 wined3d_device_vk_destroy_null_resources(device_vk, context_vk);
812 wined3d_device_destroy_default_samplers(device, &context_vk->c);
815 static void adapter_vk_uninit_3d(struct wined3d_device *device)
817 struct wined3d_context_vk *context_vk;
818 struct wined3d_device_vk *device_vk;
820 TRACE("device %p.\n", device);
822 device_vk = wined3d_device_vk(device);
823 context_vk = &device_vk->context_vk;
825 wined3d_cs_destroy_object(device->cs, adapter_vk_uninit_3d_cs, device_vk);
826 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
828 device_context_remove(device, &context_vk->c);
829 wined3d_context_vk_cleanup(context_vk);
832 static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
834 const struct wined3d_vk_info *vk_info;
835 struct wined3d_device_vk *device_vk;
836 struct wined3d_bo_slab_vk *slab;
837 void *map_ptr;
838 VkResult vr;
840 if (bo->map_ptr)
841 return bo->map_ptr;
843 vk_info = context_vk->vk_info;
844 device_vk = wined3d_device_vk(context_vk->c.device);
846 if ((slab = bo->slab))
848 if (!(map_ptr = slab->map_ptr) && !(map_ptr = wined3d_bo_vk_map(&slab->bo, context_vk)))
850 ERR("Failed to map slab.\n");
851 return NULL;
853 ++slab->map_count;
855 else if (bo->memory)
857 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(bo->memory->chunk);
859 if (!(map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk)))
861 ERR("Failed to map chunk.\n");
862 return NULL;
865 else if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0)
867 ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr));
868 return NULL;
871 if (sizeof(map_ptr) >= sizeof(uint64_t))
872 bo->map_ptr = map_ptr;
874 return map_ptr;
877 static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
879 const struct wined3d_vk_info *vk_info;
880 struct wined3d_device_vk *device_vk;
881 struct wined3d_bo_slab_vk *slab;
883 if (bo->map_ptr)
884 return;
886 if ((slab = bo->slab))
888 if (--slab->map_count)
889 return;
891 wined3d_bo_vk_unmap(&slab->bo, context_vk);
892 slab->map_ptr = NULL;
893 return;
896 vk_info = context_vk->vk_info;
897 device_vk = wined3d_device_vk(context_vk->c.device);
899 if (bo->memory)
900 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
901 else
902 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
905 static VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
907 VkAccessFlags flags = 0;
909 if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
910 flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
911 if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
912 flags |= VK_ACCESS_INDEX_READ_BIT;
913 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
914 flags |= VK_ACCESS_UNIFORM_READ_BIT;
915 if (usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
916 flags |= VK_ACCESS_SHADER_READ_BIT;
917 if (usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
918 flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
919 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
920 flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
922 return flags;
925 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
926 const struct wined3d_bo_address *data, size_t size, uint32_t map_flags)
928 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
929 const struct wined3d_vk_info *vk_info;
930 struct wined3d_bo_user_vk *bo_user_vk;
931 struct wined3d_device_vk *device_vk;
932 VkCommandBuffer vk_command_buffer;
933 VkBufferMemoryBarrier vk_barrier;
934 struct wined3d_bo_vk *bo, tmp;
935 VkMappedMemoryRange range;
936 void *map_ptr;
938 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
939 return data->addr;
941 vk_info = context_vk->vk_info;
942 device_vk = wined3d_device_vk(context->device);
944 if (map_flags & WINED3D_MAP_NOOVERWRITE)
945 goto map;
947 if ((map_flags & WINED3D_MAP_DISCARD) && bo->command_buffer_id > context_vk->completed_command_buffer_id)
949 if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp))
951 list_move_head(&tmp.users, &bo->users);
952 wined3d_context_vk_destroy_bo(context_vk, bo);
953 *bo = tmp;
954 list_init(&bo->users);
955 list_move_head(&bo->users, &tmp.users);
956 LIST_FOR_EACH_ENTRY(bo_user_vk, &bo->users, struct wined3d_bo_user_vk, entry)
958 bo_user_vk->valid = false;
961 goto map;
964 ERR("Failed to create new buffer object.\n");
967 if (map_flags & WINED3D_MAP_READ)
969 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
971 ERR("Failed to get command buffer.\n");
972 return NULL;
975 wined3d_context_vk_end_current_render_pass(context_vk);
977 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
978 vk_barrier.pNext = NULL;
979 vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage);
980 vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
981 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
982 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
983 vk_barrier.buffer = bo->vk_buffer;
984 vk_barrier.offset = bo->buffer_offset + (uintptr_t)data->addr;
985 vk_barrier.size = size;
986 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
987 VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
989 if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
991 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
992 range.pNext = NULL;
993 range.memory = bo->vk_memory;
994 range.offset = bo->memory_offset + (uintptr_t)data->addr;
995 range.size = size;
996 VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range));
999 wined3d_context_vk_reference_bo(context_vk, bo);
1002 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
1003 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1004 wined3d_context_vk_wait_command_buffer(context_vk, bo->command_buffer_id);
1006 map:
1007 if (!(map_ptr = wined3d_bo_vk_map(bo, context_vk)))
1009 ERR("Failed to map bo.\n");
1010 return NULL;
1013 return (uint8_t *)map_ptr + bo->memory_offset + (uintptr_t)data->addr;
1016 static void adapter_vk_unmap_bo_address(struct wined3d_context *context,
1017 const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges)
1019 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1020 const struct wined3d_vk_info *vk_info;
1021 struct wined3d_device_vk *device_vk;
1022 VkMappedMemoryRange range;
1023 struct wined3d_bo_vk *bo;
1024 unsigned int i;
1026 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
1027 return;
1029 vk_info = context_vk->vk_info;
1030 device_vk = wined3d_device_vk(context->device);
1032 if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
1034 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1035 range.pNext = NULL;
1036 range.memory = bo->vk_memory;
1038 for (i = 0; i < range_count; ++i)
1040 range.offset = bo->memory_offset + ranges[i].offset;
1041 range.size = ranges[i].size;
1042 VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range));
1046 wined3d_bo_vk_unmap(bo, context_vk);
1049 static void adapter_vk_copy_bo_address(struct wined3d_context *context,
1050 const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size)
1052 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1053 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1054 struct wined3d_bo_vk staging_bo, *src_bo, *dst_bo;
1055 VkAccessFlags src_access_mask, dst_access_mask;
1056 VkBufferMemoryBarrier vk_barrier[2];
1057 struct wined3d_bo_address staging;
1058 VkCommandBuffer vk_command_buffer;
1059 struct wined3d_range range;
1060 void *dst_ptr, *src_ptr;
1061 VkBufferCopy region;
1063 src_bo = (struct wined3d_bo_vk *)src->buffer_object;
1064 dst_bo = (struct wined3d_bo_vk *)dst->buffer_object;
1066 if (src_bo && dst_bo)
1068 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1070 ERR("Failed to get command buffer.\n");
1071 return;
1074 wined3d_context_vk_end_current_render_pass(context_vk);
1076 src_access_mask = vk_access_mask_from_buffer_usage(src_bo->usage);
1077 dst_access_mask = vk_access_mask_from_buffer_usage(dst_bo->usage);
1079 region.srcOffset = src_bo->buffer_offset + (uintptr_t)src->addr;
1080 region.dstOffset = dst_bo->buffer_offset + (uintptr_t)dst->addr;
1081 region.size = size;
1083 vk_barrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1084 vk_barrier[0].pNext = NULL;
1085 vk_barrier[0].srcAccessMask = src_access_mask;
1086 vk_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1087 vk_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1088 vk_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1089 vk_barrier[0].buffer = src_bo->vk_buffer;
1090 vk_barrier[0].offset = region.srcOffset;
1091 vk_barrier[0].size = region.size;
1093 vk_barrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1094 vk_barrier[1].pNext = NULL;
1095 vk_barrier[1].srcAccessMask = dst_access_mask;
1096 vk_barrier[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1097 vk_barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1098 vk_barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1099 vk_barrier[1].buffer = dst_bo->vk_buffer;
1100 vk_barrier[1].offset = region.dstOffset;
1101 vk_barrier[1].size = region.size;
1103 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1104 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1106 VK_CALL(vkCmdCopyBuffer(vk_command_buffer, src_bo->vk_buffer, dst_bo->vk_buffer, 1, &region));
1108 vk_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1109 vk_barrier[0].dstAccessMask = src_access_mask;
1111 vk_barrier[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1112 vk_barrier[1].dstAccessMask = dst_access_mask;
1114 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1115 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1117 wined3d_context_vk_reference_bo(context_vk, src_bo);
1118 wined3d_context_vk_reference_bo(context_vk, dst_bo);
1120 return;
1123 if (src_bo && !(src_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
1125 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1126 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1128 ERR("Failed to create staging bo.\n");
1129 return;
1132 staging.buffer_object = (uintptr_t)&staging_bo;
1133 staging.addr = NULL;
1134 adapter_vk_copy_bo_address(context, &staging, src, size);
1135 adapter_vk_copy_bo_address(context, dst, &staging, size);
1137 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1139 return;
1142 if (dst_bo && (dst_bo->command_buffer_id > context_vk->completed_command_buffer_id
1143 || !(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)))
1145 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1146 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1148 ERR("Failed to create staging bo.\n");
1149 return;
1152 staging.buffer_object = (uintptr_t)&staging_bo;
1153 staging.addr = NULL;
1154 adapter_vk_copy_bo_address(context, &staging, src, size);
1155 adapter_vk_copy_bo_address(context, dst, &staging, size);
1157 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1159 return;
1162 src_ptr = adapter_vk_map_bo_address(context, src, size, WINED3D_MAP_READ);
1163 dst_ptr = adapter_vk_map_bo_address(context, dst, size, WINED3D_MAP_WRITE);
1165 memcpy(dst_ptr, src_ptr, size);
1167 range.offset = 0;
1168 range.size = size;
1169 adapter_vk_unmap_bo_address(context, dst, 1, &range);
1170 adapter_vk_unmap_bo_address(context, src, 0, NULL);
1173 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
1174 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
1176 struct wined3d_swapchain_vk *swapchain_vk;
1177 HRESULT hr;
1179 TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
1180 device, desc, parent, parent_ops, swapchain);
1182 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
1183 return E_OUTOFMEMORY;
1185 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, parent, parent_ops)))
1187 WARN("Failed to initialise swapchain, hr %#x.\n", hr);
1188 heap_free(swapchain_vk);
1189 return hr;
1192 TRACE("Created swapchain %p.\n", swapchain_vk);
1193 *swapchain = &swapchain_vk->s;
1195 return hr;
1198 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
1200 struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
1202 wined3d_swapchain_vk_cleanup(swapchain_vk);
1203 heap_free(swapchain_vk);
1206 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
1207 uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
1209 const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
1210 unsigned int i;
1212 for (i = 0; i < memory_info->memoryTypeCount; ++i)
1214 if (!(memory_type_mask & (1u << i)))
1215 continue;
1216 if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
1217 return i;
1220 return ~0u;
1223 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
1224 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
1225 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
1227 struct wined3d_buffer_vk *buffer_vk;
1228 HRESULT hr;
1230 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1231 device, desc, data, parent, parent_ops, buffer);
1233 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
1234 return E_OUTOFMEMORY;
1236 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
1238 WARN("Failed to initialise buffer, hr %#x.\n", hr);
1239 heap_free(buffer_vk);
1240 return hr;
1243 TRACE("Created buffer %p.\n", buffer_vk);
1244 *buffer = &buffer_vk->b;
1246 return hr;
1249 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
1251 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
1252 struct wined3d_device *device = buffer_vk->b.resource.device;
1253 unsigned int swapchain_count = device->swapchain_count;
1255 TRACE("buffer_vk %p.\n", buffer_vk);
1257 /* Take a reference to the device, in case releasing the buffer would
1258 * cause the device to be destroyed. However, swapchain resources don't
1259 * take a reference to the device, and we wouldn't want to increment the
1260 * refcount on a device that's in the process of being destroyed. */
1261 if (swapchain_count)
1262 wined3d_device_incref(device);
1263 wined3d_buffer_cleanup(&buffer_vk->b);
1264 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
1265 if (swapchain_count)
1266 wined3d_device_decref(device);
1269 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
1270 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
1271 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
1273 struct wined3d_texture_vk *texture_vk;
1274 HRESULT hr;
1276 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
1277 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
1279 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
1280 return E_OUTOFMEMORY;
1282 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
1283 layer_count, level_count, flags, parent, parent_ops)))
1285 WARN("Failed to initialise texture, hr %#x.\n", hr);
1286 heap_free(texture_vk);
1287 return hr;
1290 TRACE("Created texture %p.\n", texture_vk);
1291 *texture = &texture_vk->t;
1293 return hr;
1296 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
1298 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
1299 struct wined3d_device *device = texture_vk->t.resource.device;
1300 unsigned int swapchain_count = device->swapchain_count;
1302 TRACE("texture_vk %p.\n", texture_vk);
1304 /* Take a reference to the device, in case releasing the texture would
1305 * cause the device to be destroyed. However, swapchain resources don't
1306 * take a reference to the device, and we wouldn't want to increment the
1307 * refcount on a device that's in the process of being destroyed. */
1308 if (swapchain_count)
1309 wined3d_device_incref(device);
1311 wined3d_texture_sub_resources_destroyed(texture);
1312 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
1314 wined3d_texture_cleanup(&texture_vk->t);
1315 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
1317 if (swapchain_count)
1318 wined3d_device_decref(device);
1321 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
1322 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1323 struct wined3d_rendertarget_view **view)
1325 struct wined3d_rendertarget_view_vk *view_vk;
1326 HRESULT hr;
1328 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1329 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1331 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1332 return E_OUTOFMEMORY;
1334 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1336 WARN("Failed to initialise view, hr %#x.\n", hr);
1337 heap_free(view_vk);
1338 return hr;
1341 TRACE("Created render target view %p.\n", view_vk);
1342 *view = &view_vk->v;
1344 return hr;
1347 struct wined3d_view_vk_destroy_ctx
1349 struct wined3d_device_vk *device_vk;
1350 VkBufferView *vk_buffer_view;
1351 VkImageView *vk_image_view;
1352 struct wined3d_bo_vk *vk_counter_bo;
1353 VkBufferView *vk_counter_view;
1354 uint64_t *command_buffer_id;
1355 void *object;
1356 struct wined3d_view_vk_destroy_ctx *free;
1359 static void wined3d_view_vk_destroy_object(void *object)
1361 struct wined3d_view_vk_destroy_ctx *ctx = object;
1362 const struct wined3d_vk_info *vk_info;
1363 struct wined3d_device_vk *device_vk;
1364 struct wined3d_context *context;
1366 device_vk = ctx->device_vk;
1367 vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
1368 context = context_acquire(&device_vk->d, NULL, 0);
1370 if (ctx->vk_buffer_view)
1372 if (context)
1374 wined3d_context_vk_destroy_buffer_view(wined3d_context_vk(context),
1375 *ctx->vk_buffer_view, *ctx->command_buffer_id);
1377 else
1379 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_buffer_view, NULL));
1380 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_buffer_view));
1383 if (ctx->vk_image_view)
1385 if (context)
1387 wined3d_context_vk_destroy_image_view(wined3d_context_vk(context),
1388 *ctx->vk_image_view, *ctx->command_buffer_id);
1390 else
1392 VK_CALL(vkDestroyImageView(device_vk->vk_device, *ctx->vk_image_view, NULL));
1393 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
1396 if (ctx->vk_counter_bo && ctx->vk_counter_bo->vk_buffer)
1397 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), ctx->vk_counter_bo);
1398 if (ctx->vk_counter_view)
1400 if (context)
1402 wined3d_context_vk_destroy_buffer_view(wined3d_context_vk(context),
1403 *ctx->vk_counter_view, *ctx->command_buffer_id);
1405 else
1407 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_counter_view, NULL));
1408 TRACE("Destroyed counter buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_counter_view));
1412 if (context)
1413 context_release(context);
1415 heap_free(ctx->object);
1416 heap_free(ctx->free);
1419 static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView *vk_buffer_view,
1420 VkImageView *vk_image_view, struct wined3d_bo_vk *vk_counter_bo,
1421 VkBufferView *vk_counter_view, uint64_t *command_buffer_id, void *view_vk)
1423 struct wined3d_view_vk_destroy_ctx *ctx, c;
1425 if (!(ctx = heap_alloc(sizeof(*ctx))))
1426 ctx = &c;
1427 ctx->device_vk = wined3d_device_vk(device);
1428 ctx->vk_buffer_view = vk_buffer_view;
1429 ctx->vk_image_view = vk_image_view;
1430 ctx->vk_counter_bo = vk_counter_bo;
1431 ctx->vk_counter_view = vk_counter_view;
1432 ctx->command_buffer_id = command_buffer_id;
1433 ctx->object = view_vk;
1434 ctx->free = ctx != &c ? ctx : NULL;
1436 wined3d_cs_destroy_object(device->cs, wined3d_view_vk_destroy_object, ctx);
1437 if (ctx == &c)
1438 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1441 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
1443 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
1444 struct wined3d_device *device = view_vk->v.resource->device;
1445 unsigned int swapchain_count = device->swapchain_count;
1447 TRACE("view_vk %p.\n", view_vk);
1449 /* Take a reference to the device, in case releasing the view's resource
1450 * would cause the device to be destroyed. However, swapchain resources
1451 * don't take a reference to the device, and we wouldn't want to increment
1452 * the refcount on a device that's in the process of being destroyed. */
1453 if (swapchain_count)
1454 wined3d_device_incref(device);
1455 wined3d_rendertarget_view_cleanup(&view_vk->v);
1456 wined3d_view_vk_destroy(device, NULL, &view_vk->vk_image_view,
1457 NULL, NULL, &view_vk->command_buffer_id, view_vk);
1458 if (swapchain_count)
1459 wined3d_device_decref(device);
1462 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
1463 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1464 struct wined3d_shader_resource_view **view)
1466 struct wined3d_shader_resource_view_vk *view_vk;
1467 HRESULT hr;
1469 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1470 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1472 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1473 return E_OUTOFMEMORY;
1475 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1477 WARN("Failed to initialise view, hr %#x.\n", hr);
1478 heap_free(view_vk);
1479 return hr;
1482 TRACE("Created shader resource view %p.\n", view_vk);
1483 *view = &view_vk->v;
1485 return hr;
1488 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
1490 struct wined3d_shader_resource_view_vk *srv_vk = wined3d_shader_resource_view_vk(view);
1491 struct wined3d_device *device = srv_vk->v.resource->device;
1492 unsigned int swapchain_count = device->swapchain_count;
1493 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1494 VkBufferView *vk_buffer_view = NULL;
1495 VkImageView *vk_image_view = NULL;
1497 TRACE("srv_vk %p.\n", srv_vk);
1499 /* Take a reference to the device, in case releasing the view's resource
1500 * would cause the device to be destroyed. However, swapchain resources
1501 * don't take a reference to the device, and we wouldn't want to increment
1502 * the refcount on a device that's in the process of being destroyed. */
1503 if (swapchain_count)
1504 wined3d_device_incref(device);
1505 if (srv_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
1506 vk_buffer_view = &view_vk->u.vk_buffer_view;
1507 else
1508 vk_image_view = &view_vk->u.vk_image_info.imageView;
1509 list_remove(&view_vk->bo_user.entry);
1510 wined3d_shader_resource_view_cleanup(&srv_vk->v);
1511 wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view,
1512 NULL, NULL, &view_vk->command_buffer_id, srv_vk);
1513 if (swapchain_count)
1514 wined3d_device_decref(device);
1517 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
1518 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1519 struct wined3d_unordered_access_view **view)
1521 struct wined3d_unordered_access_view_vk *view_vk;
1522 HRESULT hr;
1524 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1525 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1527 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1528 return E_OUTOFMEMORY;
1530 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1532 WARN("Failed to initialise view, hr %#x.\n", hr);
1533 heap_free(view_vk);
1534 return hr;
1537 TRACE("Created unordered access view %p.\n", view_vk);
1538 *view = &view_vk->v;
1540 return hr;
1543 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
1545 struct wined3d_unordered_access_view_vk *uav_vk = wined3d_unordered_access_view_vk(view);
1546 struct wined3d_device *device = uav_vk->v.resource->device;
1547 unsigned int swapchain_count = device->swapchain_count;
1548 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1549 VkBufferView *vk_buffer_view = NULL;
1550 VkImageView *vk_image_view = NULL;
1552 TRACE("uav_vk %p.\n", uav_vk);
1554 /* Take a reference to the device, in case releasing the view's resource
1555 * would cause the device to be destroyed. However, swapchain resources
1556 * don't take a reference to the device, and we wouldn't want to increment
1557 * the refcount on a device that's in the process of being destroyed. */
1558 if (swapchain_count)
1559 wined3d_device_incref(device);
1560 if (uav_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
1561 vk_buffer_view = &view_vk->u.vk_buffer_view;
1562 else
1563 vk_image_view = &view_vk->u.vk_image_info.imageView;
1564 list_remove(&view_vk->bo_user.entry);
1565 wined3d_unordered_access_view_cleanup(&uav_vk->v);
1566 wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view, &uav_vk->counter_bo,
1567 &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
1568 if (swapchain_count)
1569 wined3d_device_decref(device);
1572 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
1573 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
1575 struct wined3d_sampler_vk *sampler_vk;
1577 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
1578 device, desc, parent, parent_ops, sampler);
1580 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
1581 return E_OUTOFMEMORY;
1583 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
1585 TRACE("Created sampler %p.\n", sampler_vk);
1586 *sampler = &sampler_vk->s;
1588 return WINED3D_OK;
1591 static void wined3d_sampler_vk_destroy_object(void *object)
1593 struct wined3d_sampler_vk *sampler_vk = object;
1594 struct wined3d_context_vk *context_vk;
1596 context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
1598 wined3d_context_vk_destroy_sampler(context_vk, sampler_vk->vk_image_info.sampler, sampler_vk->command_buffer_id);
1599 heap_free(sampler_vk);
1601 context_release(&context_vk->c);
1604 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
1606 struct wined3d_sampler_vk *sampler_vk = wined3d_sampler_vk(sampler);
1608 TRACE("sampler_vk %p.\n", sampler_vk);
1610 wined3d_cs_destroy_object(sampler->device->cs, wined3d_sampler_vk_destroy_object, sampler_vk);
1613 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
1614 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1616 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1617 device, type, parent, parent_ops, query);
1619 return wined3d_query_vk_create(device, type, parent, parent_ops, query);
1622 static void wined3d_query_vk_destroy_object(void *object)
1624 struct wined3d_query_vk *query_vk = object;
1626 query_vk->q.query_ops->query_destroy(&query_vk->q);
1629 static void adapter_vk_destroy_query(struct wined3d_query *query)
1631 struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
1633 TRACE("query_vk %p.\n", query_vk);
1635 wined3d_cs_destroy_object(query->device->cs, wined3d_query_vk_destroy_object, query_vk);
1638 static void adapter_vk_flush_context(struct wined3d_context *context)
1640 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1642 TRACE("context_vk %p.\n", context_vk);
1644 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1647 static void adapter_vk_draw_primitive(struct wined3d_device *device,
1648 const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters)
1650 struct wined3d_buffer_vk *indirect_vk = NULL;
1651 const struct wined3d_vk_info *vk_info;
1652 struct wined3d_context_vk *context_vk;
1653 VkCommandBuffer vk_command_buffer;
1654 uint32_t instance_count;
1656 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1658 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1659 vk_info = context_vk->vk_info;
1661 if (parameters->indirect)
1662 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1664 if (!(vk_command_buffer = wined3d_context_vk_apply_draw_state(context_vk,
1665 state, indirect_vk, parameters->indexed)))
1667 ERR("Failed to apply draw state.\n");
1668 context_release(&context_vk->c);
1669 return;
1672 if (parameters->indirect)
1674 struct wined3d_bo_vk *bo = &indirect_vk->bo;
1675 uint32_t stride, size;
1677 wined3d_context_vk_reference_bo(context_vk, bo);
1678 size = indirect_vk->b.resource.size - parameters->u.indirect.offset;
1680 if (parameters->indexed)
1682 stride = sizeof(VkDrawIndexedIndirectCommand);
1683 VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer, bo->vk_buffer,
1684 bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride));
1686 else
1688 stride = sizeof(VkDrawIndirectCommand);
1689 VK_CALL(vkCmdDrawIndirect(vk_command_buffer, bo->vk_buffer,
1690 bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride));
1693 else
1695 instance_count = parameters->u.direct.instance_count;
1696 if (context_vk->c.instance_count)
1697 instance_count = context_vk->c.instance_count;
1698 if (!instance_count)
1699 instance_count = 1;
1701 if (parameters->indexed)
1702 VK_CALL(vkCmdDrawIndexed(vk_command_buffer, parameters->u.direct.index_count,
1703 instance_count, parameters->u.direct.start_idx, parameters->u.direct.base_vertex_idx,
1704 parameters->u.direct.start_instance));
1705 else
1706 VK_CALL(vkCmdDraw(vk_command_buffer, parameters->u.direct.index_count, instance_count,
1707 parameters->u.direct.start_idx, parameters->u.direct.start_instance));
1710 context_release(&context_vk->c);
1713 static void adapter_vk_dispatch_compute(struct wined3d_device *device,
1714 const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters)
1716 struct wined3d_buffer_vk *indirect_vk = NULL;
1717 const struct wined3d_vk_info *vk_info;
1718 struct wined3d_context_vk *context_vk;
1719 VkCommandBuffer vk_command_buffer;
1721 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1723 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1724 vk_info = context_vk->vk_info;
1726 if (parameters->indirect)
1727 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1729 if (!(vk_command_buffer = wined3d_context_vk_apply_compute_state(context_vk, state, indirect_vk)))
1731 ERR("Failed to apply compute state.\n");
1732 context_release(&context_vk->c);
1733 return;
1736 if (parameters->indirect)
1738 struct wined3d_bo_vk *bo = &indirect_vk->bo;
1740 wined3d_context_vk_reference_bo(context_vk, bo);
1741 VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer,
1742 bo->buffer_offset + parameters->u.indirect.offset));
1744 else
1746 const struct wined3d_direct_dispatch_parameters *direct = &parameters->u.direct;
1748 VK_CALL(vkCmdDispatch(vk_command_buffer, direct->group_count_x, direct->group_count_y, direct->group_count_z));
1751 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1752 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1754 context_release(&context_vk->c);
1757 void adapter_vk_clear_uav(struct wined3d_context *context,
1758 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value)
1760 TRACE("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
1762 wined3d_unordered_access_view_vk_clear_uint(wined3d_unordered_access_view_vk(view),
1763 clear_value, wined3d_context_vk(context));
1766 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
1768 .adapter_destroy = adapter_vk_destroy,
1769 .adapter_create_device = adapter_vk_create_device,
1770 .adapter_destroy_device = adapter_vk_destroy_device,
1771 .adapter_acquire_context = adapter_vk_acquire_context,
1772 .adapter_release_context = adapter_vk_release_context,
1773 .adapter_get_wined3d_caps = adapter_vk_get_wined3d_caps,
1774 .adapter_check_format = adapter_vk_check_format,
1775 .adapter_init_3d = adapter_vk_init_3d,
1776 .adapter_uninit_3d = adapter_vk_uninit_3d,
1777 .adapter_map_bo_address = adapter_vk_map_bo_address,
1778 .adapter_unmap_bo_address = adapter_vk_unmap_bo_address,
1779 .adapter_copy_bo_address = adapter_vk_copy_bo_address,
1780 .adapter_create_swapchain = adapter_vk_create_swapchain,
1781 .adapter_destroy_swapchain = adapter_vk_destroy_swapchain,
1782 .adapter_create_buffer = adapter_vk_create_buffer,
1783 .adapter_destroy_buffer = adapter_vk_destroy_buffer,
1784 .adapter_create_texture = adapter_vk_create_texture,
1785 .adapter_destroy_texture = adapter_vk_destroy_texture,
1786 .adapter_create_rendertarget_view = adapter_vk_create_rendertarget_view,
1787 .adapter_destroy_rendertarget_view = adapter_vk_destroy_rendertarget_view,
1788 .adapter_create_shader_resource_view = adapter_vk_create_shader_resource_view,
1789 .adapter_destroy_shader_resource_view = adapter_vk_destroy_shader_resource_view,
1790 .adapter_create_unordered_access_view = adapter_vk_create_unordered_access_view,
1791 .adapter_destroy_unordered_access_view = adapter_vk_destroy_unordered_access_view,
1792 .adapter_create_sampler = adapter_vk_create_sampler,
1793 .adapter_destroy_sampler = adapter_vk_destroy_sampler,
1794 .adapter_create_query = adapter_vk_create_query,
1795 .adapter_destroy_query = adapter_vk_destroy_query,
1796 .adapter_flush_context = adapter_vk_flush_context,
1797 .adapter_draw_primitive = adapter_vk_draw_primitive,
1798 .adapter_dispatch_compute = adapter_vk_dispatch_compute,
1799 .adapter_clear_uav = adapter_vk_clear_uav,
1802 static unsigned int wined3d_get_wine_vk_version(void)
1804 const char *ptr = PACKAGE_VERSION;
1805 int major, minor;
1807 major = atoi(ptr);
1809 while (isdigit(*ptr))
1810 ++ptr;
1811 if (*ptr == '.')
1812 ++ptr;
1814 minor = atoi(ptr);
1816 return VK_MAKE_VERSION(major, minor, 0);
1819 static const struct
1821 const char *name;
1822 unsigned int core_since_version;
1823 BOOL required;
1825 vulkan_instance_extensions[] =
1827 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1828 {VK_KHR_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1829 {VK_KHR_WIN32_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1832 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
1833 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
1835 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
1836 VkExtensionProperties *extensions = NULL;
1837 BOOL success = FALSE, found;
1838 unsigned int i, j, count;
1839 VkResult vr;
1841 *extension_count = 0;
1843 if (!(pfn_vkEnumerateInstanceExtensionProperties
1844 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
1846 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
1847 goto done;
1850 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
1852 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1853 goto done;
1855 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
1857 WARN("Out of memory.\n");
1858 goto done;
1860 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
1862 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1863 goto done;
1866 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
1868 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
1869 continue;
1871 for (j = 0, found = FALSE; j < count; ++j)
1873 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
1875 found = TRUE;
1876 break;
1879 if (found)
1881 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
1882 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
1884 else if (!found && vulkan_instance_extensions[i].required)
1886 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
1887 goto done;
1890 success = TRUE;
1892 done:
1893 heap_free(extensions);
1894 return success;
1897 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
1899 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
1900 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
1901 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
1902 VkInstance instance = VK_NULL_HANDLE;
1903 VkInstanceCreateInfo instance_info;
1904 VkApplicationInfo app_info;
1905 uint32_t api_version = 0;
1906 char app_name[MAX_PATH];
1907 VkResult vr;
1909 if (!wined3d_load_vulkan(vk_info))
1910 return FALSE;
1912 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
1914 ERR("Failed to get 'vkCreateInstance'.\n");
1915 goto fail;
1918 vk_info->api_version = VK_API_VERSION_1_0;
1919 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
1920 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
1922 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
1924 if (api_version >= VK_API_VERSION_1_1)
1925 vk_info->api_version = VK_API_VERSION_1_1;
1928 memset(&app_info, 0, sizeof(app_info));
1929 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1930 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
1931 app_info.pApplicationName = app_name;
1932 app_info.pEngineName = "Damavand";
1933 app_info.engineVersion = wined3d_get_wine_vk_version();
1934 app_info.apiVersion = vk_info->api_version;
1936 memset(&instance_info, 0, sizeof(instance_info));
1937 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1938 instance_info.pApplicationInfo = &app_info;
1939 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
1940 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
1941 goto fail;
1943 memset(vk_info->supported, 0, sizeof(vk_info->supported));
1944 vk_info->supported[WINED3D_VK_EXT_NONE] = TRUE;
1946 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
1948 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
1949 goto fail;
1952 TRACE("Created Vulkan instance %p.\n", instance);
1954 #define LOAD_INSTANCE_PFN(name) \
1955 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
1957 WARN("Could not get instance proc addr for '" #name "'.\n"); \
1958 goto fail; \
1960 #define LOAD_INSTANCE_OPT_PFN(name) \
1961 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
1962 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
1963 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
1964 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
1965 VK_INSTANCE_FUNCS()
1966 VK_DEVICE_FUNCS()
1967 #undef VK_INSTANCE_PFN
1968 #undef VK_INSTANCE_EXT_PFN
1969 #undef VK_DEVICE_PFN
1971 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
1972 if (!vk_ops->core_pfn) \
1973 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
1974 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
1975 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2KHR)
1976 #undef MAP_INSTANCE_FUNCTION
1978 vk_info->instance = instance;
1980 return TRUE;
1982 fail:
1983 if (vk_ops->vkDestroyInstance)
1984 VK_CALL(vkDestroyInstance(instance, NULL));
1985 wined3d_unload_vulkan(vk_info);
1986 return FALSE;
1989 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
1991 VkPhysicalDevice physical_devices[1];
1992 uint32_t count;
1993 VkResult vr;
1995 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
1997 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
1998 return VK_NULL_HANDLE;
2000 if (!count)
2002 WARN("No physical device.\n");
2003 return VK_NULL_HANDLE;
2005 if (count > 1)
2007 /* TODO: Create wined3d_adapter for each device. */
2008 FIXME("Multiple physical devices available.\n");
2009 count = 1;
2012 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
2014 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2015 return VK_NULL_HANDLE;
2018 return physical_devices[0];
2021 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
2023 switch (vendor)
2025 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
2026 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
2027 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
2028 default: return DRIVER_WINE;
2032 static bool adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
2033 const VkPhysicalDeviceProperties *properties)
2035 const VkPhysicalDeviceMemoryProperties *memory_properties = &adapter_vk->memory_properties;
2036 const struct wined3d_gpu_description *gpu_description;
2037 struct wined3d_gpu_description description;
2038 UINT64 vram_bytes, sysmem_bytes;
2039 const VkMemoryHeap *heap;
2040 unsigned int i;
2042 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
2043 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
2044 TRACE("Driver version: %#x.\n", properties->driverVersion);
2045 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
2047 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
2049 heap = &memory_properties->memoryHeaps[i];
2050 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
2051 i, heap->flags, wine_dbgstr_longlong(heap->size));
2052 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
2053 vram_bytes += heap->size;
2054 else
2055 sysmem_bytes += heap->size;
2057 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
2058 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
2060 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
2061 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
2063 if (!gpu_description)
2065 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
2066 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
2068 description.vendor = properties->vendorID;
2069 description.device = properties->deviceID;
2070 description.description = properties->deviceName;
2071 description.driver = guess_display_driver(properties->vendorID);
2072 description.vidmem = vram_bytes;
2074 gpu_description = &description;
2077 return wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description,
2078 adapter_vk->a.d3d_info.feature_level, vram_bytes, sysmem_bytes);
2081 static enum wined3d_feature_level feature_level_from_caps(const struct shader_caps *shader_caps)
2083 unsigned int shader_model;
2085 shader_model = min(shader_caps->vs_version, shader_caps->ps_version);
2086 shader_model = min(shader_model, max(shader_caps->gs_version, 3));
2087 shader_model = min(shader_model, max(shader_caps->hs_version, 4));
2088 shader_model = min(shader_model, max(shader_caps->ds_version, 4));
2090 if (shader_model >= 5)
2091 return WINED3D_FEATURE_LEVEL_11_1;
2093 if (shader_model >= 4)
2094 return WINED3D_FEATURE_LEVEL_10_1;
2096 return WINED3D_FEATURE_LEVEL_NONE;
2099 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
2101 struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info;
2102 struct wined3d_vertex_caps vertex_caps;
2103 struct fragment_caps fragment_caps;
2104 struct shader_caps shader_caps;
2106 adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps);
2107 adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps);
2108 adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps);
2110 d3d_info->limits.vs_version = shader_caps.vs_version;
2111 d3d_info->limits.hs_version = shader_caps.hs_version;
2112 d3d_info->limits.ds_version = shader_caps.ds_version;
2113 d3d_info->limits.gs_version = shader_caps.gs_version;
2114 d3d_info->limits.ps_version = shader_caps.ps_version;
2115 d3d_info->limits.cs_version = shader_caps.cs_version;
2116 d3d_info->limits.vs_uniform_count = shader_caps.vs_uniform_count;
2117 d3d_info->limits.ps_uniform_count = shader_caps.ps_uniform_count;
2118 d3d_info->limits.varying_count = shader_caps.varying_count;
2119 d3d_info->limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
2120 d3d_info->limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
2121 d3d_info->limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
2122 d3d_info->limits.active_light_count = vertex_caps.max_active_lights;
2124 d3d_info->limits.max_rt_count = WINED3D_MAX_RENDER_TARGETS;
2125 d3d_info->limits.max_clip_distances = WINED3D_MAX_CLIP_DISTANCES;
2126 d3d_info->limits.texture_size = adapter_vk->device_limits.maxImageDimension2D;
2127 d3d_info->limits.pointsize_max = adapter_vk->device_limits.pointSizeRange[1];
2129 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
2131 d3d_info->xyzrhw = vertex_caps.xyzrhw;
2132 d3d_info->emulated_flatshading = vertex_caps.emulated_flatshading;
2133 d3d_info->ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
2134 d3d_info->ffp_alpha_test = false;
2135 d3d_info->vs_clipping = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING);
2136 d3d_info->shader_color_key = !!(fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY);
2137 d3d_info->shader_double_precision = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_DOUBLE_PRECISION);
2138 d3d_info->shader_output_interpolation = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION);
2139 d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */
2140 d3d_info->texture_npot = true;
2141 d3d_info->texture_npot_conditional = true;
2142 d3d_info->draw_base_vertex_offset = true;
2143 d3d_info->vertex_bgra = true;
2144 d3d_info->texture_swizzle = true;
2145 d3d_info->srgb_read_control = false;
2146 d3d_info->srgb_write_control = false;
2147 d3d_info->clip_control = true;
2148 d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS);
2149 d3d_info->scaled_resolve = false;
2150 d3d_info->feature_level = feature_level_from_caps(&shader_caps);
2152 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
2155 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
2156 unsigned int ordinal, unsigned int wined3d_creation_flags)
2158 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2159 struct wined3d_adapter *adapter = &adapter_vk->a;
2160 VkPhysicalDeviceIDProperties id_properties;
2161 VkPhysicalDeviceProperties2 properties2;
2162 LUID *luid = NULL;
2164 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
2165 adapter_vk, ordinal, wined3d_creation_flags);
2167 if (!wined3d_init_vulkan(vk_info))
2169 WARN("Failed to initialize Vulkan.\n");
2170 return FALSE;
2173 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
2174 goto fail_vulkan;
2176 memset(&id_properties, 0, sizeof(id_properties));
2177 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
2178 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2179 properties2.pNext = &id_properties;
2181 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
2182 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
2183 else
2184 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
2185 adapter_vk->device_limits = properties2.properties.limits;
2187 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &adapter_vk->memory_properties));
2189 if (id_properties.deviceLUIDValid)
2190 luid = (LUID *)id_properties.deviceLUID;
2192 if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_vk_ops))
2193 goto fail_vulkan;
2195 adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk();
2196 adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk();
2197 adapter->misc_state_template = misc_state_template_vk;
2198 adapter->shader_backend = wined3d_spirv_shader_backend_init_vk();
2200 wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
2202 if (!adapter_vk_init_driver_info(adapter_vk, &properties2.properties))
2203 goto fail;
2204 TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
2205 adapter_vk->a.driver_info.version_high, adapter_vk->a.driver_info.version_low);
2206 adapter->vram_bytes_used = 0;
2207 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
2209 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
2210 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
2212 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
2213 goto fail;
2215 return TRUE;
2217 fail:
2218 wined3d_adapter_cleanup(adapter);
2219 fail_vulkan:
2220 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
2221 wined3d_unload_vulkan(vk_info);
2222 return FALSE;
2225 struct wined3d_adapter *wined3d_adapter_vk_create(unsigned int ordinal,
2226 unsigned int wined3d_creation_flags)
2228 struct wined3d_adapter_vk *adapter_vk;
2230 if (!(adapter_vk = heap_alloc_zero(sizeof(*adapter_vk))))
2231 return NULL;
2233 if (!wined3d_adapter_vk_init(adapter_vk, ordinal, wined3d_creation_flags))
2235 heap_free(adapter_vk);
2236 return NULL;
2239 TRACE("Created adapter %p.\n", adapter_vk);
2241 return &adapter_vk->a;