Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/Draw.cpp
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2012-2021 VMware, Inc.
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
* USE OR OTHER DEALINGS IN THE SOFTWARE.
21
*
22
* The above copyright notice and this permission notice (including the
23
* next paragraph) shall be included in all copies or substantial portions
24
* of the Software.
25
*
26
**************************************************************************/
27
28
/*
29
* Draw.h --
30
* Functions that render 3D primitives.
31
*/
32
33
34
#include "Draw.h"
35
#include "State.h"
36
#include "Shader.h"
37
38
#include "Debug.h"
39
40
#include "util/u_draw.h"
41
#include "util/u_memory.h"
42
43
static unsigned
44
ClampedUAdd(unsigned a,
45
unsigned b)
46
{
47
unsigned c = a + b;
48
if (c < a) {
49
return 0xffffffff;
50
}
51
return c;
52
}
53
54
55
/*
56
* We have to resolve the stream output state for empty geometry shaders.
57
* In particular we've remapped the output indices when translating the
58
* shaders so now the register_index variables in the stream output
59
* state are incorrect and we need to remap them back to the correct
60
* state.
61
*/
62
static void
63
ResolveState(Device *pDevice)
64
{
65
if (pDevice->bound_empty_gs && pDevice->bound_vs &&
66
pDevice->bound_vs->state.tokens) {
67
Shader *gs = pDevice->bound_empty_gs;
68
Shader *vs = pDevice->bound_vs;
69
boolean remapped = FALSE;
70
struct pipe_context *pipe = pDevice->pipe;
71
if (!gs->output_resolved) {
72
for (unsigned i = 0; i < gs->state.stream_output.num_outputs; ++i) {
73
unsigned mapping =
74
ShaderFindOutputMapping(vs, gs->state.stream_output.output[i].register_index);
75
if (mapping != gs->state.stream_output.output[i].register_index) {
76
gs->state.stream_output.output[i].register_index = mapping;
77
remapped = TRUE;
78
}
79
}
80
if (remapped) {
81
pipe->delete_gs_state(pipe, gs->handle);
82
gs->handle = pipe->create_gs_state(pipe, &gs->state);
83
}
84
gs->output_resolved = TRUE;
85
}
86
pipe->bind_gs_state(pipe, gs->handle);
87
}
88
}
89
90
91
static struct pipe_resource *
92
create_null_index_buffer(struct pipe_context *ctx, uint num_indices,
93
unsigned *restart_index, unsigned *index_size,
94
unsigned *ib_offset)
95
{
96
unsigned buf_size = num_indices * sizeof(unsigned);
97
unsigned *buf = (unsigned*)MALLOC(buf_size);
98
struct pipe_resource *ibuf;
99
100
memset(buf, 0, buf_size);
101
102
ibuf = pipe_buffer_create_with_data(ctx,
103
PIPE_BIND_INDEX_BUFFER,
104
PIPE_USAGE_IMMUTABLE,
105
buf_size, buf);
106
*index_size = 4;
107
*restart_index = 0xffffffff;
108
*ib_offset = 0;
109
110
FREE(buf);
111
112
return ibuf;
113
}
114
115
/*
116
* ----------------------------------------------------------------------
117
*
118
* Draw --
119
*
120
* The Draw function draws nonindexed primitives.
121
*
122
* ----------------------------------------------------------------------
123
*/
124
125
void APIENTRY
126
Draw(D3D10DDI_HDEVICE hDevice, // IN
127
UINT VertexCount, // IN
128
UINT StartVertexLocation) // IN
129
{
130
LOG_ENTRYPOINT();
131
132
Device *pDevice = CastDevice(hDevice);
133
134
ResolveState(pDevice);
135
136
assert(pDevice->primitive < PIPE_PRIM_MAX);
137
util_draw_arrays(pDevice->pipe,
138
pDevice->primitive,
139
StartVertexLocation,
140
VertexCount);
141
}
142
143
144
/*
145
* ----------------------------------------------------------------------
146
*
147
* DrawIndexed --
148
*
149
* The DrawIndexed function draws indexed primitives.
150
*
151
* ----------------------------------------------------------------------
152
*/
153
154
void APIENTRY
155
DrawIndexed(D3D10DDI_HDEVICE hDevice, // IN
156
UINT IndexCount, // IN
157
UINT StartIndexLocation, // IN
158
INT BaseVertexLocation) // IN
159
{
160
LOG_ENTRYPOINT();
161
162
Device *pDevice = CastDevice(hDevice);
163
struct pipe_draw_info info;
164
struct pipe_draw_start_count_bias draw;
165
struct pipe_resource *null_ib = NULL;
166
unsigned restart_index = pDevice->restart_index;
167
unsigned index_size = pDevice->index_size;
168
unsigned ib_offset = pDevice->ib_offset;
169
170
assert(pDevice->primitive < PIPE_PRIM_MAX);
171
172
/* XXX I don't think draw still needs this? */
173
if (!pDevice->index_buffer) {
174
null_ib =
175
create_null_index_buffer(pDevice->pipe,
176
StartIndexLocation + IndexCount,
177
&restart_index, &index_size, &ib_offset);
178
}
179
180
ResolveState(pDevice);
181
182
util_draw_init_info(&info);
183
info.index_size = index_size;
184
info.mode = pDevice->primitive;
185
draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size);
186
draw.count = IndexCount;
187
info.index.resource = null_ib ? null_ib : pDevice->index_buffer;
188
draw.index_bias = BaseVertexLocation;
189
info.primitive_restart = TRUE;
190
info.restart_index = restart_index;
191
192
pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1);
193
194
if (null_ib) {
195
pipe_resource_reference(&null_ib, NULL);
196
}
197
}
198
199
200
/*
201
* ----------------------------------------------------------------------
202
*
203
* DrawInstanced --
204
*
205
* The DrawInstanced function draws particular instances
206
* of nonindexed primitives.
207
*
208
* ----------------------------------------------------------------------
209
*/
210
211
void APIENTRY
212
DrawInstanced(D3D10DDI_HDEVICE hDevice, // IN
213
UINT VertexCountPerInstance, // IN
214
UINT InstanceCount, // IN
215
UINT StartVertexLocation, // IN
216
UINT StartInstanceLocation) // IN
217
{
218
LOG_ENTRYPOINT();
219
220
Device *pDevice = CastDevice(hDevice);
221
222
if (!InstanceCount) {
223
return;
224
}
225
226
ResolveState(pDevice);
227
228
assert(pDevice->primitive < PIPE_PRIM_MAX);
229
util_draw_arrays_instanced(pDevice->pipe,
230
pDevice->primitive,
231
StartVertexLocation,
232
VertexCountPerInstance,
233
StartInstanceLocation,
234
InstanceCount);
235
}
236
237
238
/*
239
* ----------------------------------------------------------------------
240
*
241
* DrawIndexedInstanced --
242
*
243
* The DrawIndexedInstanced function draws particular
244
* instances of indexed primitives.
245
*
246
* ----------------------------------------------------------------------
247
*/
248
249
void APIENTRY
250
DrawIndexedInstanced(D3D10DDI_HDEVICE hDevice, // IN
251
UINT IndexCountPerInstance, // IN
252
UINT InstanceCount, // IN
253
UINT StartIndexLocation, // IN
254
INT BaseVertexLocation, // IN
255
UINT StartInstanceLocation) // IN
256
{
257
LOG_ENTRYPOINT();
258
259
Device *pDevice = CastDevice(hDevice);
260
struct pipe_draw_info info;
261
struct pipe_draw_start_count_bias draw;
262
struct pipe_resource *null_ib = NULL;
263
unsigned restart_index = pDevice->restart_index;
264
unsigned index_size = pDevice->index_size;
265
unsigned ib_offset = pDevice->ib_offset;
266
267
assert(pDevice->primitive < PIPE_PRIM_MAX);
268
269
if (!InstanceCount) {
270
return;
271
}
272
273
/* XXX I don't think draw still needs this? */
274
if (!pDevice->index_buffer) {
275
null_ib =
276
create_null_index_buffer(pDevice->pipe,
277
StartIndexLocation + IndexCountPerInstance,
278
&restart_index, &index_size, &ib_offset);
279
}
280
281
ResolveState(pDevice);
282
283
util_draw_init_info(&info);
284
info.index_size = index_size;
285
info.mode = pDevice->primitive;
286
draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size);
287
draw.count = IndexCountPerInstance;
288
info.index.resource = null_ib ? null_ib : pDevice->index_buffer;
289
draw.index_bias = BaseVertexLocation;
290
info.start_instance = StartInstanceLocation;
291
info.instance_count = InstanceCount;
292
info.primitive_restart = TRUE;
293
info.restart_index = restart_index;
294
295
pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1);
296
297
if (null_ib) {
298
pipe_resource_reference(&null_ib, NULL);
299
}
300
}
301
302
303
/*
304
* ----------------------------------------------------------------------
305
*
306
* DrawAuto --
307
*
308
* The DrawAuto function works similarly to the Draw function,
309
* except DrawAuto is used for the special case where vertex
310
* data is written through the stream-output unit and then
311
* recycled as a vertex buffer. The driver determines the number
312
* of primitives, in part, by how much data was written to the
313
* buffer through stream output.
314
*
315
* ----------------------------------------------------------------------
316
*/
317
318
void APIENTRY
319
DrawAuto(D3D10DDI_HDEVICE hDevice) // IN
320
{
321
LOG_ENTRYPOINT();
322
323
Device *pDevice = CastDevice(hDevice);
324
struct pipe_draw_info info;
325
struct pipe_draw_indirect_info indirect;
326
327
328
if (!pDevice->draw_so_target) {
329
LOG_UNSUPPORTED("DrawAuto without a set source buffer!");
330
return;
331
}
332
333
assert(pDevice->primitive < PIPE_PRIM_MAX);
334
335
ResolveState(pDevice);
336
337
util_draw_init_info(&info);
338
info.mode = pDevice->primitive;
339
memset(&indirect, 0, sizeof indirect);
340
indirect.count_from_stream_output = pDevice->draw_so_target;
341
342
pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, &indirect, NULL, 1);
343
}
344
345