wined3d: Partially implement adapter_vk_clear_uav().
[wine.git] / dlls / wined3d / adapter_vk.c
blob1e4d663dcb435c76d15d6e1140245f1be2e148df
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_STREAMSRC, {STATE_STREAMSRC, state_nop}},
43 {STATE_VDECL, {STATE_VDECL, state_nop}},
44 {STATE_RASTERIZER, {STATE_RASTERIZER, state_nop}},
45 {STATE_SCISSORRECT, {STATE_SCISSORRECT, state_nop}},
46 {STATE_POINTSPRITECOORDORIGIN, {STATE_POINTSPRITECOORDORIGIN, state_nop}},
48 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
49 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
50 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
51 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00)}},
52 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
53 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
54 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
55 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00)}},
56 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
57 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
58 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
59 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00)}},
60 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
61 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
62 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
63 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00)}},
64 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
65 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
66 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
67 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00)}},
68 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
69 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
70 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
71 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00)}},
72 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
73 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
74 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
75 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00)}},
76 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), state_nop}},
77 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
78 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
79 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00)}},
80 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
81 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE)}},
82 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
83 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE)}},
84 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
85 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE)}},
86 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
87 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE)}},
88 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
89 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE)}},
90 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
91 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE)}},
92 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
93 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE)}},
94 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE), state_nop}},
95 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE)}},
97 {STATE_VIEWPORT, {STATE_VIEWPORT, state_nop}},
98 {STATE_INDEXBUFFER, {STATE_INDEXBUFFER, state_nop}},
99 {STATE_RENDER(WINED3D_RS_ANTIALIAS), {STATE_RENDER(WINED3D_RS_ANTIALIAS), state_nop}},
100 {STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE), {STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE), state_nop}},
101 {STATE_RENDER(WINED3D_RS_ZENABLE), {STATE_RENDER(WINED3D_RS_ZENABLE), state_nop}},
102 {STATE_RENDER(WINED3D_RS_WRAPU), {STATE_RENDER(WINED3D_RS_WRAPU), state_nop}},
103 {STATE_RENDER(WINED3D_RS_WRAPV), {STATE_RENDER(WINED3D_RS_WRAPV), state_nop}},
104 {STATE_RENDER(WINED3D_RS_LINEPATTERN), {STATE_RENDER(WINED3D_RS_LINEPATTERN), state_nop}},
105 {STATE_RENDER(WINED3D_RS_MONOENABLE), {STATE_RENDER(WINED3D_RS_MONOENABLE), state_nop}},
106 {STATE_RENDER(WINED3D_RS_ROP2), {STATE_RENDER(WINED3D_RS_ROP2), state_nop}},
107 {STATE_RENDER(WINED3D_RS_PLANEMASK), {STATE_RENDER(WINED3D_RS_PLANEMASK), state_nop}},
108 {STATE_RENDER(WINED3D_RS_ZWRITEENABLE), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
109 {STATE_RENDER(WINED3D_RS_LASTPIXEL), {STATE_RENDER(WINED3D_RS_LASTPIXEL), state_nop}},
110 {STATE_RENDER(WINED3D_RS_ZFUNC), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
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_STENCILENABLE), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
121 {STATE_RENDER(WINED3D_RS_STENCILFAIL), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
122 {STATE_RENDER(WINED3D_RS_STENCILZFAIL), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
123 {STATE_RENDER(WINED3D_RS_STENCILPASS), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
124 {STATE_RENDER(WINED3D_RS_STENCILFUNC), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
125 {STATE_RENDER(WINED3D_RS_STENCILREF), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
126 {STATE_RENDER(WINED3D_RS_STENCILMASK), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
127 {STATE_RENDER(WINED3D_RS_STENCILWRITEMASK), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
128 {STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
129 {STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
130 {STATE_RENDER(WINED3D_RS_BACK_STENCILZFAIL), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
131 {STATE_RENDER(WINED3D_RS_BACK_STENCILPASS), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
132 {STATE_RENDER(WINED3D_RS_BACK_STENCILFUNC), {STATE_RENDER(WINED3D_RS_ZENABLE)}},
133 {STATE_RENDER(WINED3D_RS_WRAP0), {STATE_RENDER(WINED3D_RS_WRAP0), state_nop}},
134 {STATE_RENDER(WINED3D_RS_WRAP1), {STATE_RENDER(WINED3D_RS_WRAP0)}},
135 {STATE_RENDER(WINED3D_RS_WRAP2), {STATE_RENDER(WINED3D_RS_WRAP0)}},
136 {STATE_RENDER(WINED3D_RS_WRAP3), {STATE_RENDER(WINED3D_RS_WRAP0)}},
137 {STATE_RENDER(WINED3D_RS_WRAP4), {STATE_RENDER(WINED3D_RS_WRAP0)}},
138 {STATE_RENDER(WINED3D_RS_WRAP5), {STATE_RENDER(WINED3D_RS_WRAP0)}},
139 {STATE_RENDER(WINED3D_RS_WRAP6), {STATE_RENDER(WINED3D_RS_WRAP0)}},
140 {STATE_RENDER(WINED3D_RS_WRAP7), {STATE_RENDER(WINED3D_RS_WRAP0)}},
141 {STATE_RENDER(WINED3D_RS_WRAP8), {STATE_RENDER(WINED3D_RS_WRAP0)}},
142 {STATE_RENDER(WINED3D_RS_WRAP9), {STATE_RENDER(WINED3D_RS_WRAP0)}},
143 {STATE_RENDER(WINED3D_RS_WRAP10), {STATE_RENDER(WINED3D_RS_WRAP0)}},
144 {STATE_RENDER(WINED3D_RS_WRAP11), {STATE_RENDER(WINED3D_RS_WRAP0)}},
145 {STATE_RENDER(WINED3D_RS_WRAP12), {STATE_RENDER(WINED3D_RS_WRAP0)}},
146 {STATE_RENDER(WINED3D_RS_WRAP13), {STATE_RENDER(WINED3D_RS_WRAP0)}},
147 {STATE_RENDER(WINED3D_RS_WRAP14), {STATE_RENDER(WINED3D_RS_WRAP0)}},
148 {STATE_RENDER(WINED3D_RS_WRAP15), {STATE_RENDER(WINED3D_RS_WRAP0)}},
149 {STATE_RENDER(WINED3D_RS_EXTENTS), {STATE_RENDER(WINED3D_RS_EXTENTS), state_nop}},
150 {STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE), {STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE), state_nop}},
151 {STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING), {STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING), state_nop}},
152 {STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE), {STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE), state_nop}},
153 {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS), state_nop}},
154 {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), {STATE_RENDER(WINED3D_RS_POSITIONDEGREE), state_nop}},
155 {STATE_RENDER(WINED3D_RS_NORMALDEGREE), {STATE_RENDER(WINED3D_RS_NORMALDEGREE), state_nop}},
156 {STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
157 {STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
158 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
159 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
160 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
161 {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)}},
162 {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), state_nop}},
163 {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS), state_nop}},
164 {STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK), {STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK), state_nop}},
165 {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN), state_nop}},
166 {STATE_RENDER(WINED3D_RS_ZVISIBLE), {STATE_RENDER(WINED3D_RS_ZVISIBLE), state_nop}},
167 /* Samplers */
168 {STATE_SAMPLER(0), {STATE_SAMPLER(0), state_nop}},
169 {STATE_SAMPLER(1), {STATE_SAMPLER(1), state_nop}},
170 {STATE_SAMPLER(2), {STATE_SAMPLER(2), state_nop}},
171 {STATE_SAMPLER(3), {STATE_SAMPLER(3), state_nop}},
172 {STATE_SAMPLER(4), {STATE_SAMPLER(4), state_nop}},
173 {STATE_SAMPLER(5), {STATE_SAMPLER(5), state_nop}},
174 {STATE_SAMPLER(6), {STATE_SAMPLER(6), state_nop}},
175 {STATE_SAMPLER(7), {STATE_SAMPLER(7), state_nop}},
176 {STATE_SAMPLER(8), {STATE_SAMPLER(8), state_nop}},
177 {STATE_SAMPLER(9), {STATE_SAMPLER(9), state_nop}},
178 {STATE_SAMPLER(10), {STATE_SAMPLER(10), state_nop}},
179 {STATE_SAMPLER(11), {STATE_SAMPLER(11), state_nop}},
180 {STATE_SAMPLER(12), {STATE_SAMPLER(12), state_nop}},
181 {STATE_SAMPLER(13), {STATE_SAMPLER(13), state_nop}},
182 {STATE_SAMPLER(14), {STATE_SAMPLER(14), state_nop}},
183 {STATE_SAMPLER(15), {STATE_SAMPLER(15), state_nop}},
184 {STATE_SAMPLER(16), /* Vertex sampler 0 */ {STATE_SAMPLER(16), state_nop}},
185 {STATE_SAMPLER(17), /* Vertex sampler 1 */ {STATE_SAMPLER(17), state_nop}},
186 {STATE_SAMPLER(18), /* Vertex sampler 2 */ {STATE_SAMPLER(18), state_nop}},
187 {STATE_SAMPLER(19), /* Vertex sampler 3 */ {STATE_SAMPLER(19), state_nop}},
188 {STATE_BASEVERTEXINDEX, {STATE_STREAMSRC}},
189 {STATE_FRAMEBUFFER, {STATE_FRAMEBUFFER, state_nop}},
190 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), state_nop}},
191 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), state_nop}},
192 {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN), state_nop}},
193 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), state_nop}},
194 {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE), state_nop}},
195 {0}, /* Terminate */
198 static inline const struct wined3d_adapter_vk *wined3d_adapter_vk_const(const struct wined3d_adapter *adapter)
200 return CONTAINING_RECORD(adapter, struct wined3d_adapter_vk, a);
203 static const char *debug_vk_version(uint32_t version)
205 return wine_dbg_sprintf("%u.%u.%u",
206 VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version));
209 static HRESULT hresult_from_vk_result(VkResult vr)
211 switch (vr)
213 case VK_SUCCESS:
214 return S_OK;
215 case VK_ERROR_OUT_OF_HOST_MEMORY:
216 WARN("Out of host memory.\n");
217 return E_OUTOFMEMORY;
218 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
219 WARN("Out of device memory.\n");
220 return E_OUTOFMEMORY;
221 case VK_ERROR_DEVICE_LOST:
222 WARN("Device lost.\n");
223 return E_FAIL;
224 case VK_ERROR_EXTENSION_NOT_PRESENT:
225 WARN("Extension not present.\n");
226 return E_FAIL;
227 default:
228 FIXME("Unhandled VkResult %d.\n", vr);
229 return E_FAIL;
233 #ifdef USE_WIN32_VULKAN
234 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
236 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
238 if (!(vk_info->vulkan_lib = LoadLibraryA("vulkan-1.dll")))
240 WARN("Failed to load vulkan-1.dll.\n");
241 return FALSE;
244 vk_ops->vkGetInstanceProcAddr = (void *)GetProcAddress(vk_info->vulkan_lib, "vkGetInstanceProcAddr");
245 if (!vk_ops->vkGetInstanceProcAddr)
247 FreeLibrary(vk_info->vulkan_lib);
248 return FALSE;
251 return TRUE;
254 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info)
256 if (vk_info->vulkan_lib)
258 FreeLibrary(vk_info->vulkan_lib);
259 vk_info->vulkan_lib = NULL;
262 #else
263 static BOOL wined3d_load_vulkan(struct wined3d_vk_info *vk_info)
265 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
266 const struct vulkan_funcs *vk_funcs;
267 HDC dc;
269 dc = GetDC(0);
270 vk_funcs = __wine_get_vulkan_driver(dc, WINE_VULKAN_DRIVER_VERSION);
271 ReleaseDC(0, dc);
273 if (!vk_funcs)
274 return FALSE;
276 vk_ops->vkGetInstanceProcAddr = (void *)vk_funcs->p_vkGetInstanceProcAddr;
277 return TRUE;
280 static void wined3d_unload_vulkan(struct wined3d_vk_info *vk_info) {}
281 #endif
283 static void adapter_vk_destroy(struct wined3d_adapter *adapter)
285 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter);
286 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
288 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
289 wined3d_unload_vulkan(vk_info);
290 wined3d_adapter_cleanup(&adapter_vk->a);
291 heap_free(adapter_vk);
294 static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk,
295 uint32_t *queue_family_index, uint32_t *timestamp_bits)
297 VkPhysicalDevice physical_device = adapter_vk->physical_device;
298 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
299 VkQueueFamilyProperties *queue_properties;
300 uint32_t count, i;
302 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, NULL));
304 if (!(queue_properties = heap_calloc(count, sizeof(*queue_properties))))
305 return E_OUTOFMEMORY;
307 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_properties));
309 for (i = 0; i < count; ++i)
311 if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
313 *queue_family_index = i;
314 *timestamp_bits = queue_properties[i].timestampValidBits;
315 heap_free(queue_properties);
316 return WINED3D_OK;
319 heap_free(queue_properties);
321 WARN("Failed to find graphics queue.\n");
322 return E_FAIL;
325 struct wined3d_physical_device_info
327 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
329 VkPhysicalDeviceFeatures2 features2;
332 static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info *info)
334 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features = &info->vertex_divisor_features;
335 VkPhysicalDeviceFeatures *features = &info->features2.features;
337 vertex_divisor_features->vertexAttributeInstanceRateZeroDivisor = VK_FALSE;
339 features->depthBounds = VK_FALSE;
340 features->alphaToOne = VK_FALSE;
341 features->textureCompressionETC2 = VK_FALSE;
342 features->textureCompressionASTC_LDR = VK_FALSE;
343 features->shaderStorageImageMultisample = VK_FALSE;
344 features->shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
345 features->shaderSampledImageArrayDynamicIndexing = VK_FALSE;
346 features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
347 features->shaderStorageImageArrayDynamicIndexing = VK_FALSE;
348 features->shaderInt16 = VK_FALSE;
349 features->shaderResourceResidency = VK_FALSE;
350 features->shaderResourceMinLod = VK_FALSE;
351 features->sparseBinding = VK_FALSE;
352 features->sparseResidencyBuffer = VK_FALSE;
353 features->sparseResidencyImage2D = VK_FALSE;
354 features->sparseResidencyImage3D = VK_FALSE;
355 features->sparseResidency2Samples = VK_FALSE;
356 features->sparseResidency4Samples = VK_FALSE;
357 features->sparseResidency8Samples = VK_FALSE;
358 features->sparseResidency16Samples = VK_FALSE;
359 features->sparseResidencyAliased = VK_FALSE;
360 features->inheritedQueries = VK_FALSE;
363 static struct wined3d_allocator_chunk *wined3d_allocator_vk_create_chunk(struct wined3d_allocator *allocator,
364 struct wined3d_context *context, unsigned int memory_type, size_t chunk_size)
366 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
367 struct wined3d_allocator_chunk_vk *chunk_vk;
369 if (!(chunk_vk = heap_alloc(sizeof(*chunk_vk))))
370 return NULL;
372 if (!wined3d_allocator_chunk_init(&chunk_vk->c, allocator))
374 heap_free(chunk_vk);
375 return NULL;
378 if (!(chunk_vk->vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, chunk_size)))
380 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
381 heap_free(chunk_vk);
382 return NULL;
384 list_add_head(&allocator->pools[memory_type].chunks, &chunk_vk->c.entry);
386 return &chunk_vk->c;
389 static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *chunk)
391 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(chunk);
392 const struct wined3d_vk_info *vk_info;
393 struct wined3d_device_vk *device_vk;
395 TRACE("chunk %p.\n", chunk);
397 device_vk = CONTAINING_RECORD(chunk_vk->c.allocator, struct wined3d_device_vk, allocator);
398 vk_info = &device_vk->vk_info;
400 if (chunk_vk->c.map_ptr)
401 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
402 VK_CALL(vkFreeMemory(device_vk->vk_device, chunk_vk->vk_memory, NULL));
403 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk->vk_memory));
404 wined3d_allocator_chunk_cleanup(&chunk_vk->c);
405 heap_free(chunk_vk);
408 static const struct wined3d_allocator_ops wined3d_allocator_vk_ops =
410 .allocator_create_chunk = wined3d_allocator_vk_create_chunk,
411 .allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk,
414 static const struct
416 const char *name;
417 unsigned int core_since_version;
419 vulkan_device_extensions[] =
421 {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
422 {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
423 {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
424 {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
427 static bool enable_vulkan_device_extensions(VkPhysicalDevice physical_device, uint32_t *extension_count,
428 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
430 VkExtensionProperties *extensions = NULL;
431 bool success = false, found;
432 unsigned int i, j, count;
433 VkResult vr;
435 *extension_count = 0;
437 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
439 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
440 goto done;
442 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
444 WARN("Out of memory.\n");
445 goto done;
447 if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
449 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
450 goto done;
453 for (i = 0; i < ARRAY_SIZE(vulkan_device_extensions); ++i)
455 if (vulkan_device_extensions[i].core_since_version <= vk_info->api_version)
456 continue;
458 for (j = 0, found = false; j < count; ++j)
460 if (!strcmp(extensions[j].extensionName, vulkan_device_extensions[i].name))
462 found = true;
463 break;
467 if (!found)
469 WARN("Required extension '%s' is not available.\n", vulkan_device_extensions[i].name);
470 goto done;
473 TRACE("Enabling instance extension '%s'.\n", vulkan_device_extensions[i].name);
474 enabled_extensions[(*extension_count)++] = vulkan_device_extensions[i].name;
476 success = true;
478 done:
479 heap_free(extensions);
480 return success;
483 static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
484 enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
485 const enum wined3d_feature_level *levels, unsigned int level_count,
486 struct wined3d_device_parent *device_parent, struct wined3d_device **device)
488 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
489 const char *enabled_device_extensions[ARRAY_SIZE(vulkan_device_extensions)];
490 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
491 const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
492 struct wined3d_physical_device_info physical_device_info;
493 static const float priorities[] = {1.0f};
494 VkPhysicalDeviceFeatures2 *features2;
495 struct wined3d_device_vk *device_vk;
496 VkDevice vk_device = VK_NULL_HANDLE;
497 VkDeviceQueueCreateInfo queue_info;
498 VkPhysicalDevice physical_device;
499 VkDeviceCreateInfo device_info;
500 uint32_t queue_family_index;
501 uint32_t timestamp_bits;
502 VkResult vr;
503 HRESULT hr;
505 if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
506 return E_OUTOFMEMORY;
508 if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, &timestamp_bits)))
509 goto fail;
511 physical_device = adapter_vk->physical_device;
513 memset(&physical_device_info, 0, sizeof(physical_device_info));
515 vertex_divisor_features = &physical_device_info.vertex_divisor_features;
516 vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
518 features2 = &physical_device_info.features2;
519 features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
520 features2->pNext = vertex_divisor_features;
522 if (vk_info->vk_ops.vkGetPhysicalDeviceFeatures2)
523 VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device, features2));
524 else
525 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &features2->features));
527 if (!vertex_divisor_features->vertexAttributeInstanceRateDivisor)
529 WARN("Vertex attribute divisors not supported.\n");
530 hr = E_FAIL;
531 goto fail;
534 wined3d_disable_vulkan_features(&physical_device_info);
536 queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
537 queue_info.pNext = NULL;
538 queue_info.flags = 0;
539 queue_info.queueFamilyIndex = queue_family_index;
540 queue_info.queueCount = ARRAY_SIZE(priorities);
541 queue_info.pQueuePriorities = priorities;
543 device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
544 device_info.pNext = features2->pNext;
545 device_info.flags = 0;
546 device_info.queueCreateInfoCount = 1;
547 device_info.pQueueCreateInfos = &queue_info;
548 device_info.enabledLayerCount = 0;
549 device_info.ppEnabledLayerNames = NULL;
550 device_info.ppEnabledExtensionNames = enabled_device_extensions;
551 if (!enable_vulkan_device_extensions(physical_device,
552 &device_info.enabledExtensionCount, enabled_device_extensions, vk_info))
554 hr = E_FAIL;
555 goto fail;
557 device_info.pEnabledFeatures = &features2->features;
559 if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
561 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr));
562 vk_device = VK_NULL_HANDLE;
563 hr = hresult_from_vk_result(vr);
564 goto fail;
567 device_vk->vk_device = vk_device;
568 VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
569 device_vk->vk_queue_family_index = queue_family_index;
570 device_vk->timestamp_bits = timestamp_bits;
572 device_vk->vk_info = *vk_info;
573 #define LOAD_DEVICE_PFN(name) \
574 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
576 WARN("Could not get device proc addr for '" #name "'.\n"); \
577 hr = E_FAIL; \
578 goto fail; \
580 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
581 VK_DEVICE_FUNCS()
582 #undef VK_DEVICE_PFN
584 if (!wined3d_allocator_init(&device_vk->allocator,
585 adapter_vk->memory_properties.memoryTypeCount, &wined3d_allocator_vk_ops))
587 WARN("Failed to initialise allocator.\n");
588 hr = E_FAIL;
589 goto fail;
592 if (FAILED(hr = wined3d_device_init(&device_vk->d, wined3d, adapter->ordinal, device_type, focus_window,
593 flags, surface_alignment, levels, level_count, vk_info->supported, device_parent)))
595 WARN("Failed to initialize device, hr %#x.\n", hr);
596 wined3d_allocator_cleanup(&device_vk->allocator);
597 goto fail;
600 *device = &device_vk->d;
602 return WINED3D_OK;
604 fail:
605 VK_CALL(vkDestroyDevice(vk_device, NULL));
606 heap_free(device_vk);
607 return hr;
610 static void adapter_vk_destroy_device(struct wined3d_device *device)
612 struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
613 const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
615 wined3d_device_cleanup(&device_vk->d);
616 wined3d_allocator_cleanup(&device_vk->allocator);
617 VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL));
618 heap_free(device_vk);
621 struct wined3d_context *adapter_vk_acquire_context(struct wined3d_device *device,
622 struct wined3d_texture *texture, unsigned int sub_resource_idx)
624 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
626 wined3d_from_cs(device->cs);
628 if (!device->context_count)
629 return NULL;
631 return &wined3d_device_vk(device)->context_vk.c;
634 void adapter_vk_release_context(struct wined3d_context *context)
636 TRACE("context %p.\n", context);
639 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
641 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
642 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
643 BOOL sampler_anisotropy = limits->maxSamplerAnisotropy > 1.0f;
645 caps->ddraw_caps.dds_caps |= WINEDDSCAPS_BACKBUFFER
646 | WINEDDSCAPS_COMPLEX
647 | WINEDDSCAPS_FRONTBUFFER
648 | WINEDDSCAPS_3DDEVICE
649 | WINEDDSCAPS_VIDEOMEMORY
650 | WINEDDSCAPS_OWNDC
651 | WINEDDSCAPS_LOCALVIDMEM
652 | WINEDDSCAPS_NONLOCALVIDMEM;
653 caps->ddraw_caps.caps |= WINEDDCAPS_3D;
655 caps->Caps2 |= WINED3DCAPS2_CANGENMIPMAP;
657 caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_BLENDOP
658 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
659 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
660 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
661 | WINED3DPMISCCAPS_SEPARATEALPHABLEND;
663 caps->RasterCaps |= WINED3DPRASTERCAPS_MIPMAPLODBIAS;
665 if (sampler_anisotropy)
667 caps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY;
669 caps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
670 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
672 caps->MaxAnisotropy = limits->maxSamplerAnisotropy;
675 caps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
676 caps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR
677 | WINED3DPBLENDCAPS_SRCALPHASAT;
679 caps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP
680 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
681 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
682 caps->VolumeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
683 | WINED3DPTFILTERCAPS_MAGFPOINT
684 | WINED3DPTFILTERCAPS_MINFLINEAR
685 | WINED3DPTFILTERCAPS_MINFPOINT
686 | WINED3DPTFILTERCAPS_MIPFLINEAR
687 | WINED3DPTFILTERCAPS_MIPFPOINT
688 | WINED3DPTFILTERCAPS_LINEAR
689 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
690 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
691 | WINED3DPTFILTERCAPS_MIPLINEAR
692 | WINED3DPTFILTERCAPS_MIPNEAREST
693 | WINED3DPTFILTERCAPS_NEAREST;
694 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_INDEPENDENTUV
695 | WINED3DPTADDRESSCAPS_CLAMP
696 | WINED3DPTADDRESSCAPS_WRAP;
697 caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
698 | WINED3DPTADDRESSCAPS_MIRROR
699 | WINED3DPTADDRESSCAPS_MIRRORONCE;
701 caps->MaxVolumeExtent = limits->maxImageDimension3D;
703 caps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP
704 | WINED3DPTEXTURECAPS_MIPCUBEMAP
705 | WINED3DPTEXTURECAPS_CUBEMAP_POW2;
706 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFLINEAR
707 | WINED3DPTFILTERCAPS_MAGFPOINT
708 | WINED3DPTFILTERCAPS_MINFLINEAR
709 | WINED3DPTFILTERCAPS_MINFPOINT
710 | WINED3DPTFILTERCAPS_MIPFLINEAR
711 | WINED3DPTFILTERCAPS_MIPFPOINT
712 | WINED3DPTFILTERCAPS_LINEAR
713 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
714 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
715 | WINED3DPTFILTERCAPS_MIPLINEAR
716 | WINED3DPTFILTERCAPS_MIPNEAREST
717 | WINED3DPTFILTERCAPS_NEAREST;
719 if (sampler_anisotropy)
721 caps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
722 | WINED3DPTFILTERCAPS_MINFANISOTROPIC;
725 caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER
726 | WINED3DPTADDRESSCAPS_MIRROR
727 | WINED3DPTADDRESSCAPS_MIRRORONCE;
729 caps->StencilCaps |= WINED3DSTENCILCAPS_DECR
730 | WINED3DSTENCILCAPS_INCR
731 | WINED3DSTENCILCAPS_TWOSIDED;
733 caps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 | WINED3DDTCAPS_FLOAT16_4;
735 caps->MaxPixelShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
736 caps->MaxVertexShader30InstructionSlots = WINED3DMAX30SHADERINSTRUCTIONS;
737 caps->PS20Caps.temp_count = WINED3DPS20_MAX_NUMTEMPS;
738 caps->VS20Caps.temp_count = WINED3DVS20_MAX_NUMTEMPS;
741 static BOOL adapter_vk_check_format(const struct wined3d_adapter *adapter,
742 const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
743 const struct wined3d_format *ds_format)
745 return TRUE;
748 static HRESULT adapter_vk_init_3d(struct wined3d_device *device)
750 struct wined3d_context_vk *context_vk;
751 struct wined3d_device_vk *device_vk;
752 HRESULT hr;
754 TRACE("device %p.\n", device);
756 device_vk = wined3d_device_vk(device);
757 context_vk = &device_vk->context_vk;
758 if (FAILED(hr = wined3d_context_vk_init(context_vk, device->swapchains[0])))
760 WARN("Failed to initialise context.\n");
761 return hr;
764 if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
765 device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
767 ERR("Failed to allocate shader private data, hr %#x.\n", hr);
768 wined3d_context_vk_cleanup(context_vk);
769 return hr;
772 if (!device_context_add(device, &context_vk->c))
774 ERR("Failed to add the newly created context to the context list.\n");
775 device->shader_backend->shader_free_private(device, NULL);
776 wined3d_context_vk_cleanup(context_vk);
777 return E_FAIL;
780 TRACE("Initialised context %p.\n", context_vk);
782 if (!(device_vk->d.blitter = wined3d_cpu_blitter_create()))
784 ERR("Failed to create CPU blitter.\n");
785 device_context_remove(device, &context_vk->c);
786 device->shader_backend->shader_free_private(device, NULL);
787 wined3d_context_vk_cleanup(context_vk);
788 return E_FAIL;
790 wined3d_vk_blitter_create(&device_vk->d.blitter);
792 wined3d_device_create_default_samplers(device, &context_vk->c);
793 wined3d_device_vk_create_null_resources(device_vk, context_vk);
794 wined3d_device_vk_create_null_views(device_vk, context_vk);
796 return WINED3D_OK;
799 static void adapter_vk_uninit_3d_cs(void *object)
801 struct wined3d_device_vk *device_vk = object;
802 struct wined3d_context_vk *context_vk;
803 struct wined3d_device *device;
804 struct wined3d_shader *shader;
806 TRACE("device_vk %p.\n", device_vk);
808 context_vk = &device_vk->context_vk;
809 device = &device_vk->d;
811 LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry)
813 device->shader_backend->shader_destroy(shader);
816 device->blitter->ops->blitter_destroy(device->blitter, NULL);
817 device->shader_backend->shader_free_private(device, &context_vk->c);
818 wined3d_device_vk_destroy_null_views(device_vk, context_vk);
819 wined3d_device_vk_destroy_null_resources(device_vk, context_vk);
820 wined3d_device_destroy_default_samplers(device, &context_vk->c);
823 static void adapter_vk_uninit_3d(struct wined3d_device *device)
825 struct wined3d_context_vk *context_vk;
826 struct wined3d_device_vk *device_vk;
828 TRACE("device %p.\n", device);
830 device_vk = wined3d_device_vk(device);
831 context_vk = &device_vk->context_vk;
833 wined3d_cs_destroy_object(device->cs, adapter_vk_uninit_3d_cs, device_vk);
834 wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
836 device_context_remove(device, &context_vk->c);
837 wined3d_context_vk_cleanup(context_vk);
840 static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
842 const struct wined3d_vk_info *vk_info;
843 struct wined3d_device_vk *device_vk;
844 struct wined3d_bo_slab_vk *slab;
845 void *map_ptr;
846 VkResult vr;
848 if (bo->map_ptr)
849 return bo->map_ptr;
851 vk_info = context_vk->vk_info;
852 device_vk = wined3d_device_vk(context_vk->c.device);
854 if ((slab = bo->slab))
856 if (!(map_ptr = slab->map_ptr) && !(map_ptr = wined3d_bo_vk_map(&slab->bo, context_vk)))
858 ERR("Failed to map slab.\n");
859 return NULL;
861 ++slab->map_count;
863 else if (bo->memory)
865 struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(bo->memory->chunk);
867 if (!(map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk)))
869 ERR("Failed to map chunk.\n");
870 return NULL;
873 else if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0)
875 ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr));
876 return NULL;
879 if (sizeof(map_ptr) >= sizeof(uint64_t))
880 bo->map_ptr = map_ptr;
882 return map_ptr;
885 static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk)
887 const struct wined3d_vk_info *vk_info;
888 struct wined3d_device_vk *device_vk;
889 struct wined3d_bo_slab_vk *slab;
891 if (bo->map_ptr)
892 return;
894 if ((slab = bo->slab))
896 if (--slab->map_count)
897 return;
899 wined3d_bo_vk_unmap(&slab->bo, context_vk);
900 slab->map_ptr = NULL;
901 return;
904 vk_info = context_vk->vk_info;
905 device_vk = wined3d_device_vk(context_vk->c.device);
907 if (bo->memory)
908 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
909 else
910 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
913 static VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
915 VkAccessFlags flags = 0;
917 if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
918 flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
919 if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
920 flags |= VK_ACCESS_INDEX_READ_BIT;
921 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
922 flags |= VK_ACCESS_UNIFORM_READ_BIT;
923 if (usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
924 flags |= VK_ACCESS_SHADER_READ_BIT;
925 if (usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)
926 flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
927 if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
928 flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
930 return flags;
933 static void *adapter_vk_map_bo_address(struct wined3d_context *context,
934 const struct wined3d_bo_address *data, size_t size, uint32_t map_flags)
936 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
937 const struct wined3d_vk_info *vk_info;
938 struct wined3d_bo_user_vk *bo_user_vk;
939 struct wined3d_device_vk *device_vk;
940 VkCommandBuffer vk_command_buffer;
941 VkBufferMemoryBarrier vk_barrier;
942 struct wined3d_bo_vk *bo, tmp;
943 VkMappedMemoryRange range;
944 void *map_ptr;
946 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
947 return data->addr;
949 vk_info = context_vk->vk_info;
950 device_vk = wined3d_device_vk(context->device);
952 if (map_flags & WINED3D_MAP_NOOVERWRITE)
953 goto map;
955 if ((map_flags & WINED3D_MAP_DISCARD) && bo->command_buffer_id > context_vk->completed_command_buffer_id)
957 if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp))
959 list_move_head(&tmp.users, &bo->users);
960 wined3d_context_vk_destroy_bo(context_vk, bo);
961 *bo = tmp;
962 list_init(&bo->users);
963 list_move_head(&bo->users, &tmp.users);
964 LIST_FOR_EACH_ENTRY(bo_user_vk, &bo->users, struct wined3d_bo_user_vk, entry)
966 bo_user_vk->valid = false;
969 goto map;
972 ERR("Failed to create new buffer object.\n");
975 if (map_flags & WINED3D_MAP_READ)
977 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
979 ERR("Failed to get command buffer.\n");
980 return NULL;
983 wined3d_context_vk_end_current_render_pass(context_vk);
985 vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
986 vk_barrier.pNext = NULL;
987 vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage);
988 vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
989 vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
990 vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
991 vk_barrier.buffer = bo->vk_buffer;
992 vk_barrier.offset = bo->buffer_offset + (uintptr_t)data->addr;
993 vk_barrier.size = size;
994 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
995 VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
997 if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
999 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1000 range.pNext = NULL;
1001 range.memory = bo->vk_memory;
1002 range.offset = bo->memory_offset + (uintptr_t)data->addr;
1003 range.size = size;
1004 VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range));
1007 wined3d_context_vk_reference_bo(context_vk, bo);
1010 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
1011 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1012 wined3d_context_vk_wait_command_buffer(context_vk, bo->command_buffer_id);
1014 map:
1015 if (!(map_ptr = wined3d_bo_vk_map(bo, context_vk)))
1017 ERR("Failed to map bo.\n");
1018 return NULL;
1021 return (uint8_t *)map_ptr + bo->memory_offset + (uintptr_t)data->addr;
1024 static void adapter_vk_unmap_bo_address(struct wined3d_context *context,
1025 const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges)
1027 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1028 const struct wined3d_vk_info *vk_info;
1029 struct wined3d_device_vk *device_vk;
1030 VkMappedMemoryRange range;
1031 struct wined3d_bo_vk *bo;
1032 unsigned int i;
1034 if (!(bo = (struct wined3d_bo_vk *)data->buffer_object))
1035 return;
1037 vk_info = context_vk->vk_info;
1038 device_vk = wined3d_device_vk(context->device);
1040 if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
1042 range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1043 range.pNext = NULL;
1044 range.memory = bo->vk_memory;
1046 for (i = 0; i < range_count; ++i)
1048 range.offset = bo->memory_offset + ranges[i].offset;
1049 range.size = ranges[i].size;
1050 VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range));
1054 wined3d_bo_vk_unmap(bo, context_vk);
1057 static void adapter_vk_copy_bo_address(struct wined3d_context *context,
1058 const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size)
1060 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1061 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1062 struct wined3d_bo_vk staging_bo, *src_bo, *dst_bo;
1063 VkAccessFlags src_access_mask, dst_access_mask;
1064 VkBufferMemoryBarrier vk_barrier[2];
1065 struct wined3d_bo_address staging;
1066 VkCommandBuffer vk_command_buffer;
1067 struct wined3d_range range;
1068 void *dst_ptr, *src_ptr;
1069 VkBufferCopy region;
1071 src_bo = (struct wined3d_bo_vk *)src->buffer_object;
1072 dst_bo = (struct wined3d_bo_vk *)dst->buffer_object;
1074 if (src_bo && dst_bo)
1076 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
1078 ERR("Failed to get command buffer.\n");
1079 return;
1082 wined3d_context_vk_end_current_render_pass(context_vk);
1084 src_access_mask = vk_access_mask_from_buffer_usage(src_bo->usage);
1085 dst_access_mask = vk_access_mask_from_buffer_usage(dst_bo->usage);
1087 region.srcOffset = src_bo->buffer_offset + (uintptr_t)src->addr;
1088 region.dstOffset = dst_bo->buffer_offset + (uintptr_t)dst->addr;
1089 region.size = size;
1091 vk_barrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1092 vk_barrier[0].pNext = NULL;
1093 vk_barrier[0].srcAccessMask = src_access_mask;
1094 vk_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1095 vk_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1096 vk_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1097 vk_barrier[0].buffer = src_bo->vk_buffer;
1098 vk_barrier[0].offset = region.srcOffset;
1099 vk_barrier[0].size = region.size;
1101 vk_barrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1102 vk_barrier[1].pNext = NULL;
1103 vk_barrier[1].srcAccessMask = dst_access_mask;
1104 vk_barrier[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1105 vk_barrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1106 vk_barrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1107 vk_barrier[1].buffer = dst_bo->vk_buffer;
1108 vk_barrier[1].offset = region.dstOffset;
1109 vk_barrier[1].size = region.size;
1111 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
1112 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1114 VK_CALL(vkCmdCopyBuffer(vk_command_buffer, src_bo->vk_buffer, dst_bo->vk_buffer, 1, &region));
1116 vk_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1117 vk_barrier[0].dstAccessMask = src_access_mask;
1119 vk_barrier[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1120 vk_barrier[1].dstAccessMask = dst_access_mask;
1122 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1123 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 2, vk_barrier, 0, NULL));
1125 wined3d_context_vk_reference_bo(context_vk, src_bo);
1126 wined3d_context_vk_reference_bo(context_vk, dst_bo);
1128 return;
1131 if (src_bo && !(src_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
1133 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1134 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1136 ERR("Failed to create staging bo.\n");
1137 return;
1140 staging.buffer_object = (uintptr_t)&staging_bo;
1141 staging.addr = NULL;
1142 adapter_vk_copy_bo_address(context, &staging, src, size);
1143 adapter_vk_copy_bo_address(context, dst, &staging, size);
1145 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1147 return;
1150 if (dst_bo && (dst_bo->command_buffer_id > context_vk->completed_command_buffer_id
1151 || !(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)))
1153 if (!(wined3d_context_vk_create_bo(context_vk, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1154 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)))
1156 ERR("Failed to create staging bo.\n");
1157 return;
1160 staging.buffer_object = (uintptr_t)&staging_bo;
1161 staging.addr = NULL;
1162 adapter_vk_copy_bo_address(context, &staging, src, size);
1163 adapter_vk_copy_bo_address(context, dst, &staging, size);
1165 wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
1167 return;
1170 src_ptr = adapter_vk_map_bo_address(context, src, size, WINED3D_MAP_READ);
1171 dst_ptr = adapter_vk_map_bo_address(context, dst, size, WINED3D_MAP_WRITE);
1173 memcpy(dst_ptr, src_ptr, size);
1175 range.offset = 0;
1176 range.size = size;
1177 adapter_vk_unmap_bo_address(context, dst, 1, &range);
1178 adapter_vk_unmap_bo_address(context, src, 0, NULL);
1181 static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
1182 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
1184 struct wined3d_swapchain_vk *swapchain_vk;
1185 HRESULT hr;
1187 TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
1188 device, desc, parent, parent_ops, swapchain);
1190 if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
1191 return E_OUTOFMEMORY;
1193 if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, parent, parent_ops)))
1195 WARN("Failed to initialise swapchain, hr %#x.\n", hr);
1196 heap_free(swapchain_vk);
1197 return hr;
1200 TRACE("Created swapchain %p.\n", swapchain_vk);
1201 *swapchain = &swapchain_vk->s;
1203 return hr;
1206 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
1208 struct wined3d_swapchain_vk *swapchain_vk = wined3d_swapchain_vk(swapchain);
1210 wined3d_swapchain_vk_cleanup(swapchain_vk);
1211 heap_free(swapchain_vk);
1214 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk *adapter_vk,
1215 uint32_t memory_type_mask, VkMemoryPropertyFlags flags)
1217 const VkPhysicalDeviceMemoryProperties *memory_info = &adapter_vk->memory_properties;
1218 unsigned int i;
1220 for (i = 0; i < memory_info->memoryTypeCount; ++i)
1222 if (!(memory_type_mask & (1u << i)))
1223 continue;
1224 if ((memory_info->memoryTypes[i].propertyFlags & flags) == flags)
1225 return i;
1228 return ~0u;
1231 static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
1232 const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
1233 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
1235 struct wined3d_buffer_vk *buffer_vk;
1236 HRESULT hr;
1238 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1239 device, desc, data, parent, parent_ops, buffer);
1241 if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
1242 return E_OUTOFMEMORY;
1244 if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
1246 WARN("Failed to initialise buffer, hr %#x.\n", hr);
1247 heap_free(buffer_vk);
1248 return hr;
1251 TRACE("Created buffer %p.\n", buffer_vk);
1252 *buffer = &buffer_vk->b;
1254 return hr;
1257 static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
1259 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
1260 struct wined3d_device *device = buffer_vk->b.resource.device;
1261 unsigned int swapchain_count = device->swapchain_count;
1263 TRACE("buffer_vk %p.\n", buffer_vk);
1265 /* Take a reference to the device, in case releasing the buffer would
1266 * cause the device to be destroyed. However, swapchain resources don't
1267 * take a reference to the device, and we wouldn't want to increment the
1268 * refcount on a device that's in the process of being destroyed. */
1269 if (swapchain_count)
1270 wined3d_device_incref(device);
1271 wined3d_buffer_cleanup(&buffer_vk->b);
1272 wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
1273 if (swapchain_count)
1274 wined3d_device_decref(device);
1277 static HRESULT adapter_vk_create_texture(struct wined3d_device *device,
1278 const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
1279 uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
1281 struct wined3d_texture_vk *texture_vk;
1282 HRESULT hr;
1284 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
1285 device, desc, layer_count, level_count, flags, parent, parent_ops, texture);
1287 if (!(texture_vk = wined3d_texture_allocate_object_memory(sizeof(*texture_vk), level_count, layer_count)))
1288 return E_OUTOFMEMORY;
1290 if (FAILED(hr = wined3d_texture_vk_init(texture_vk, device, desc,
1291 layer_count, level_count, flags, parent, parent_ops)))
1293 WARN("Failed to initialise texture, hr %#x.\n", hr);
1294 heap_free(texture_vk);
1295 return hr;
1298 TRACE("Created texture %p.\n", texture_vk);
1299 *texture = &texture_vk->t;
1301 return hr;
1304 static void adapter_vk_destroy_texture(struct wined3d_texture *texture)
1306 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture);
1307 struct wined3d_device *device = texture_vk->t.resource.device;
1308 unsigned int swapchain_count = device->swapchain_count;
1310 TRACE("texture_vk %p.\n", texture_vk);
1312 /* Take a reference to the device, in case releasing the texture would
1313 * cause the device to be destroyed. However, swapchain resources don't
1314 * take a reference to the device, and we wouldn't want to increment the
1315 * refcount on a device that's in the process of being destroyed. */
1316 if (swapchain_count)
1317 wined3d_device_incref(device);
1319 wined3d_texture_sub_resources_destroyed(texture);
1320 texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
1322 wined3d_texture_cleanup(&texture_vk->t);
1323 wined3d_cs_destroy_object(device->cs, heap_free, texture_vk);
1325 if (swapchain_count)
1326 wined3d_device_decref(device);
1329 static HRESULT adapter_vk_create_rendertarget_view(const struct wined3d_view_desc *desc,
1330 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1331 struct wined3d_rendertarget_view **view)
1333 struct wined3d_rendertarget_view_vk *view_vk;
1334 HRESULT hr;
1336 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1337 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1339 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1340 return E_OUTOFMEMORY;
1342 if (FAILED(hr = wined3d_rendertarget_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1344 WARN("Failed to initialise view, hr %#x.\n", hr);
1345 heap_free(view_vk);
1346 return hr;
1349 TRACE("Created render target view %p.\n", view_vk);
1350 *view = &view_vk->v;
1352 return hr;
1355 struct wined3d_view_vk_destroy_ctx
1357 struct wined3d_device_vk *device_vk;
1358 VkBufferView *vk_buffer_view;
1359 VkImageView *vk_image_view;
1360 struct wined3d_bo_vk *vk_counter_bo;
1361 VkBufferView *vk_counter_view;
1362 uint64_t *command_buffer_id;
1363 void *object;
1364 struct wined3d_view_vk_destroy_ctx *free;
1367 static void wined3d_view_vk_destroy_object(void *object)
1369 struct wined3d_view_vk_destroy_ctx *ctx = object;
1370 const struct wined3d_vk_info *vk_info;
1371 struct wined3d_device_vk *device_vk;
1372 struct wined3d_context *context;
1374 device_vk = ctx->device_vk;
1375 vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
1376 context = context_acquire(&device_vk->d, NULL, 0);
1378 if (ctx->vk_buffer_view)
1380 if (context)
1382 wined3d_context_vk_destroy_buffer_view(wined3d_context_vk(context),
1383 *ctx->vk_buffer_view, *ctx->command_buffer_id);
1385 else
1387 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_buffer_view, NULL));
1388 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_buffer_view));
1391 if (ctx->vk_image_view)
1393 if (context)
1395 wined3d_context_vk_destroy_image_view(wined3d_context_vk(context),
1396 *ctx->vk_image_view, *ctx->command_buffer_id);
1398 else
1400 VK_CALL(vkDestroyImageView(device_vk->vk_device, *ctx->vk_image_view, NULL));
1401 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_image_view));
1404 if (ctx->vk_counter_bo && ctx->vk_counter_bo->vk_buffer)
1405 wined3d_context_vk_destroy_bo(wined3d_context_vk(context), ctx->vk_counter_bo);
1406 if (ctx->vk_counter_view)
1408 if (context)
1410 wined3d_context_vk_destroy_buffer_view(wined3d_context_vk(context),
1411 *ctx->vk_counter_view, *ctx->command_buffer_id);
1413 else
1415 VK_CALL(vkDestroyBufferView(device_vk->vk_device, *ctx->vk_counter_view, NULL));
1416 TRACE("Destroyed counter buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx->vk_counter_view));
1420 if (context)
1421 context_release(context);
1423 heap_free(ctx->object);
1424 heap_free(ctx->free);
1427 static void wined3d_view_vk_destroy(struct wined3d_device *device, VkBufferView *vk_buffer_view,
1428 VkImageView *vk_image_view, struct wined3d_bo_vk *vk_counter_bo,
1429 VkBufferView *vk_counter_view, uint64_t *command_buffer_id, void *view_vk)
1431 struct wined3d_view_vk_destroy_ctx *ctx, c;
1433 if (!(ctx = heap_alloc(sizeof(*ctx))))
1434 ctx = &c;
1435 ctx->device_vk = wined3d_device_vk(device);
1436 ctx->vk_buffer_view = vk_buffer_view;
1437 ctx->vk_image_view = vk_image_view;
1438 ctx->vk_counter_bo = vk_counter_bo;
1439 ctx->vk_counter_view = vk_counter_view;
1440 ctx->command_buffer_id = command_buffer_id;
1441 ctx->object = view_vk;
1442 ctx->free = ctx != &c ? ctx : NULL;
1444 wined3d_cs_destroy_object(device->cs, wined3d_view_vk_destroy_object, ctx);
1445 if (ctx == &c)
1446 device->cs->ops->finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
1449 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
1451 struct wined3d_rendertarget_view_vk *view_vk = wined3d_rendertarget_view_vk(view);
1452 struct wined3d_device *device = view_vk->v.resource->device;
1453 unsigned int swapchain_count = device->swapchain_count;
1455 TRACE("view_vk %p.\n", view_vk);
1457 /* Take a reference to the device, in case releasing the view's resource
1458 * would cause the device to be destroyed. However, swapchain resources
1459 * don't take a reference to the device, and we wouldn't want to increment
1460 * the refcount on a device that's in the process of being destroyed. */
1461 if (swapchain_count)
1462 wined3d_device_incref(device);
1463 wined3d_rendertarget_view_cleanup(&view_vk->v);
1464 wined3d_view_vk_destroy(device, NULL, &view_vk->vk_image_view,
1465 NULL, NULL, &view_vk->command_buffer_id, view_vk);
1466 if (swapchain_count)
1467 wined3d_device_decref(device);
1470 static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc,
1471 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1472 struct wined3d_shader_resource_view **view)
1474 struct wined3d_shader_resource_view_vk *view_vk;
1475 HRESULT hr;
1477 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1478 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1480 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1481 return E_OUTOFMEMORY;
1483 if (FAILED(hr = wined3d_shader_resource_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1485 WARN("Failed to initialise view, hr %#x.\n", hr);
1486 heap_free(view_vk);
1487 return hr;
1490 TRACE("Created shader resource view %p.\n", view_vk);
1491 *view = &view_vk->v;
1493 return hr;
1496 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
1498 struct wined3d_shader_resource_view_vk *srv_vk = wined3d_shader_resource_view_vk(view);
1499 struct wined3d_device *device = srv_vk->v.resource->device;
1500 unsigned int swapchain_count = device->swapchain_count;
1501 struct wined3d_view_vk *view_vk = &srv_vk->view_vk;
1502 VkBufferView *vk_buffer_view = NULL;
1503 VkImageView *vk_image_view = NULL;
1505 TRACE("srv_vk %p.\n", srv_vk);
1507 /* Take a reference to the device, in case releasing the view's resource
1508 * would cause the device to be destroyed. However, swapchain resources
1509 * don't take a reference to the device, and we wouldn't want to increment
1510 * the refcount on a device that's in the process of being destroyed. */
1511 if (swapchain_count)
1512 wined3d_device_incref(device);
1513 if (srv_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
1514 vk_buffer_view = &view_vk->u.vk_buffer_view;
1515 else
1516 vk_image_view = &view_vk->u.vk_image_info.imageView;
1517 list_remove(&view_vk->bo_user.entry);
1518 wined3d_shader_resource_view_cleanup(&srv_vk->v);
1519 wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view,
1520 NULL, NULL, &view_vk->command_buffer_id, srv_vk);
1521 if (swapchain_count)
1522 wined3d_device_decref(device);
1525 static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc,
1526 struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
1527 struct wined3d_unordered_access_view **view)
1529 struct wined3d_unordered_access_view_vk *view_vk;
1530 HRESULT hr;
1532 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1533 wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);
1535 if (!(view_vk = heap_alloc_zero(sizeof(*view_vk))))
1536 return E_OUTOFMEMORY;
1538 if (FAILED(hr = wined3d_unordered_access_view_vk_init(view_vk, desc, resource, parent, parent_ops)))
1540 WARN("Failed to initialise view, hr %#x.\n", hr);
1541 heap_free(view_vk);
1542 return hr;
1545 TRACE("Created unordered access view %p.\n", view_vk);
1546 *view = &view_vk->v;
1548 return hr;
1551 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
1553 struct wined3d_unordered_access_view_vk *uav_vk = wined3d_unordered_access_view_vk(view);
1554 struct wined3d_device *device = uav_vk->v.resource->device;
1555 unsigned int swapchain_count = device->swapchain_count;
1556 struct wined3d_view_vk *view_vk = &uav_vk->view_vk;
1557 VkBufferView *vk_buffer_view = NULL;
1558 VkImageView *vk_image_view = NULL;
1560 TRACE("uav_vk %p.\n", uav_vk);
1562 /* Take a reference to the device, in case releasing the view's resource
1563 * would cause the device to be destroyed. However, swapchain resources
1564 * don't take a reference to the device, and we wouldn't want to increment
1565 * the refcount on a device that's in the process of being destroyed. */
1566 if (swapchain_count)
1567 wined3d_device_incref(device);
1568 if (uav_vk->v.resource->type == WINED3D_RTYPE_BUFFER)
1569 vk_buffer_view = &view_vk->u.vk_buffer_view;
1570 else
1571 vk_image_view = &view_vk->u.vk_image_info.imageView;
1572 list_remove(&view_vk->bo_user.entry);
1573 wined3d_unordered_access_view_cleanup(&uav_vk->v);
1574 wined3d_view_vk_destroy(device, vk_buffer_view, vk_image_view, &uav_vk->counter_bo,
1575 &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk);
1576 if (swapchain_count)
1577 wined3d_device_decref(device);
1580 static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
1581 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
1583 struct wined3d_sampler_vk *sampler_vk;
1585 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
1586 device, desc, parent, parent_ops, sampler);
1588 if (!(sampler_vk = heap_alloc_zero(sizeof(*sampler_vk))))
1589 return E_OUTOFMEMORY;
1591 wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
1593 TRACE("Created sampler %p.\n", sampler_vk);
1594 *sampler = &sampler_vk->s;
1596 return WINED3D_OK;
1599 static void wined3d_sampler_vk_destroy_object(void *object)
1601 struct wined3d_sampler_vk *sampler_vk = object;
1602 struct wined3d_context_vk *context_vk;
1604 context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
1606 wined3d_context_vk_destroy_sampler(context_vk, sampler_vk->vk_image_info.sampler, sampler_vk->command_buffer_id);
1607 heap_free(sampler_vk);
1609 context_release(&context_vk->c);
1612 static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
1614 struct wined3d_sampler_vk *sampler_vk = wined3d_sampler_vk(sampler);
1616 TRACE("sampler_vk %p.\n", sampler_vk);
1618 wined3d_cs_destroy_object(sampler->device->cs, wined3d_sampler_vk_destroy_object, sampler_vk);
1621 static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
1622 void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
1624 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1625 device, type, parent, parent_ops, query);
1627 return wined3d_query_vk_create(device, type, parent, parent_ops, query);
1630 static void wined3d_query_vk_destroy_object(void *object)
1632 struct wined3d_query_vk *query_vk = object;
1634 query_vk->q.query_ops->query_destroy(&query_vk->q);
1637 static void adapter_vk_destroy_query(struct wined3d_query *query)
1639 struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
1641 TRACE("query_vk %p.\n", query_vk);
1643 wined3d_cs_destroy_object(query->device->cs, wined3d_query_vk_destroy_object, query_vk);
1646 static void adapter_vk_flush_context(struct wined3d_context *context)
1648 struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
1650 TRACE("context_vk %p.\n", context_vk);
1652 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1655 static void adapter_vk_draw_primitive(struct wined3d_device *device,
1656 const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters)
1658 struct wined3d_buffer_vk *indirect_vk = NULL;
1659 const struct wined3d_vk_info *vk_info;
1660 struct wined3d_context_vk *context_vk;
1661 VkCommandBuffer vk_command_buffer;
1662 uint32_t instance_count;
1664 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1666 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1667 vk_info = context_vk->vk_info;
1669 if (parameters->indirect)
1670 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1672 if (!(vk_command_buffer = wined3d_context_vk_apply_draw_state(context_vk,
1673 state, indirect_vk, parameters->indexed)))
1675 ERR("Failed to apply draw state.\n");
1676 context_release(&context_vk->c);
1677 return;
1680 if (parameters->indirect)
1682 struct wined3d_bo_vk *bo = &indirect_vk->bo;
1683 uint32_t stride, size;
1685 wined3d_context_vk_reference_bo(context_vk, bo);
1686 size = indirect_vk->b.resource.size - parameters->u.indirect.offset;
1688 if (parameters->indexed)
1690 stride = sizeof(VkDrawIndexedIndirectCommand);
1691 VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer, bo->vk_buffer,
1692 bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride));
1694 else
1696 stride = sizeof(VkDrawIndirectCommand);
1697 VK_CALL(vkCmdDrawIndirect(vk_command_buffer, bo->vk_buffer,
1698 bo->buffer_offset + parameters->u.indirect.offset, size / stride, stride));
1701 else
1703 instance_count = parameters->u.direct.instance_count;
1704 if (context_vk->c.instance_count)
1705 instance_count = context_vk->c.instance_count;
1706 if (!instance_count)
1707 instance_count = 1;
1709 if (parameters->indexed)
1710 VK_CALL(vkCmdDrawIndexed(vk_command_buffer, parameters->u.direct.index_count,
1711 instance_count, parameters->u.direct.start_idx, parameters->u.direct.base_vertex_idx,
1712 parameters->u.direct.start_instance));
1713 else
1714 VK_CALL(vkCmdDraw(vk_command_buffer, parameters->u.direct.index_count, instance_count,
1715 parameters->u.direct.start_idx, parameters->u.direct.start_instance));
1718 context_release(&context_vk->c);
1721 static void adapter_vk_dispatch_compute(struct wined3d_device *device,
1722 const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters)
1724 struct wined3d_buffer_vk *indirect_vk = NULL;
1725 const struct wined3d_vk_info *vk_info;
1726 struct wined3d_context_vk *context_vk;
1727 VkCommandBuffer vk_command_buffer;
1729 TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
1731 context_vk = wined3d_context_vk(context_acquire(device, NULL, 0));
1732 vk_info = context_vk->vk_info;
1734 if (parameters->indirect)
1735 indirect_vk = wined3d_buffer_vk(parameters->u.indirect.buffer);
1737 if (!(vk_command_buffer = wined3d_context_vk_apply_compute_state(context_vk, state, indirect_vk)))
1739 ERR("Failed to apply compute state.\n");
1740 context_release(&context_vk->c);
1741 return;
1744 if (parameters->indirect)
1746 struct wined3d_bo_vk *bo = &indirect_vk->bo;
1748 wined3d_context_vk_reference_bo(context_vk, bo);
1749 VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer,
1750 bo->buffer_offset + parameters->u.indirect.offset));
1752 else
1754 const struct wined3d_direct_dispatch_parameters *direct = &parameters->u.direct;
1756 VK_CALL(vkCmdDispatch(vk_command_buffer, direct->group_count_x, direct->group_count_y, direct->group_count_z));
1759 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1760 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1762 context_release(&context_vk->c);
1765 void adapter_vk_clear_uav(struct wined3d_context *context,
1766 struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value)
1768 TRACE("context %p, view %p, clear_value %s.\n", context, view, debug_uvec4(clear_value));
1770 wined3d_unordered_access_view_vk_clear_uint(wined3d_unordered_access_view_vk(view),
1771 clear_value, wined3d_context_vk(context));
1774 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
1776 .adapter_destroy = adapter_vk_destroy,
1777 .adapter_create_device = adapter_vk_create_device,
1778 .adapter_destroy_device = adapter_vk_destroy_device,
1779 .adapter_acquire_context = adapter_vk_acquire_context,
1780 .adapter_release_context = adapter_vk_release_context,
1781 .adapter_get_wined3d_caps = adapter_vk_get_wined3d_caps,
1782 .adapter_check_format = adapter_vk_check_format,
1783 .adapter_init_3d = adapter_vk_init_3d,
1784 .adapter_uninit_3d = adapter_vk_uninit_3d,
1785 .adapter_map_bo_address = adapter_vk_map_bo_address,
1786 .adapter_unmap_bo_address = adapter_vk_unmap_bo_address,
1787 .adapter_copy_bo_address = adapter_vk_copy_bo_address,
1788 .adapter_create_swapchain = adapter_vk_create_swapchain,
1789 .adapter_destroy_swapchain = adapter_vk_destroy_swapchain,
1790 .adapter_create_buffer = adapter_vk_create_buffer,
1791 .adapter_destroy_buffer = adapter_vk_destroy_buffer,
1792 .adapter_create_texture = adapter_vk_create_texture,
1793 .adapter_destroy_texture = adapter_vk_destroy_texture,
1794 .adapter_create_rendertarget_view = adapter_vk_create_rendertarget_view,
1795 .adapter_destroy_rendertarget_view = adapter_vk_destroy_rendertarget_view,
1796 .adapter_create_shader_resource_view = adapter_vk_create_shader_resource_view,
1797 .adapter_destroy_shader_resource_view = adapter_vk_destroy_shader_resource_view,
1798 .adapter_create_unordered_access_view = adapter_vk_create_unordered_access_view,
1799 .adapter_destroy_unordered_access_view = adapter_vk_destroy_unordered_access_view,
1800 .adapter_create_sampler = adapter_vk_create_sampler,
1801 .adapter_destroy_sampler = adapter_vk_destroy_sampler,
1802 .adapter_create_query = adapter_vk_create_query,
1803 .adapter_destroy_query = adapter_vk_destroy_query,
1804 .adapter_flush_context = adapter_vk_flush_context,
1805 .adapter_draw_primitive = adapter_vk_draw_primitive,
1806 .adapter_dispatch_compute = adapter_vk_dispatch_compute,
1807 .adapter_clear_uav = adapter_vk_clear_uav,
1810 static unsigned int wined3d_get_wine_vk_version(void)
1812 const char *ptr = PACKAGE_VERSION;
1813 int major, minor;
1815 major = atoi(ptr);
1817 while (isdigit(*ptr))
1818 ++ptr;
1819 if (*ptr == '.')
1820 ++ptr;
1822 minor = atoi(ptr);
1824 return VK_MAKE_VERSION(major, minor, 0);
1827 static const struct
1829 const char *name;
1830 unsigned int core_since_version;
1831 BOOL required;
1833 vulkan_instance_extensions[] =
1835 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_API_VERSION_1_1, FALSE},
1836 {VK_KHR_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1837 {VK_KHR_WIN32_SURFACE_EXTENSION_NAME, ~0u, TRUE},
1840 static BOOL enable_vulkan_instance_extensions(uint32_t *extension_count,
1841 const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
1843 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
1844 VkExtensionProperties *extensions = NULL;
1845 BOOL success = FALSE, found;
1846 unsigned int i, j, count;
1847 VkResult vr;
1849 *extension_count = 0;
1851 if (!(pfn_vkEnumerateInstanceExtensionProperties
1852 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"))))
1854 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
1855 goto done;
1858 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL)) < 0)
1860 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1861 goto done;
1863 if (!(extensions = heap_calloc(count, sizeof(*extensions))))
1865 WARN("Out of memory.\n");
1866 goto done;
1868 if ((vr = pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, extensions)) < 0)
1870 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr));
1871 goto done;
1874 for (i = 0; i < ARRAY_SIZE(vulkan_instance_extensions); ++i)
1876 if (vulkan_instance_extensions[i].core_since_version <= vk_info->api_version)
1877 continue;
1879 for (j = 0, found = FALSE; j < count; ++j)
1881 if (!strcmp(extensions[j].extensionName, vulkan_instance_extensions[i].name))
1883 found = TRUE;
1884 break;
1887 if (found)
1889 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions[i].name);
1890 enabled_extensions[(*extension_count)++] = vulkan_instance_extensions[i].name;
1892 else if (!found && vulkan_instance_extensions[i].required)
1894 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions[i].name);
1895 goto done;
1898 success = TRUE;
1900 done:
1901 heap_free(extensions);
1902 return success;
1905 static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
1907 const char *enabled_instance_extensions[ARRAY_SIZE(vulkan_instance_extensions)];
1908 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
1909 struct vulkan_ops *vk_ops = &vk_info->vk_ops;
1910 VkInstance instance = VK_NULL_HANDLE;
1911 VkInstanceCreateInfo instance_info;
1912 VkApplicationInfo app_info;
1913 uint32_t api_version = 0;
1914 char app_name[MAX_PATH];
1915 VkResult vr;
1917 if (!wined3d_load_vulkan(vk_info))
1918 return FALSE;
1920 if (!(vk_ops->vkCreateInstance = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkCreateInstance"))))
1922 ERR("Failed to get 'vkCreateInstance'.\n");
1923 goto fail;
1926 vk_info->api_version = VK_API_VERSION_1_0;
1927 if ((pfn_vkEnumerateInstanceVersion = (void *)VK_CALL(vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion")))
1928 && pfn_vkEnumerateInstanceVersion(&api_version) == VK_SUCCESS)
1930 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version));
1932 if (api_version >= VK_API_VERSION_1_1)
1933 vk_info->api_version = VK_API_VERSION_1_1;
1936 memset(&app_info, 0, sizeof(app_info));
1937 app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1938 if (wined3d_get_app_name(app_name, ARRAY_SIZE(app_name)))
1939 app_info.pApplicationName = app_name;
1940 app_info.pEngineName = "Damavand";
1941 app_info.engineVersion = wined3d_get_wine_vk_version();
1942 app_info.apiVersion = vk_info->api_version;
1944 memset(&instance_info, 0, sizeof(instance_info));
1945 instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1946 instance_info.pApplicationInfo = &app_info;
1947 instance_info.ppEnabledExtensionNames = enabled_instance_extensions;
1948 if (!enable_vulkan_instance_extensions(&instance_info.enabledExtensionCount, enabled_instance_extensions, vk_info))
1949 goto fail;
1951 memset(vk_info->supported, 0, sizeof(vk_info->supported));
1952 vk_info->supported[WINED3D_VK_EXT_NONE] = TRUE;
1954 if ((vr = VK_CALL(vkCreateInstance(&instance_info, NULL, &instance))) < 0)
1956 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr));
1957 goto fail;
1960 TRACE("Created Vulkan instance %p.\n", instance);
1962 #define LOAD_INSTANCE_PFN(name) \
1963 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
1965 WARN("Could not get instance proc addr for '" #name "'.\n"); \
1966 goto fail; \
1968 #define LOAD_INSTANCE_OPT_PFN(name) \
1969 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
1970 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
1971 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
1972 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
1973 VK_INSTANCE_FUNCS()
1974 VK_DEVICE_FUNCS()
1975 #undef VK_INSTANCE_PFN
1976 #undef VK_INSTANCE_EXT_PFN
1977 #undef VK_DEVICE_PFN
1979 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
1980 if (!vk_ops->core_pfn) \
1981 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
1982 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2KHR)
1983 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2KHR)
1984 #undef MAP_INSTANCE_FUNCTION
1986 vk_info->instance = instance;
1988 return TRUE;
1990 fail:
1991 if (vk_ops->vkDestroyInstance)
1992 VK_CALL(vkDestroyInstance(instance, NULL));
1993 wined3d_unload_vulkan(vk_info);
1994 return FALSE;
1997 static VkPhysicalDevice get_vulkan_physical_device(struct wined3d_vk_info *vk_info)
1999 VkPhysicalDevice physical_devices[1];
2000 uint32_t count;
2001 VkResult vr;
2003 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, NULL))) < 0)
2005 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2006 return VK_NULL_HANDLE;
2008 if (!count)
2010 WARN("No physical device.\n");
2011 return VK_NULL_HANDLE;
2013 if (count > 1)
2015 /* TODO: Create wined3d_adapter for each device. */
2016 FIXME("Multiple physical devices available.\n");
2017 count = 1;
2020 if ((vr = VK_CALL(vkEnumeratePhysicalDevices(vk_info->instance, &count, physical_devices))) < 0)
2022 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr));
2023 return VK_NULL_HANDLE;
2026 return physical_devices[0];
2029 static enum wined3d_display_driver guess_display_driver(enum wined3d_pci_vendor vendor)
2031 switch (vendor)
2033 case HW_VENDOR_AMD: return DRIVER_AMD_RX;
2034 case HW_VENDOR_INTEL: return DRIVER_INTEL_HD4000;
2035 case HW_VENDOR_NVIDIA: return DRIVER_NVIDIA_GEFORCE8;
2036 default: return DRIVER_WINE;
2040 static void adapter_vk_init_driver_info(struct wined3d_adapter_vk *adapter_vk,
2041 const VkPhysicalDeviceProperties *properties)
2043 const VkPhysicalDeviceMemoryProperties *memory_properties = &adapter_vk->memory_properties;
2044 const struct wined3d_gpu_description *gpu_description;
2045 struct wined3d_gpu_description description;
2046 UINT64 vram_bytes, sysmem_bytes;
2047 const VkMemoryHeap *heap;
2048 unsigned int i;
2050 TRACE("Device name: %s.\n", debugstr_a(properties->deviceName));
2051 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties->vendorID, properties->deviceID);
2052 TRACE("Driver version: %#x.\n", properties->driverVersion);
2053 TRACE("API version: %s.\n", debug_vk_version(properties->apiVersion));
2055 for (i = 0, vram_bytes = 0, sysmem_bytes = 0; i < memory_properties->memoryHeapCount; ++i)
2057 heap = &memory_properties->memoryHeaps[i];
2058 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
2059 i, heap->flags, wine_dbgstr_longlong(heap->size));
2060 if (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
2061 vram_bytes += heap->size;
2062 else
2063 sysmem_bytes += heap->size;
2065 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes));
2066 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes));
2068 if (!(gpu_description = wined3d_get_user_override_gpu_description(properties->vendorID, properties->deviceID)))
2069 gpu_description = wined3d_get_gpu_description(properties->vendorID, properties->deviceID);
2071 if (!gpu_description)
2073 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
2074 debugstr_a(properties->deviceName), properties->vendorID, properties->deviceID);
2076 description.vendor = properties->vendorID;
2077 description.device = properties->deviceID;
2078 description.description = properties->deviceName;
2079 description.driver = guess_display_driver(properties->vendorID);
2080 description.vidmem = vram_bytes;
2082 gpu_description = &description;
2085 wined3d_driver_info_init(&adapter_vk->a.driver_info, gpu_description, vram_bytes, sysmem_bytes);
2088 static enum wined3d_feature_level feature_level_from_caps(const struct shader_caps *shader_caps)
2090 unsigned int shader_model;
2092 shader_model = min(shader_caps->vs_version, shader_caps->ps_version);
2093 shader_model = min(shader_model, max(shader_caps->gs_version, 3));
2094 shader_model = min(shader_model, max(shader_caps->hs_version, 4));
2095 shader_model = min(shader_model, max(shader_caps->ds_version, 4));
2097 if (shader_model >= 5)
2098 return WINED3D_FEATURE_LEVEL_11_1;
2100 if (shader_model >= 4)
2101 return WINED3D_FEATURE_LEVEL_10_1;
2103 return WINED3D_FEATURE_LEVEL_NONE;
2106 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_vk, uint32_t wined3d_creation_flags)
2108 struct wined3d_d3d_info *d3d_info = &adapter_vk->a.d3d_info;
2109 struct wined3d_vertex_caps vertex_caps;
2110 struct fragment_caps fragment_caps;
2111 struct shader_caps shader_caps;
2113 adapter_vk->a.shader_backend->shader_get_caps(&adapter_vk->a, &shader_caps);
2114 adapter_vk->a.vertex_pipe->vp_get_caps(&adapter_vk->a, &vertex_caps);
2115 adapter_vk->a.fragment_pipe->get_caps(&adapter_vk->a, &fragment_caps);
2117 d3d_info->limits.vs_version = shader_caps.vs_version;
2118 d3d_info->limits.hs_version = shader_caps.hs_version;
2119 d3d_info->limits.ds_version = shader_caps.ds_version;
2120 d3d_info->limits.gs_version = shader_caps.gs_version;
2121 d3d_info->limits.ps_version = shader_caps.ps_version;
2122 d3d_info->limits.cs_version = shader_caps.cs_version;
2123 d3d_info->limits.vs_uniform_count = shader_caps.vs_uniform_count;
2124 d3d_info->limits.ps_uniform_count = shader_caps.ps_uniform_count;
2125 d3d_info->limits.varying_count = shader_caps.varying_count;
2126 d3d_info->limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
2127 d3d_info->limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
2128 d3d_info->limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices;
2129 d3d_info->limits.active_light_count = vertex_caps.max_active_lights;
2131 d3d_info->limits.max_rt_count = WINED3D_MAX_RENDER_TARGETS;
2132 d3d_info->limits.max_clip_distances = WINED3D_MAX_CLIP_DISTANCES;
2133 d3d_info->limits.texture_size = adapter_vk->device_limits.maxImageDimension2D;
2134 d3d_info->limits.pointsize_max = adapter_vk->device_limits.pointSizeRange[1];
2136 d3d_info->wined3d_creation_flags = wined3d_creation_flags;
2138 d3d_info->xyzrhw = vertex_caps.xyzrhw;
2139 d3d_info->emulated_flatshading = vertex_caps.emulated_flatshading;
2140 d3d_info->ffp_generic_attributes = vertex_caps.ffp_generic_attributes;
2141 d3d_info->ffp_alpha_test = false;
2142 d3d_info->vs_clipping = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING);
2143 d3d_info->shader_color_key = !!(fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY);
2144 d3d_info->shader_double_precision = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_DOUBLE_PRECISION);
2145 d3d_info->shader_output_interpolation = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION);
2146 d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */
2147 d3d_info->texture_npot = true;
2148 d3d_info->texture_npot_conditional = true;
2149 d3d_info->draw_base_vertex_offset = true;
2150 d3d_info->vertex_bgra = true;
2151 d3d_info->texture_swizzle = true;
2152 d3d_info->srgb_read_control = false;
2153 d3d_info->srgb_write_control = false;
2154 d3d_info->clip_control = true;
2155 d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS);
2156 d3d_info->scaled_resolve = false;
2157 d3d_info->feature_level = feature_level_from_caps(&shader_caps);
2159 d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
2162 static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
2163 unsigned int ordinal, unsigned int wined3d_creation_flags)
2165 struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
2166 struct wined3d_adapter *adapter = &adapter_vk->a;
2167 VkPhysicalDeviceIDProperties id_properties;
2168 VkPhysicalDeviceProperties2 properties2;
2170 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
2171 adapter_vk, ordinal, wined3d_creation_flags);
2173 if (!wined3d_adapter_init(adapter, ordinal, &wined3d_adapter_vk_ops))
2174 return FALSE;
2176 if (!wined3d_init_vulkan(vk_info))
2178 WARN("Failed to initialize Vulkan.\n");
2179 goto fail;
2182 if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
2183 goto fail_vulkan;
2185 memset(&id_properties, 0, sizeof(id_properties));
2186 id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
2187 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2188 properties2.pNext = &id_properties;
2190 if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2)
2191 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2));
2192 else
2193 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk->physical_device, &properties2.properties));
2194 adapter_vk->device_limits = properties2.properties.limits;
2196 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk->physical_device, &adapter_vk->memory_properties));
2198 adapter_vk_init_driver_info(adapter_vk, &properties2.properties);
2199 adapter->vram_bytes_used = 0;
2200 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));
2202 memcpy(&adapter->driver_uuid, id_properties.driverUUID, sizeof(adapter->driver_uuid));
2203 memcpy(&adapter->device_uuid, id_properties.deviceUUID, sizeof(adapter->device_uuid));
2205 if (!wined3d_adapter_vk_init_format_info(adapter_vk, vk_info))
2206 goto fail_vulkan;
2208 adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk();
2209 adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk();
2210 adapter->misc_state_template = misc_state_template_vk;
2211 adapter->shader_backend = wined3d_spirv_shader_backend_init_vk();
2213 wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
2215 return TRUE;
2217 fail_vulkan:
2218 VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
2219 wined3d_unload_vulkan(vk_info);
2220 fail:
2221 wined3d_adapter_cleanup(adapter);
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;