2 * Copyright 2013 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
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
25 #define WINED3D_INITIAL_CS_SIZE 4096
30 WINED3D_CS_OP_PRESENT
,
32 WINED3D_CS_OP_DISPATCH
,
35 WINED3D_CS_OP_SET_PREDICATION
,
36 WINED3D_CS_OP_SET_VIEWPORTS
,
37 WINED3D_CS_OP_SET_SCISSOR_RECTS
,
38 WINED3D_CS_OP_SET_RENDERTARGET_VIEW
,
39 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
,
40 WINED3D_CS_OP_SET_VERTEX_DECLARATION
,
41 WINED3D_CS_OP_SET_STREAM_SOURCE
,
42 WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
,
43 WINED3D_CS_OP_SET_STREAM_OUTPUT
,
44 WINED3D_CS_OP_SET_INDEX_BUFFER
,
45 WINED3D_CS_OP_SET_CONSTANT_BUFFER
,
46 WINED3D_CS_OP_SET_TEXTURE
,
47 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
,
48 WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW
,
49 WINED3D_CS_OP_SET_SAMPLER
,
50 WINED3D_CS_OP_SET_SHADER
,
51 WINED3D_CS_OP_SET_BLEND_STATE
,
52 WINED3D_CS_OP_SET_RASTERIZER_STATE
,
53 WINED3D_CS_OP_SET_RENDER_STATE
,
54 WINED3D_CS_OP_SET_TEXTURE_STATE
,
55 WINED3D_CS_OP_SET_SAMPLER_STATE
,
56 WINED3D_CS_OP_SET_TRANSFORM
,
57 WINED3D_CS_OP_SET_CLIP_PLANE
,
58 WINED3D_CS_OP_SET_COLOR_KEY
,
59 WINED3D_CS_OP_SET_MATERIAL
,
60 WINED3D_CS_OP_SET_LIGHT
,
61 WINED3D_CS_OP_SET_LIGHT_ENABLE
,
62 WINED3D_CS_OP_PUSH_CONSTANTS
,
63 WINED3D_CS_OP_RESET_STATE
,
64 WINED3D_CS_OP_CALLBACK
,
65 WINED3D_CS_OP_QUERY_ISSUE
,
66 WINED3D_CS_OP_PRELOAD_RESOURCE
,
67 WINED3D_CS_OP_UNLOAD_RESOURCE
,
70 WINED3D_CS_OP_BLT_SUB_RESOURCE
,
71 WINED3D_CS_OP_UPDATE_SUB_RESOURCE
,
72 WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
,
73 WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
,
74 WINED3D_CS_OP_COPY_UAV_COUNTER
,
75 WINED3D_CS_OP_GENERATE_MIPMAPS
,
79 struct wined3d_cs_packet
87 enum wined3d_cs_op opcode
;
90 struct wined3d_cs_present
92 enum wined3d_cs_op opcode
;
93 HWND dst_window_override
;
94 struct wined3d_swapchain
*swapchain
;
97 unsigned int swap_interval
;
101 struct wined3d_cs_clear
103 enum wined3d_cs_op opcode
;
105 unsigned int rt_count
;
106 struct wined3d_fb_state
*fb
;
108 struct wined3d_color color
;
111 unsigned int rect_count
;
115 struct wined3d_cs_dispatch
117 enum wined3d_cs_op opcode
;
118 struct wined3d_dispatch_parameters parameters
;
121 struct wined3d_cs_draw
123 enum wined3d_cs_op opcode
;
124 GLenum primitive_type
;
125 GLint patch_vertex_count
;
126 struct wined3d_draw_parameters parameters
;
129 struct wined3d_cs_flush
131 enum wined3d_cs_op opcode
;
134 struct wined3d_cs_set_predication
136 enum wined3d_cs_op opcode
;
137 struct wined3d_query
*predicate
;
141 struct wined3d_cs_set_viewports
143 enum wined3d_cs_op opcode
;
144 unsigned int viewport_count
;
145 struct wined3d_viewport viewports
[1];
148 struct wined3d_cs_set_scissor_rects
150 enum wined3d_cs_op opcode
;
151 unsigned int rect_count
;
155 struct wined3d_cs_set_rendertarget_view
157 enum wined3d_cs_op opcode
;
158 unsigned int view_idx
;
159 struct wined3d_rendertarget_view
*view
;
162 struct wined3d_cs_set_depth_stencil_view
164 enum wined3d_cs_op opcode
;
165 struct wined3d_rendertarget_view
*view
;
168 struct wined3d_cs_set_vertex_declaration
170 enum wined3d_cs_op opcode
;
171 struct wined3d_vertex_declaration
*declaration
;
174 struct wined3d_cs_set_stream_source
176 enum wined3d_cs_op opcode
;
178 struct wined3d_buffer
*buffer
;
183 struct wined3d_cs_set_stream_source_freq
185 enum wined3d_cs_op opcode
;
191 struct wined3d_cs_set_stream_output
193 enum wined3d_cs_op opcode
;
195 struct wined3d_buffer
*buffer
;
199 struct wined3d_cs_set_index_buffer
201 enum wined3d_cs_op opcode
;
202 struct wined3d_buffer
*buffer
;
203 enum wined3d_format_id format_id
;
207 struct wined3d_cs_set_constant_buffer
209 enum wined3d_cs_op opcode
;
210 enum wined3d_shader_type type
;
212 struct wined3d_buffer
*buffer
;
215 struct wined3d_cs_set_texture
217 enum wined3d_cs_op opcode
;
219 struct wined3d_texture
*texture
;
222 struct wined3d_cs_set_color_key
224 enum wined3d_cs_op opcode
;
225 struct wined3d_texture
*texture
;
228 struct wined3d_color_key color_key
;
231 struct wined3d_cs_set_shader_resource_view
233 enum wined3d_cs_op opcode
;
234 enum wined3d_shader_type type
;
236 struct wined3d_shader_resource_view
*view
;
239 struct wined3d_cs_set_unordered_access_view
241 enum wined3d_cs_op opcode
;
242 enum wined3d_pipeline pipeline
;
243 unsigned int view_idx
;
244 struct wined3d_unordered_access_view
*view
;
245 unsigned int initial_count
;
248 struct wined3d_cs_set_sampler
250 enum wined3d_cs_op opcode
;
251 enum wined3d_shader_type type
;
253 struct wined3d_sampler
*sampler
;
256 struct wined3d_cs_set_shader
258 enum wined3d_cs_op opcode
;
259 enum wined3d_shader_type type
;
260 struct wined3d_shader
*shader
;
263 struct wined3d_cs_set_blend_state
265 enum wined3d_cs_op opcode
;
266 struct wined3d_blend_state
*state
;
267 struct wined3d_color factor
;
270 struct wined3d_cs_set_rasterizer_state
272 enum wined3d_cs_op opcode
;
273 struct wined3d_rasterizer_state
*state
;
276 struct wined3d_cs_set_render_state
278 enum wined3d_cs_op opcode
;
279 enum wined3d_render_state state
;
283 struct wined3d_cs_set_texture_state
285 enum wined3d_cs_op opcode
;
287 enum wined3d_texture_stage_state state
;
291 struct wined3d_cs_set_sampler_state
293 enum wined3d_cs_op opcode
;
295 enum wined3d_sampler_state state
;
299 struct wined3d_cs_set_transform
301 enum wined3d_cs_op opcode
;
302 enum wined3d_transform_state state
;
303 struct wined3d_matrix matrix
;
306 struct wined3d_cs_set_clip_plane
308 enum wined3d_cs_op opcode
;
310 struct wined3d_vec4 plane
;
313 struct wined3d_cs_set_material
315 enum wined3d_cs_op opcode
;
316 struct wined3d_material material
;
319 struct wined3d_cs_set_light
321 enum wined3d_cs_op opcode
;
322 struct wined3d_light_info light
;
325 struct wined3d_cs_set_light_enable
327 enum wined3d_cs_op opcode
;
332 struct wined3d_cs_push_constants
334 enum wined3d_cs_op opcode
;
335 enum wined3d_push_constants type
;
336 unsigned int start_idx
;
341 struct wined3d_cs_reset_state
343 enum wined3d_cs_op opcode
;
346 struct wined3d_cs_callback
348 enum wined3d_cs_op opcode
;
349 void (*callback
)(void *object
);
353 struct wined3d_cs_query_issue
355 enum wined3d_cs_op opcode
;
356 struct wined3d_query
*query
;
360 struct wined3d_cs_preload_resource
362 enum wined3d_cs_op opcode
;
363 struct wined3d_resource
*resource
;
366 struct wined3d_cs_unload_resource
368 enum wined3d_cs_op opcode
;
369 struct wined3d_resource
*resource
;
372 struct wined3d_cs_map
374 enum wined3d_cs_op opcode
;
375 struct wined3d_resource
*resource
;
376 unsigned int sub_resource_idx
;
377 struct wined3d_map_desc
*map_desc
;
378 const struct wined3d_box
*box
;
383 struct wined3d_cs_unmap
385 enum wined3d_cs_op opcode
;
386 struct wined3d_resource
*resource
;
387 unsigned int sub_resource_idx
;
391 struct wined3d_cs_blt_sub_resource
393 enum wined3d_cs_op opcode
;
394 struct wined3d_resource
*dst_resource
;
395 unsigned int dst_sub_resource_idx
;
396 struct wined3d_box dst_box
;
397 struct wined3d_resource
*src_resource
;
398 unsigned int src_sub_resource_idx
;
399 struct wined3d_box src_box
;
401 struct wined3d_blt_fx fx
;
402 enum wined3d_texture_filter_type filter
;
405 struct wined3d_cs_update_sub_resource
407 enum wined3d_cs_op opcode
;
408 struct wined3d_resource
*resource
;
409 unsigned int sub_resource_idx
;
410 struct wined3d_box box
;
411 struct wined3d_sub_resource_data data
;
414 struct wined3d_cs_add_dirty_texture_region
416 enum wined3d_cs_op opcode
;
417 struct wined3d_texture
*texture
;
421 struct wined3d_cs_clear_unordered_access_view
423 enum wined3d_cs_op opcode
;
424 struct wined3d_unordered_access_view
*view
;
425 struct wined3d_uvec4 clear_value
;
428 struct wined3d_cs_copy_uav_counter
430 enum wined3d_cs_op opcode
;
431 struct wined3d_buffer
*buffer
;
433 struct wined3d_unordered_access_view
*view
;
436 struct wined3d_cs_generate_mipmaps
438 enum wined3d_cs_op opcode
;
439 struct wined3d_shader_resource_view
*view
;
442 struct wined3d_cs_stop
444 enum wined3d_cs_op opcode
;
447 static inline void *wined3d_cs_require_space(struct wined3d_cs
*cs
,
448 size_t size
, enum wined3d_cs_queue_id queue_id
)
450 return cs
->ops
->require_space(cs
, size
, queue_id
);
453 static inline void wined3d_cs_submit(struct wined3d_cs
*cs
, enum wined3d_cs_queue_id queue_id
)
455 cs
->ops
->submit(cs
, queue_id
);
458 static const char *debug_cs_op(enum wined3d_cs_op op
)
462 #define WINED3D_TO_STR(type) case type: return #type
463 WINED3D_TO_STR(WINED3D_CS_OP_NOP
);
464 WINED3D_TO_STR(WINED3D_CS_OP_PRESENT
);
465 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR
);
466 WINED3D_TO_STR(WINED3D_CS_OP_DISPATCH
);
467 WINED3D_TO_STR(WINED3D_CS_OP_DRAW
);
468 WINED3D_TO_STR(WINED3D_CS_OP_FLUSH
);
469 WINED3D_TO_STR(WINED3D_CS_OP_SET_PREDICATION
);
470 WINED3D_TO_STR(WINED3D_CS_OP_SET_VIEWPORTS
);
471 WINED3D_TO_STR(WINED3D_CS_OP_SET_SCISSOR_RECTS
);
472 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEW
);
473 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
);
474 WINED3D_TO_STR(WINED3D_CS_OP_SET_VERTEX_DECLARATION
);
475 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCE
);
476 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
);
477 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_OUTPUT
);
478 WINED3D_TO_STR(WINED3D_CS_OP_SET_INDEX_BUFFER
);
479 WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFER
);
480 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE
);
481 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
);
482 WINED3D_TO_STR(WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW
);
483 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLER
);
484 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER
);
485 WINED3D_TO_STR(WINED3D_CS_OP_SET_BLEND_STATE
);
486 WINED3D_TO_STR(WINED3D_CS_OP_SET_RASTERIZER_STATE
);
487 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDER_STATE
);
488 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE_STATE
);
489 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLER_STATE
);
490 WINED3D_TO_STR(WINED3D_CS_OP_SET_TRANSFORM
);
491 WINED3D_TO_STR(WINED3D_CS_OP_SET_CLIP_PLANE
);
492 WINED3D_TO_STR(WINED3D_CS_OP_SET_COLOR_KEY
);
493 WINED3D_TO_STR(WINED3D_CS_OP_SET_MATERIAL
);
494 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT
);
495 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT_ENABLE
);
496 WINED3D_TO_STR(WINED3D_CS_OP_PUSH_CONSTANTS
);
497 WINED3D_TO_STR(WINED3D_CS_OP_RESET_STATE
);
498 WINED3D_TO_STR(WINED3D_CS_OP_CALLBACK
);
499 WINED3D_TO_STR(WINED3D_CS_OP_QUERY_ISSUE
);
500 WINED3D_TO_STR(WINED3D_CS_OP_PRELOAD_RESOURCE
);
501 WINED3D_TO_STR(WINED3D_CS_OP_UNLOAD_RESOURCE
);
502 WINED3D_TO_STR(WINED3D_CS_OP_MAP
);
503 WINED3D_TO_STR(WINED3D_CS_OP_UNMAP
);
504 WINED3D_TO_STR(WINED3D_CS_OP_BLT_SUB_RESOURCE
);
505 WINED3D_TO_STR(WINED3D_CS_OP_UPDATE_SUB_RESOURCE
);
506 WINED3D_TO_STR(WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
);
507 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
);
508 WINED3D_TO_STR(WINED3D_CS_OP_COPY_UAV_COUNTER
);
509 WINED3D_TO_STR(WINED3D_CS_OP_GENERATE_MIPMAPS
);
510 WINED3D_TO_STR(WINED3D_CS_OP_STOP
);
511 #undef WINED3D_TO_STR
513 return wine_dbg_sprintf("UNKNOWN_OP(%#x)", op
);
517 static void wined3d_cs_exec_nop(struct wined3d_cs
*cs
, const void *data
)
521 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
523 const struct wined3d_cs_present
*op
= data
;
524 struct wined3d_swapchain
*swapchain
;
527 swapchain
= op
->swapchain
;
528 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
530 swapchain
->swapchain_ops
->swapchain_present(swapchain
, &op
->src_rect
, &op
->dst_rect
, op
->swap_interval
, op
->flags
);
532 wined3d_resource_release(&swapchain
->front_buffer
->resource
);
533 for (i
= 0; i
< swapchain
->state
.desc
.backbuffer_count
; ++i
)
535 wined3d_resource_release(&swapchain
->back_buffers
[i
]->resource
);
538 InterlockedDecrement(&cs
->pending_presents
);
541 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
542 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
,
543 unsigned int swap_interval
, DWORD flags
)
545 struct wined3d_cs_present
*op
;
549 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
550 op
->opcode
= WINED3D_CS_OP_PRESENT
;
551 op
->dst_window_override
= dst_window_override
;
552 op
->swapchain
= swapchain
;
553 op
->src_rect
= *src_rect
;
554 op
->dst_rect
= *dst_rect
;
555 op
->swap_interval
= swap_interval
;
558 pending
= InterlockedIncrement(&cs
->pending_presents
);
560 wined3d_resource_acquire(&swapchain
->front_buffer
->resource
);
561 for (i
= 0; i
< swapchain
->state
.desc
.backbuffer_count
; ++i
)
563 wined3d_resource_acquire(&swapchain
->back_buffers
[i
]->resource
);
566 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
568 /* Limit input latency by limiting the number of presents that we can get
569 * ahead of the worker thread. */
570 while (pending
>= swapchain
->max_frame_latency
)
573 pending
= InterlockedCompareExchange(&cs
->pending_presents
, 0, 0);
577 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
579 const struct wined3d_cs_clear
*op
= data
;
580 struct wined3d_device
*device
;
584 device
->blitter
->ops
->blitter_clear(device
->blitter
, device
, op
->rt_count
, op
->fb
,
585 op
->rect_count
, op
->rects
, &op
->draw_rect
, op
->flags
, &op
->color
, op
->depth
, op
->stencil
);
587 if (op
->flags
& WINED3DCLEAR_TARGET
)
589 for (i
= 0; i
< op
->rt_count
; ++i
)
591 if (op
->fb
->render_targets
[i
])
592 wined3d_resource_release(op
->fb
->render_targets
[i
]->resource
);
595 if (op
->flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
596 wined3d_resource_release(op
->fb
->depth_stencil
->resource
);
599 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
600 DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
602 const struct wined3d_state
*state
= &cs
->device
->state
;
603 const struct wined3d_viewport
*vp
= &state
->viewports
[0];
604 struct wined3d_rendertarget_view
*view
;
605 struct wined3d_cs_clear
*op
;
606 unsigned int rt_count
, i
;
608 rt_count
= flags
& WINED3DCLEAR_TARGET
? cs
->device
->adapter
->d3d_info
.limits
.max_rt_count
: 0;
610 op
= wined3d_cs_require_space(cs
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]),
611 WINED3D_CS_QUEUE_DEFAULT
);
612 op
->opcode
= WINED3D_CS_OP_CLEAR
;
613 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
614 op
->rt_count
= rt_count
;
616 SetRect(&op
->draw_rect
, vp
->x
, vp
->y
, vp
->x
+ vp
->width
, vp
->y
+ vp
->height
);
617 if (state
->render_states
[WINED3D_RS_SCISSORTESTENABLE
])
618 IntersectRect(&op
->draw_rect
, &op
->draw_rect
, &state
->scissor_rects
[0]);
621 op
->stencil
= stencil
;
622 op
->rect_count
= rect_count
;
623 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
625 for (i
= 0; i
< rt_count
; ++i
)
627 if ((view
= state
->fb
->render_targets
[i
]))
628 wined3d_resource_acquire(view
->resource
);
630 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
632 view
= state
->fb
->depth_stencil
;
633 wined3d_resource_acquire(view
->resource
);
636 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
639 void wined3d_cs_emit_clear_rendertarget_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
,
640 const RECT
*rect
, DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
642 struct wined3d_cs_clear
*op
;
645 size
= FIELD_OFFSET(struct wined3d_cs_clear
, rects
[1]) + sizeof(struct wined3d_fb_state
);
646 op
= wined3d_cs_require_space(cs
, size
, WINED3D_CS_QUEUE_DEFAULT
);
647 op
->fb
= (void *)&op
->rects
[1];
649 op
->opcode
= WINED3D_CS_OP_CLEAR
;
650 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
651 if (flags
& WINED3DCLEAR_TARGET
)
654 op
->fb
->render_targets
[0] = view
;
655 op
->fb
->depth_stencil
= NULL
;
661 op
->fb
->render_targets
[0] = NULL
;
662 op
->fb
->depth_stencil
= view
;
664 op
->stencil
= stencil
;
666 SetRect(&op
->draw_rect
, 0, 0, view
->width
, view
->height
);
668 op
->rects
[0] = *rect
;
670 wined3d_resource_acquire(view
->resource
);
672 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
673 if (flags
& WINED3DCLEAR_SYNCHRONOUS
)
674 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
677 static void acquire_shader_resources(const struct wined3d_state
*state
, unsigned int shader_mask
)
679 struct wined3d_shader_sampler_map_entry
*entry
;
680 struct wined3d_shader_resource_view
*view
;
681 struct wined3d_shader
*shader
;
684 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
686 if (!(shader_mask
& (1u << i
)))
689 if (!(shader
= state
->shader
[i
]))
692 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
695 wined3d_resource_acquire(&state
->cb
[i
][j
]->resource
);
698 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
700 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
702 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
705 wined3d_resource_acquire(view
->resource
);
710 static void release_shader_resources(const struct wined3d_state
*state
, unsigned int shader_mask
)
712 struct wined3d_shader_sampler_map_entry
*entry
;
713 struct wined3d_shader_resource_view
*view
;
714 struct wined3d_shader
*shader
;
717 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
719 if (!(shader_mask
& (1u << i
)))
722 if (!(shader
= state
->shader
[i
]))
725 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
728 wined3d_resource_release(&state
->cb
[i
][j
]->resource
);
731 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
733 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
735 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
738 wined3d_resource_release(view
->resource
);
743 static void acquire_unordered_access_resources(const struct wined3d_shader
*shader
,
744 struct wined3d_unordered_access_view
* const *views
)
751 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
753 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
759 wined3d_resource_acquire(views
[i
]->resource
);
763 static void release_unordered_access_resources(const struct wined3d_shader
*shader
,
764 struct wined3d_unordered_access_view
* const *views
)
771 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
773 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
779 wined3d_resource_release(views
[i
]->resource
);
783 static void wined3d_cs_exec_dispatch(struct wined3d_cs
*cs
, const void *data
)
785 const struct wined3d_cs_dispatch
*op
= data
;
786 struct wined3d_state
*state
= &cs
->state
;
788 dispatch_compute(cs
->device
, state
, &op
->parameters
);
790 if (op
->parameters
.indirect
)
791 wined3d_resource_release(&op
->parameters
.u
.indirect
.buffer
->resource
);
793 release_shader_resources(state
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
794 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
795 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
798 static void acquire_compute_pipeline_resources(const struct wined3d_state
*state
)
800 acquire_shader_resources(state
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
801 acquire_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
802 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
805 void wined3d_cs_emit_dispatch(struct wined3d_cs
*cs
,
806 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
808 const struct wined3d_state
*state
= &cs
->device
->state
;
809 struct wined3d_cs_dispatch
*op
;
811 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
812 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
813 op
->parameters
.indirect
= FALSE
;
814 op
->parameters
.u
.direct
.group_count_x
= group_count_x
;
815 op
->parameters
.u
.direct
.group_count_y
= group_count_y
;
816 op
->parameters
.u
.direct
.group_count_z
= group_count_z
;
818 acquire_compute_pipeline_resources(state
);
820 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
823 void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs
*cs
,
824 struct wined3d_buffer
*buffer
, unsigned int offset
)
826 const struct wined3d_state
*state
= &cs
->device
->state
;
827 struct wined3d_cs_dispatch
*op
;
829 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
830 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
831 op
->parameters
.indirect
= TRUE
;
832 op
->parameters
.u
.indirect
.buffer
= buffer
;
833 op
->parameters
.u
.indirect
.offset
= offset
;
835 acquire_compute_pipeline_resources(state
);
836 wined3d_resource_acquire(&buffer
->resource
);
838 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
841 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
843 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
844 const struct wined3d_shader
*geometry_shader
;
845 struct wined3d_device
*device
= cs
->device
;
846 int base_vertex_idx
, load_base_vertex_idx
;
847 struct wined3d_state
*state
= &cs
->state
;
848 const struct wined3d_cs_draw
*op
= data
;
852 if (!op
->parameters
.indirect
)
854 const struct wined3d_direct_draw_parameters
*direct
= &op
->parameters
.u
.direct
;
856 if (op
->parameters
.indexed
&& d3d_info
->draw_base_vertex_offset
)
857 base_vertex_idx
= direct
->base_vertex_idx
;
858 else if (!op
->parameters
.indexed
)
859 base_vertex_idx
= direct
->start_idx
;
862 /* ARB_draw_indirect always supports a base vertex offset. */
863 if (!op
->parameters
.indirect
&& !d3d_info
->draw_base_vertex_offset
)
864 load_base_vertex_idx
= op
->parameters
.u
.direct
.base_vertex_idx
;
866 load_base_vertex_idx
= 0;
868 if (state
->base_vertex_index
!= base_vertex_idx
)
870 state
->base_vertex_index
= base_vertex_idx
;
871 for (i
= 0; i
< device
->context_count
; ++i
)
872 device
->contexts
[i
]->constant_update_mask
|= WINED3D_SHADER_CONST_BASE_VERTEX_ID
;
875 if (state
->load_base_vertex_index
!= load_base_vertex_idx
)
877 state
->load_base_vertex_index
= load_base_vertex_idx
;
878 device_invalidate_state(cs
->device
, STATE_BASEVERTEXINDEX
);
881 if (state
->gl_primitive_type
!= op
->primitive_type
)
883 if ((geometry_shader
= state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]) && !geometry_shader
->function
)
884 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
));
885 if (state
->gl_primitive_type
== GL_POINTS
|| op
->primitive_type
== GL_POINTS
)
886 device_invalidate_state(cs
->device
, STATE_POINT_ENABLE
);
887 state
->gl_primitive_type
= op
->primitive_type
;
889 state
->gl_patch_vertices
= op
->patch_vertex_count
;
891 draw_primitive(cs
->device
, state
, &op
->parameters
);
893 if (op
->parameters
.indirect
)
895 struct wined3d_buffer
*buffer
= op
->parameters
.u
.indirect
.buffer
;
896 wined3d_resource_release(&buffer
->resource
);
899 if (op
->parameters
.indexed
)
900 wined3d_resource_release(&state
->index_buffer
->resource
);
901 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
903 if (state
->streams
[i
].buffer
)
904 wined3d_resource_release(&state
->streams
[i
].buffer
->resource
);
906 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
908 if (state
->stream_output
[i
].buffer
)
909 wined3d_resource_release(&state
->stream_output
[i
].buffer
->resource
);
911 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
913 if (state
->textures
[i
])
914 wined3d_resource_release(&state
->textures
[i
]->resource
);
916 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
918 if (state
->fb
->render_targets
[i
])
919 wined3d_resource_release(state
->fb
->render_targets
[i
]->resource
);
921 if (state
->fb
->depth_stencil
)
922 wined3d_resource_release(state
->fb
->depth_stencil
->resource
);
923 release_shader_resources(state
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
924 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
925 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
928 static void acquire_graphics_pipeline_resources(const struct wined3d_state
*state
,
929 BOOL indexed
, const struct wined3d_d3d_info
*d3d_info
)
934 wined3d_resource_acquire(&state
->index_buffer
->resource
);
935 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
937 if (state
->streams
[i
].buffer
)
938 wined3d_resource_acquire(&state
->streams
[i
].buffer
->resource
);
940 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
942 if (state
->stream_output
[i
].buffer
)
943 wined3d_resource_acquire(&state
->stream_output
[i
].buffer
->resource
);
945 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
947 if (state
->textures
[i
])
948 wined3d_resource_acquire(&state
->textures
[i
]->resource
);
950 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
952 if (state
->fb
->render_targets
[i
])
953 wined3d_resource_acquire(state
->fb
->render_targets
[i
]->resource
);
955 if (state
->fb
->depth_stencil
)
956 wined3d_resource_acquire(state
->fb
->depth_stencil
->resource
);
957 acquire_shader_resources(state
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
958 acquire_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
959 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
962 void wined3d_cs_emit_draw(struct wined3d_cs
*cs
, GLenum primitive_type
, unsigned int patch_vertex_count
,
963 int base_vertex_idx
, unsigned int start_idx
, unsigned int index_count
,
964 unsigned int start_instance
, unsigned int instance_count
, BOOL indexed
)
966 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
967 const struct wined3d_state
*state
= &cs
->device
->state
;
968 struct wined3d_cs_draw
*op
;
970 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
971 op
->opcode
= WINED3D_CS_OP_DRAW
;
972 op
->primitive_type
= primitive_type
;
973 op
->patch_vertex_count
= patch_vertex_count
;
974 op
->parameters
.indirect
= FALSE
;
975 op
->parameters
.u
.direct
.base_vertex_idx
= base_vertex_idx
;
976 op
->parameters
.u
.direct
.start_idx
= start_idx
;
977 op
->parameters
.u
.direct
.index_count
= index_count
;
978 op
->parameters
.u
.direct
.start_instance
= start_instance
;
979 op
->parameters
.u
.direct
.instance_count
= instance_count
;
980 op
->parameters
.indexed
= indexed
;
982 acquire_graphics_pipeline_resources(state
, indexed
, d3d_info
);
984 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
987 void wined3d_cs_emit_draw_indirect(struct wined3d_cs
*cs
, GLenum primitive_type
, unsigned int patch_vertex_count
,
988 struct wined3d_buffer
*buffer
, unsigned int offset
, BOOL indexed
)
990 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
991 const struct wined3d_state
*state
= &cs
->device
->state
;
992 struct wined3d_cs_draw
*op
;
994 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
995 op
->opcode
= WINED3D_CS_OP_DRAW
;
996 op
->primitive_type
= primitive_type
;
997 op
->patch_vertex_count
= patch_vertex_count
;
998 op
->parameters
.indirect
= TRUE
;
999 op
->parameters
.u
.indirect
.buffer
= buffer
;
1000 op
->parameters
.u
.indirect
.offset
= offset
;
1001 op
->parameters
.indexed
= indexed
;
1003 acquire_graphics_pipeline_resources(state
, indexed
, d3d_info
);
1004 wined3d_resource_acquire(&buffer
->resource
);
1006 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1009 static void wined3d_cs_exec_flush(struct wined3d_cs
*cs
, const void *data
)
1011 struct wined3d_context
*context
;
1013 context
= context_acquire(cs
->device
, NULL
, 0);
1014 cs
->device
->adapter
->adapter_ops
->adapter_flush_context(context
);
1015 context_release(context
);
1018 void wined3d_cs_emit_flush(struct wined3d_cs
*cs
)
1020 struct wined3d_cs_flush
*op
;
1022 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1023 op
->opcode
= WINED3D_CS_OP_FLUSH
;
1025 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1026 cs
->queries_flushed
= TRUE
;
1029 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
1031 const struct wined3d_cs_set_predication
*op
= data
;
1033 cs
->state
.predicate
= op
->predicate
;
1034 cs
->state
.predicate_value
= op
->value
;
1037 void wined3d_cs_emit_set_predication(struct wined3d_cs
*cs
, struct wined3d_query
*predicate
, BOOL value
)
1039 struct wined3d_cs_set_predication
*op
;
1041 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1042 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
1043 op
->predicate
= predicate
;
1046 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1049 static void wined3d_cs_exec_set_viewports(struct wined3d_cs
*cs
, const void *data
)
1051 const struct wined3d_cs_set_viewports
*op
= data
;
1053 if (op
->viewport_count
)
1054 memcpy(cs
->state
.viewports
, op
->viewports
, op
->viewport_count
* sizeof(*op
->viewports
));
1056 memset(cs
->state
.viewports
, 0, sizeof(*cs
->state
.viewports
));
1057 cs
->state
.viewport_count
= op
->viewport_count
;
1058 device_invalidate_state(cs
->device
, STATE_VIEWPORT
);
1061 void wined3d_cs_emit_set_viewports(struct wined3d_cs
*cs
, unsigned int viewport_count
,
1062 const struct wined3d_viewport
*viewports
)
1064 struct wined3d_cs_set_viewports
*op
;
1066 op
= wined3d_cs_require_space(cs
, FIELD_OFFSET(struct wined3d_cs_set_viewports
, viewports
[viewport_count
]),
1067 WINED3D_CS_QUEUE_DEFAULT
);
1068 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORTS
;
1069 memcpy(op
->viewports
, viewports
, viewport_count
* sizeof(*viewports
));
1070 op
->viewport_count
= viewport_count
;
1072 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1075 static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs
*cs
, const void *data
)
1077 const struct wined3d_cs_set_scissor_rects
*op
= data
;
1080 memcpy(cs
->state
.scissor_rects
, op
->rects
, op
->rect_count
* sizeof(*op
->rects
));
1082 SetRectEmpty(cs
->state
.scissor_rects
);
1083 cs
->state
.scissor_rect_count
= op
->rect_count
;
1084 device_invalidate_state(cs
->device
, STATE_SCISSORRECT
);
1087 void wined3d_cs_emit_set_scissor_rects(struct wined3d_cs
*cs
, unsigned int rect_count
, const RECT
*rects
)
1089 struct wined3d_cs_set_scissor_rects
*op
;
1091 op
= wined3d_cs_require_space(cs
, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects
, rects
[rect_count
]),
1092 WINED3D_CS_QUEUE_DEFAULT
);
1093 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECTS
;
1094 memcpy(op
->rects
, rects
, rect_count
* sizeof(*rects
));
1095 op
->rect_count
= rect_count
;
1097 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1100 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs
*cs
, const void *data
)
1102 const struct wined3d_cs_set_rendertarget_view
*op
= data
;
1103 BOOL prev_alpha_swizzle
, curr_alpha_swizzle
;
1104 struct wined3d_rendertarget_view
*prev
;
1106 prev
= cs
->state
.fb
->render_targets
[op
->view_idx
];
1107 cs
->fb
.render_targets
[op
->view_idx
] = op
->view
;
1108 device_invalidate_state(cs
->device
, STATE_FRAMEBUFFER
);
1110 prev_alpha_swizzle
= prev
&& prev
->format
->id
== WINED3DFMT_A8_UNORM
;
1111 curr_alpha_swizzle
= op
->view
&& op
->view
->format
->id
== WINED3DFMT_A8_UNORM
;
1112 if (prev_alpha_swizzle
!= curr_alpha_swizzle
)
1113 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1116 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs
*cs
, unsigned int view_idx
,
1117 struct wined3d_rendertarget_view
*view
)
1119 struct wined3d_cs_set_rendertarget_view
*op
;
1121 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1122 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEW
;
1123 op
->view_idx
= view_idx
;
1126 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1129 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
1131 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
1132 struct wined3d_device
*device
= cs
->device
;
1133 struct wined3d_rendertarget_view
*prev
;
1135 if ((prev
= cs
->state
.fb
->depth_stencil
) && prev
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
1137 struct wined3d_texture
*prev_texture
= texture_from_resource(prev
->resource
);
1139 if (device
->swapchains
[0]->state
.desc
.flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
1140 || prev_texture
->flags
& WINED3D_TEXTURE_DISCARD
)
1141 wined3d_texture_validate_location(prev_texture
,
1142 prev
->sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
1145 cs
->fb
.depth_stencil
= op
->view
;
1147 if (!prev
!= !op
->view
)
1149 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
1150 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_ZENABLE
));
1151 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILENABLE
));
1152 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK
));
1153 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
1157 if (prev
->format
->depth_bias_scale
!= op
->view
->format
->depth_bias_scale
)
1158 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_DEPTHBIAS
));
1159 if (prev
->format
->stencil_size
!= op
->view
->format
->stencil_size
)
1160 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_STENCILREF
));
1163 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1166 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs
*cs
, struct wined3d_rendertarget_view
*view
)
1168 struct wined3d_cs_set_depth_stencil_view
*op
;
1170 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1171 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
1174 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1177 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
1179 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
1181 cs
->state
.vertex_declaration
= op
->declaration
;
1182 device_invalidate_state(cs
->device
, STATE_VDECL
);
1185 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs
*cs
, struct wined3d_vertex_declaration
*declaration
)
1187 struct wined3d_cs_set_vertex_declaration
*op
;
1189 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1190 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
1191 op
->declaration
= declaration
;
1193 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1196 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs
*cs
, const void *data
)
1198 const struct wined3d_cs_set_stream_source
*op
= data
;
1199 struct wined3d_stream_state
*stream
;
1200 struct wined3d_buffer
*prev
;
1202 stream
= &cs
->state
.streams
[op
->stream_idx
];
1203 prev
= stream
->buffer
;
1204 stream
->buffer
= op
->buffer
;
1205 stream
->offset
= op
->offset
;
1206 stream
->stride
= op
->stride
;
1209 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1211 InterlockedDecrement(&prev
->resource
.bind_count
);
1213 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
1216 void wined3d_cs_emit_set_stream_source(struct wined3d_cs
*cs
, UINT stream_idx
,
1217 struct wined3d_buffer
*buffer
, UINT offset
, UINT stride
)
1219 struct wined3d_cs_set_stream_source
*op
;
1221 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1222 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE
;
1223 op
->stream_idx
= stream_idx
;
1224 op
->buffer
= buffer
;
1225 op
->offset
= offset
;
1226 op
->stride
= stride
;
1228 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1231 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs
*cs
, const void *data
)
1233 const struct wined3d_cs_set_stream_source_freq
*op
= data
;
1234 struct wined3d_stream_state
*stream
;
1236 stream
= &cs
->state
.streams
[op
->stream_idx
];
1237 stream
->frequency
= op
->frequency
;
1238 stream
->flags
= op
->flags
;
1240 device_invalidate_state(cs
->device
, STATE_STREAMSRC
);
1243 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs
*cs
, UINT stream_idx
, UINT frequency
, UINT flags
)
1245 struct wined3d_cs_set_stream_source_freq
*op
;
1247 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1248 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ
;
1249 op
->stream_idx
= stream_idx
;
1250 op
->frequency
= frequency
;
1253 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1256 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs
*cs
, const void *data
)
1258 const struct wined3d_cs_set_stream_output
*op
= data
;
1259 struct wined3d_stream_output
*stream
;
1260 struct wined3d_buffer
*prev
;
1262 stream
= &cs
->state
.stream_output
[op
->stream_idx
];
1263 prev
= stream
->buffer
;
1264 stream
->buffer
= op
->buffer
;
1265 stream
->offset
= op
->offset
;
1268 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1270 InterlockedDecrement(&prev
->resource
.bind_count
);
1272 device_invalidate_state(cs
->device
, STATE_STREAM_OUTPUT
);
1275 void wined3d_cs_emit_set_stream_output(struct wined3d_cs
*cs
, UINT stream_idx
,
1276 struct wined3d_buffer
*buffer
, UINT offset
)
1278 struct wined3d_cs_set_stream_output
*op
;
1280 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1281 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUT
;
1282 op
->stream_idx
= stream_idx
;
1283 op
->buffer
= buffer
;
1284 op
->offset
= offset
;
1286 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1289 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
1291 const struct wined3d_cs_set_index_buffer
*op
= data
;
1292 struct wined3d_buffer
*prev
;
1294 prev
= cs
->state
.index_buffer
;
1295 cs
->state
.index_buffer
= op
->buffer
;
1296 cs
->state
.index_format
= op
->format_id
;
1297 cs
->state
.index_offset
= op
->offset
;
1300 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1302 InterlockedDecrement(&prev
->resource
.bind_count
);
1304 device_invalidate_state(cs
->device
, STATE_INDEXBUFFER
);
1307 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs
*cs
, struct wined3d_buffer
*buffer
,
1308 enum wined3d_format_id format_id
, unsigned int offset
)
1310 struct wined3d_cs_set_index_buffer
*op
;
1312 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1313 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
1314 op
->buffer
= buffer
;
1315 op
->format_id
= format_id
;
1316 op
->offset
= offset
;
1318 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1321 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs
*cs
, const void *data
)
1323 const struct wined3d_cs_set_constant_buffer
*op
= data
;
1324 struct wined3d_buffer
*prev
;
1326 prev
= cs
->state
.cb
[op
->type
][op
->cb_idx
];
1327 cs
->state
.cb
[op
->type
][op
->cb_idx
] = op
->buffer
;
1330 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1332 InterlockedDecrement(&prev
->resource
.bind_count
);
1334 device_invalidate_state(cs
->device
, STATE_CONSTANT_BUFFER(op
->type
));
1337 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
1338 UINT cb_idx
, struct wined3d_buffer
*buffer
)
1340 struct wined3d_cs_set_constant_buffer
*op
;
1342 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1343 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFER
;
1345 op
->cb_idx
= cb_idx
;
1346 op
->buffer
= buffer
;
1348 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1351 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
1353 const struct wined3d_d3d_info
*d3d_info
= &cs
->device
->adapter
->d3d_info
;
1354 const struct wined3d_cs_set_texture
*op
= data
;
1355 struct wined3d_texture
*prev
;
1356 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
1358 prev
= cs
->state
.textures
[op
->stage
];
1359 cs
->state
.textures
[op
->stage
] = op
->texture
;
1363 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
1364 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
1365 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
1366 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
1368 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
1369 op
->texture
->sampler
= op
->stage
;
1371 if (!prev
|| wined3d_texture_gl(op
->texture
)->target
!= wined3d_texture_gl(prev
)->target
1372 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
1373 && !(can_use_texture_swizzle(d3d_info
, new_format
) && can_use_texture_swizzle(d3d_info
, old_format
)))
1374 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
1375 device_invalidate_state(cs
->device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1377 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1379 /* The source arguments for color and alpha ops have different
1380 * meanings when a NULL texture is bound, so the COLOR_OP and
1381 * ALPHA_OP have to be dirtified. */
1382 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1383 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1386 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1387 new_use_color_key
= TRUE
;
1392 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
1396 /* Search for other stages the texture is bound to. Shouldn't
1397 * happen if applications bind textures to a single stage only. */
1398 TRACE("Searching for other stages the texture is bound to.\n");
1399 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
1401 if (cs
->state
.textures
[i
] == prev
)
1403 TRACE("Texture is also bound to stage %u.\n", i
);
1410 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1412 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1413 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1416 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1417 old_use_color_key
= TRUE
;
1420 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->stage
));
1422 if (new_use_color_key
!= old_use_color_key
)
1423 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1425 if (new_use_color_key
)
1426 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
1429 void wined3d_cs_emit_set_texture(struct wined3d_cs
*cs
, UINT stage
, struct wined3d_texture
*texture
)
1431 struct wined3d_cs_set_texture
*op
;
1433 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1434 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
1436 op
->texture
= texture
;
1438 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1441 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs
*cs
, const void *data
)
1443 const struct wined3d_cs_set_shader_resource_view
*op
= data
;
1444 struct wined3d_shader_resource_view
*prev
;
1446 prev
= cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
];
1447 cs
->state
.shader_resource_view
[op
->type
][op
->view_idx
] = op
->view
;
1450 InterlockedIncrement(&op
->view
->resource
->bind_count
);
1452 InterlockedDecrement(&prev
->resource
->bind_count
);
1454 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1455 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1457 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1460 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
1461 UINT view_idx
, struct wined3d_shader_resource_view
*view
)
1463 struct wined3d_cs_set_shader_resource_view
*op
;
1465 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1466 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW
;
1468 op
->view_idx
= view_idx
;
1471 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1474 static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
1476 const struct wined3d_cs_set_unordered_access_view
*op
= data
;
1477 struct wined3d_unordered_access_view
*prev
;
1479 prev
= cs
->state
.unordered_access_view
[op
->pipeline
][op
->view_idx
];
1480 cs
->state
.unordered_access_view
[op
->pipeline
][op
->view_idx
] = op
->view
;
1483 InterlockedIncrement(&op
->view
->resource
->bind_count
);
1485 InterlockedDecrement(&prev
->resource
->bind_count
);
1487 if (op
->view
&& op
->initial_count
!= ~0u)
1488 wined3d_unordered_access_view_set_counter(op
->view
, op
->initial_count
);
1490 device_invalidate_state(cs
->device
, STATE_UNORDERED_ACCESS_VIEW_BINDING(op
->pipeline
));
1493 void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs
*cs
, enum wined3d_pipeline pipeline
,
1494 unsigned int view_idx
, struct wined3d_unordered_access_view
*view
, unsigned int initial_count
)
1496 struct wined3d_cs_set_unordered_access_view
*op
;
1498 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1499 op
->opcode
= WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW
;
1500 op
->pipeline
= pipeline
;
1501 op
->view_idx
= view_idx
;
1503 op
->initial_count
= initial_count
;
1505 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1508 static void wined3d_cs_exec_set_sampler(struct wined3d_cs
*cs
, const void *data
)
1510 const struct wined3d_cs_set_sampler
*op
= data
;
1512 cs
->state
.sampler
[op
->type
][op
->sampler_idx
] = op
->sampler
;
1513 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1514 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1516 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1519 void wined3d_cs_emit_set_sampler(struct wined3d_cs
*cs
, enum wined3d_shader_type type
,
1520 UINT sampler_idx
, struct wined3d_sampler
*sampler
)
1522 struct wined3d_cs_set_sampler
*op
;
1524 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1525 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER
;
1527 op
->sampler_idx
= sampler_idx
;
1528 op
->sampler
= sampler
;
1530 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1533 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
1535 const struct wined3d_cs_set_shader
*op
= data
;
1537 cs
->state
.shader
[op
->type
] = op
->shader
;
1538 device_invalidate_state(cs
->device
, STATE_SHADER(op
->type
));
1539 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1540 device_invalidate_state(cs
->device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1542 device_invalidate_state(cs
->device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1545 void wined3d_cs_emit_set_shader(struct wined3d_cs
*cs
, enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
1547 struct wined3d_cs_set_shader
*op
;
1549 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1550 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
1552 op
->shader
= shader
;
1554 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1557 static void wined3d_cs_exec_set_blend_state(struct wined3d_cs
*cs
, const void *data
)
1559 const struct wined3d_cs_set_blend_state
*op
= data
;
1560 struct wined3d_state
*state
= &cs
->state
;
1562 if (state
->blend_state
!= op
->state
)
1564 state
->blend_state
= op
->state
;
1565 device_invalidate_state(cs
->device
, STATE_BLEND
);
1567 state
->blend_factor
= op
->factor
;
1568 device_invalidate_state(cs
->device
, STATE_BLEND_FACTOR
);
1571 void wined3d_cs_emit_set_blend_state(struct wined3d_cs
*cs
, struct wined3d_blend_state
*state
,
1572 const struct wined3d_color
*blend_factor
)
1574 struct wined3d_cs_set_blend_state
*op
;
1576 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1577 op
->opcode
= WINED3D_CS_OP_SET_BLEND_STATE
;
1579 op
->factor
= *blend_factor
;
1581 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1584 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs
, const void *data
)
1586 const struct wined3d_cs_set_rasterizer_state
*op
= data
;
1588 cs
->state
.rasterizer_state
= op
->state
;
1589 device_invalidate_state(cs
->device
, STATE_RASTERIZER
);
1592 void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs
*cs
,
1593 struct wined3d_rasterizer_state
*rasterizer_state
)
1595 struct wined3d_cs_set_rasterizer_state
*op
;
1597 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1598 op
->opcode
= WINED3D_CS_OP_SET_RASTERIZER_STATE
;
1599 op
->state
= rasterizer_state
;
1601 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1604 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
1606 const struct wined3d_cs_set_render_state
*op
= data
;
1608 cs
->state
.render_states
[op
->state
] = op
->value
;
1609 device_invalidate_state(cs
->device
, STATE_RENDER(op
->state
));
1612 void wined3d_cs_emit_set_render_state(struct wined3d_cs
*cs
, enum wined3d_render_state state
, DWORD value
)
1614 struct wined3d_cs_set_render_state
*op
;
1616 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1617 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
1621 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1624 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
1626 const struct wined3d_cs_set_texture_state
*op
= data
;
1628 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
1629 device_invalidate_state(cs
->device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
1632 void wined3d_cs_emit_set_texture_state(struct wined3d_cs
*cs
, UINT stage
,
1633 enum wined3d_texture_stage_state state
, DWORD value
)
1635 struct wined3d_cs_set_texture_state
*op
;
1637 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1638 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
1643 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1646 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
1648 const struct wined3d_cs_set_sampler_state
*op
= data
;
1650 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
1651 device_invalidate_state(cs
->device
, STATE_SAMPLER(op
->sampler_idx
));
1654 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs
*cs
, UINT sampler_idx
,
1655 enum wined3d_sampler_state state
, DWORD value
)
1657 struct wined3d_cs_set_sampler_state
*op
;
1659 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1660 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
1661 op
->sampler_idx
= sampler_idx
;
1665 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1668 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
1670 const struct wined3d_cs_set_transform
*op
= data
;
1672 cs
->state
.transforms
[op
->state
] = op
->matrix
;
1673 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
1674 device_invalidate_state(cs
->device
, STATE_TRANSFORM(op
->state
));
1677 void wined3d_cs_emit_set_transform(struct wined3d_cs
*cs
, enum wined3d_transform_state state
,
1678 const struct wined3d_matrix
*matrix
)
1680 struct wined3d_cs_set_transform
*op
;
1682 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1683 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
1685 op
->matrix
= *matrix
;
1687 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1690 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
1692 const struct wined3d_cs_set_clip_plane
*op
= data
;
1694 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
1695 device_invalidate_state(cs
->device
, STATE_CLIPPLANE(op
->plane_idx
));
1698 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs
*cs
, UINT plane_idx
, const struct wined3d_vec4
*plane
)
1700 struct wined3d_cs_set_clip_plane
*op
;
1702 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1703 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
1704 op
->plane_idx
= plane_idx
;
1707 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1710 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
1712 const struct wined3d_cs_set_color_key
*op
= data
;
1713 struct wined3d_texture
*texture
= op
->texture
;
1719 case WINED3D_CKEY_DST_BLT
:
1720 texture
->async
.dst_blt_color_key
= op
->color_key
;
1721 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
1724 case WINED3D_CKEY_DST_OVERLAY
:
1725 texture
->async
.dst_overlay_color_key
= op
->color_key
;
1726 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
1729 case WINED3D_CKEY_SRC_BLT
:
1730 if (texture
== cs
->state
.textures
[0])
1732 device_invalidate_state(cs
->device
, STATE_COLOR_KEY
);
1733 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
1734 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1737 texture
->async
.src_blt_color_key
= op
->color_key
;
1738 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
1741 case WINED3D_CKEY_SRC_OVERLAY
:
1742 texture
->async
.src_overlay_color_key
= op
->color_key
;
1743 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
1751 case WINED3D_CKEY_DST_BLT
:
1752 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
1755 case WINED3D_CKEY_DST_OVERLAY
:
1756 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
1759 case WINED3D_CKEY_SRC_BLT
:
1760 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1761 device_invalidate_state(cs
->device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1763 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
1766 case WINED3D_CKEY_SRC_OVERLAY
:
1767 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
1773 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
1774 WORD flags
, const struct wined3d_color_key
*color_key
)
1776 struct wined3d_cs_set_color_key
*op
;
1778 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1779 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
1780 op
->texture
= texture
;
1784 op
->color_key
= *color_key
;
1790 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1793 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
1795 const struct wined3d_cs_set_material
*op
= data
;
1797 cs
->state
.material
= op
->material
;
1798 device_invalidate_state(cs
->device
, STATE_MATERIAL
);
1801 void wined3d_cs_emit_set_material(struct wined3d_cs
*cs
, const struct wined3d_material
*material
)
1803 struct wined3d_cs_set_material
*op
;
1805 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1806 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
1807 op
->material
= *material
;
1809 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1812 static void wined3d_cs_exec_set_light(struct wined3d_cs
*cs
, const void *data
)
1814 const struct wined3d_cs_set_light
*op
= data
;
1815 struct wined3d_light_info
*light_info
;
1816 unsigned int light_idx
, hash_idx
;
1818 light_idx
= op
->light
.OriginalIndex
;
1820 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, light_idx
)))
1822 TRACE("Adding new light.\n");
1823 if (!(light_info
= heap_alloc_zero(sizeof(*light_info
))))
1825 ERR("Failed to allocate light info.\n");
1829 hash_idx
= LIGHTMAP_HASHFUNC(light_idx
);
1830 list_add_head(&cs
->state
.light_state
.light_map
[hash_idx
], &light_info
->entry
);
1831 light_info
->glIndex
= -1;
1832 light_info
->OriginalIndex
= light_idx
;
1835 if (light_info
->glIndex
!= -1)
1837 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
1838 device_invalidate_state(cs
->device
, STATE_LIGHT_TYPE
);
1839 device_invalidate_state(cs
->device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
1842 light_info
->OriginalParms
= op
->light
.OriginalParms
;
1843 light_info
->position
= op
->light
.position
;
1844 light_info
->direction
= op
->light
.direction
;
1845 light_info
->exponent
= op
->light
.exponent
;
1846 light_info
->cutoff
= op
->light
.cutoff
;
1849 void wined3d_cs_emit_set_light(struct wined3d_cs
*cs
, const struct wined3d_light_info
*light
)
1851 struct wined3d_cs_set_light
*op
;
1853 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1854 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
1857 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1860 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
1862 const struct wined3d_cs_set_light_enable
*op
= data
;
1863 struct wined3d_device
*device
= cs
->device
;
1864 struct wined3d_light_info
*light_info
;
1867 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, op
->idx
)))
1869 ERR("Light doesn't exist.\n");
1873 prev_idx
= light_info
->glIndex
;
1874 wined3d_light_state_enable_light(&cs
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
);
1875 if (light_info
->glIndex
!= prev_idx
)
1877 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
1878 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
1882 void wined3d_cs_emit_set_light_enable(struct wined3d_cs
*cs
, unsigned int idx
, BOOL enable
)
1884 struct wined3d_cs_set_light_enable
*op
;
1886 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1887 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
1889 op
->enable
= enable
;
1891 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1900 wined3d_cs_push_constant_info
[] =
1902 /* WINED3D_PUSH_CONSTANTS_VS_F */
1903 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
1904 /* WINED3D_PUSH_CONSTANTS_PS_F */
1905 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
1906 /* WINED3D_PUSH_CONSTANTS_VS_I */
1907 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
1908 /* WINED3D_PUSH_CONSTANTS_PS_I */
1909 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
1910 /* WINED3D_PUSH_CONSTANTS_VS_B */
1911 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
1912 /* WINED3D_PUSH_CONSTANTS_PS_B */
1913 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
1916 static void wined3d_cs_st_push_constants(struct wined3d_cs
*cs
, enum wined3d_push_constants p
,
1917 unsigned int start_idx
, unsigned int count
, const void *constants
)
1919 struct wined3d_device
*device
= cs
->device
;
1920 unsigned int context_count
;
1924 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
1925 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
1926 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
1927 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
1929 offset
= wined3d_cs_push_constant_info
[p
].offset
+ start_idx
* wined3d_cs_push_constant_info
[p
].size
;
1930 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* wined3d_cs_push_constant_info
[p
].size
);
1931 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
1933 device
->contexts
[i
]->constant_update_mask
|= wined3d_cs_push_constant_info
[p
].mask
;
1937 static void wined3d_cs_exec_push_constants(struct wined3d_cs
*cs
, const void *data
)
1939 const struct wined3d_cs_push_constants
*op
= data
;
1941 wined3d_cs_st_push_constants(cs
, op
->type
, op
->start_idx
, op
->count
, op
->constants
);
1944 static void wined3d_cs_mt_push_constants(struct wined3d_cs
*cs
, enum wined3d_push_constants p
,
1945 unsigned int start_idx
, unsigned int count
, const void *constants
)
1947 struct wined3d_cs_push_constants
*op
;
1950 size
= count
* wined3d_cs_push_constant_info
[p
].size
;
1951 op
= wined3d_cs_require_space(cs
, FIELD_OFFSET(struct wined3d_cs_push_constants
, constants
[size
]),
1952 WINED3D_CS_QUEUE_DEFAULT
);
1953 op
->opcode
= WINED3D_CS_OP_PUSH_CONSTANTS
;
1955 op
->start_idx
= start_idx
;
1957 memcpy(op
->constants
, constants
, size
);
1959 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1962 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
1964 struct wined3d_adapter
*adapter
= cs
->device
->adapter
;
1966 state_cleanup(&cs
->state
);
1967 memset(&cs
->state
, 0, sizeof(cs
->state
));
1968 state_init(&cs
->state
, &cs
->fb
, &adapter
->d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
);
1971 void wined3d_cs_emit_reset_state(struct wined3d_cs
*cs
)
1973 struct wined3d_cs_reset_state
*op
;
1975 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1976 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
1978 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
1981 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
1983 const struct wined3d_cs_callback
*op
= data
;
1985 op
->callback(op
->object
);
1988 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
1990 struct wined3d_cs_callback
*op
;
1992 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1993 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
1994 op
->callback
= callback
;
1995 op
->object
= object
;
1997 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2000 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2002 wined3d_cs_emit_callback(cs
, callback
, object
);
2005 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2007 wined3d_cs_emit_callback(cs
, callback
, object
);
2010 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
2012 const struct wined3d_cs_query_issue
*op
= data
;
2013 struct wined3d_query
*query
= op
->query
;
2016 poll
= query
->query_ops
->query_issue(query
, op
->flags
);
2021 if (poll
&& list_empty(&query
->poll_list_entry
))
2023 if (query
->buffer_object
)
2024 InterlockedIncrement(&query
->counter_retrieved
);
2026 list_add_tail(&cs
->query_poll_list
, &query
->poll_list_entry
);
2030 /* This can happen if occlusion queries are restarted. This discards the
2031 * old result, since polling it could result in a GL error. */
2032 if ((op
->flags
& WINED3DISSUE_BEGIN
) && !poll
&& !list_empty(&query
->poll_list_entry
))
2034 list_remove(&query
->poll_list_entry
);
2035 list_init(&query
->poll_list_entry
);
2036 InterlockedIncrement(&query
->counter_retrieved
);
2040 /* This can happen when an occlusion query is ended without being started,
2041 * in which case we don't want to poll, but still have to counter-balance
2042 * the increment of the main counter.
2044 * This can also happen if an event query is re-issued before the first
2045 * fence was reached. In this case the query is already in the list and
2046 * the poll function will check the new fence. We have to counter-balance
2047 * the discarded increment. */
2048 if (op
->flags
& WINED3DISSUE_END
)
2049 InterlockedIncrement(&query
->counter_retrieved
);
2052 void wined3d_cs_emit_query_issue(struct wined3d_cs
*cs
, struct wined3d_query
*query
, DWORD flags
)
2054 struct wined3d_cs_query_issue
*op
;
2056 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2057 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
2061 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2062 cs
->queries_flushed
= FALSE
;
2065 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
2067 const struct wined3d_cs_preload_resource
*op
= data
;
2068 struct wined3d_resource
*resource
= op
->resource
;
2070 resource
->resource_ops
->resource_preload(resource
);
2071 wined3d_resource_release(resource
);
2074 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2076 struct wined3d_cs_preload_resource
*op
;
2078 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2079 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
2080 op
->resource
= resource
;
2082 wined3d_resource_acquire(resource
);
2084 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2087 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
2089 const struct wined3d_cs_unload_resource
*op
= data
;
2090 struct wined3d_resource
*resource
= op
->resource
;
2092 resource
->resource_ops
->resource_unload(resource
);
2093 wined3d_resource_release(resource
);
2096 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2098 struct wined3d_cs_unload_resource
*op
;
2100 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2101 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
2102 op
->resource
= resource
;
2104 wined3d_resource_acquire(resource
);
2106 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2109 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
2111 const struct wined3d_cs_map
*op
= data
;
2112 struct wined3d_resource
*resource
= op
->resource
;
2114 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
2115 op
->sub_resource_idx
, op
->map_desc
, op
->box
, op
->flags
);
2118 HRESULT
wined3d_cs_map(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
2119 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
2121 struct wined3d_cs_map
*op
;
2124 /* Mapping resources from the worker thread isn't an issue by itself, but
2125 * increasing the map count would be visible to applications. */
2126 wined3d_not_from_cs(cs
);
2128 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2129 op
->opcode
= WINED3D_CS_OP_MAP
;
2130 op
->resource
= resource
;
2131 op
->sub_resource_idx
= sub_resource_idx
;
2132 op
->map_desc
= map_desc
;
2137 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_MAP
);
2138 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_MAP
);
2143 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
2145 const struct wined3d_cs_unmap
*op
= data
;
2146 struct wined3d_resource
*resource
= op
->resource
;
2148 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
2151 HRESULT
wined3d_cs_unmap(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
2153 struct wined3d_cs_unmap
*op
;
2156 wined3d_not_from_cs(cs
);
2158 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2159 op
->opcode
= WINED3D_CS_OP_UNMAP
;
2160 op
->resource
= resource
;
2161 op
->sub_resource_idx
= sub_resource_idx
;
2164 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_MAP
);
2165 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_MAP
);
2170 static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2172 const struct wined3d_cs_blt_sub_resource
*op
= data
;
2174 if (op
->dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
2176 wined3d_buffer_copy(buffer_from_resource(op
->dst_resource
), op
->dst_box
.left
,
2177 buffer_from_resource(op
->src_resource
), op
->src_box
.left
,
2178 op
->src_box
.right
- op
->src_box
.left
);
2180 else if (op
->dst_resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
2182 struct wined3d_texture
*src_texture
, *dst_texture
;
2183 unsigned int level
, update_w
, update_h
, update_d
;
2184 unsigned int row_pitch
, slice_pitch
;
2185 struct wined3d_context
*context
;
2186 struct wined3d_bo_address addr
;
2188 if (op
->flags
& ~WINED3D_BLT_RAW
)
2190 FIXME("Flags %#x not implemented for %s resources.\n",
2191 op
->flags
, debug_d3dresourcetype(op
->dst_resource
->type
));
2195 if (!(op
->flags
& WINED3D_BLT_RAW
) && op
->src_resource
->format
!= op
->dst_resource
->format
)
2197 FIXME("Format conversion not implemented for %s resources.\n",
2198 debug_d3dresourcetype(op
->dst_resource
->type
));
2202 update_w
= op
->dst_box
.right
- op
->dst_box
.left
;
2203 update_h
= op
->dst_box
.bottom
- op
->dst_box
.top
;
2204 update_d
= op
->dst_box
.back
- op
->dst_box
.front
;
2205 if (op
->src_box
.right
- op
->src_box
.left
!= update_w
2206 || op
->src_box
.bottom
- op
->src_box
.top
!= update_h
2207 || op
->src_box
.back
- op
->src_box
.front
!= update_d
)
2209 FIXME("Stretching not implemented for %s resources.\n",
2210 debug_d3dresourcetype(op
->dst_resource
->type
));
2214 dst_texture
= texture_from_resource(op
->dst_resource
);
2215 src_texture
= texture_from_resource(op
->src_resource
);
2217 context
= context_acquire(cs
->device
, NULL
, 0);
2219 if (!wined3d_texture_load_location(src_texture
, op
->src_sub_resource_idx
,
2220 context
, src_texture
->resource
.map_binding
))
2222 ERR("Failed to load source sub-resource into %s.\n",
2223 wined3d_debug_location(src_texture
->resource
.map_binding
));
2224 context_release(context
);
2228 level
= op
->dst_sub_resource_idx
% dst_texture
->level_count
;
2229 if (update_w
== wined3d_texture_get_level_width(dst_texture
, level
)
2230 && update_h
== wined3d_texture_get_level_height(dst_texture
, level
)
2231 && update_d
== wined3d_texture_get_level_depth(dst_texture
, level
))
2233 wined3d_texture_prepare_location(dst_texture
, op
->dst_sub_resource_idx
,
2234 context
, WINED3D_LOCATION_TEXTURE_RGB
);
2236 else if (!wined3d_texture_load_location(dst_texture
, op
->dst_sub_resource_idx
,
2237 context
, WINED3D_LOCATION_TEXTURE_RGB
))
2239 ERR("Failed to load destination sub-resource.\n");
2240 context_release(context
);
2244 wined3d_texture_get_memory(src_texture
, op
->src_sub_resource_idx
, &addr
, src_texture
->resource
.map_binding
);
2245 wined3d_texture_get_pitch(src_texture
, op
->src_sub_resource_idx
% src_texture
->level_count
,
2246 &row_pitch
, &slice_pitch
);
2248 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&addr
),
2249 dst_texture
->resource
.format
, &op
->src_box
, row_pitch
, slice_pitch
, dst_texture
,
2250 op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
2251 op
->dst_box
.left
, op
->dst_box
.top
, op
->dst_box
.front
);
2252 wined3d_texture_validate_location(dst_texture
, op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2253 wined3d_texture_invalidate_location(dst_texture
, op
->dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2255 context_release(context
);
2259 if (FAILED(texture2d_blt(texture_from_resource(op
->dst_resource
), op
->dst_sub_resource_idx
,
2260 &op
->dst_box
, texture_from_resource(op
->src_resource
), op
->src_sub_resource_idx
,
2261 &op
->src_box
, op
->flags
, &op
->fx
, op
->filter
)))
2262 FIXME("Blit failed.\n");
2266 if (op
->src_resource
)
2267 wined3d_resource_release(op
->src_resource
);
2268 wined3d_resource_release(op
->dst_resource
);
2271 void wined3d_cs_emit_blt_sub_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*dst_resource
,
2272 unsigned int dst_sub_resource_idx
, const struct wined3d_box
*dst_box
, struct wined3d_resource
*src_resource
,
2273 unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
, DWORD flags
,
2274 const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
2276 struct wined3d_cs_blt_sub_resource
*op
;
2278 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2279 op
->opcode
= WINED3D_CS_OP_BLT_SUB_RESOURCE
;
2280 op
->dst_resource
= dst_resource
;
2281 op
->dst_sub_resource_idx
= dst_sub_resource_idx
;
2282 op
->dst_box
= *dst_box
;
2283 op
->src_resource
= src_resource
;
2284 op
->src_sub_resource_idx
= src_sub_resource_idx
;
2285 op
->src_box
= *src_box
;
2290 memset(&op
->fx
, 0, sizeof(op
->fx
));
2291 op
->filter
= filter
;
2293 wined3d_resource_acquire(dst_resource
);
2295 wined3d_resource_acquire(src_resource
);
2297 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2298 if (flags
& WINED3D_BLT_SYNCHRONOUS
)
2299 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2302 static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2304 const struct wined3d_cs_update_sub_resource
*op
= data
;
2305 struct wined3d_resource
*resource
= op
->resource
;
2306 const struct wined3d_box
*box
= &op
->box
;
2307 unsigned int width
, height
, depth
, level
;
2308 struct wined3d_const_bo_address addr
;
2309 struct wined3d_context
*context
;
2310 struct wined3d_texture
*texture
;
2311 struct wined3d_box src_box
;
2313 context
= context_acquire(cs
->device
, NULL
, 0);
2315 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2317 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
2319 if (!wined3d_buffer_load_location(buffer
, context
, WINED3D_LOCATION_BUFFER
))
2321 ERR("Failed to load buffer location.\n");
2325 wined3d_buffer_upload_data(buffer
, context
, box
, op
->data
.data
);
2326 wined3d_buffer_invalidate_location(buffer
, ~WINED3D_LOCATION_BUFFER
);
2330 texture
= wined3d_texture_from_resource(resource
);
2332 level
= op
->sub_resource_idx
% texture
->level_count
;
2333 width
= wined3d_texture_get_level_width(texture
, level
);
2334 height
= wined3d_texture_get_level_height(texture
, level
);
2335 depth
= wined3d_texture_get_level_depth(texture
, level
);
2337 addr
.buffer_object
= 0;
2338 addr
.addr
= op
->data
.data
;
2340 /* Only load the sub-resource for partial updates. */
2341 if (!box
->left
&& !box
->top
&& !box
->front
2342 && box
->right
== width
&& box
->bottom
== height
&& box
->back
== depth
)
2343 wined3d_texture_prepare_location(texture
, op
->sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
2345 wined3d_texture_load_location(texture
, op
->sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
2347 wined3d_box_set(&src_box
, 0, 0, box
->right
- box
->left
, box
->bottom
- box
->top
, 0, box
->back
- box
->front
);
2348 texture
->texture_ops
->texture_upload_data(context
, &addr
, texture
->resource
.format
, &src_box
,
2349 op
->data
.row_pitch
, op
->data
.slice_pitch
, texture
, op
->sub_resource_idx
,
2350 WINED3D_LOCATION_TEXTURE_RGB
, box
->left
, box
->top
, box
->front
);
2352 wined3d_texture_validate_location(texture
, op
->sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2353 wined3d_texture_invalidate_location(texture
, op
->sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2356 context_release(context
);
2358 wined3d_resource_release(resource
);
2361 void wined3d_cs_emit_update_sub_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
,
2362 unsigned int sub_resource_idx
, const struct wined3d_box
*box
, const void *data
, unsigned int row_pitch
,
2363 unsigned int slice_pitch
)
2365 struct wined3d_cs_update_sub_resource
*op
;
2367 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2368 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2369 op
->resource
= resource
;
2370 op
->sub_resource_idx
= sub_resource_idx
;
2372 op
->data
.row_pitch
= row_pitch
;
2373 op
->data
.slice_pitch
= slice_pitch
;
2374 op
->data
.data
= data
;
2376 wined3d_resource_acquire(resource
);
2378 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_MAP
);
2379 /* The data pointer may go away, so we need to wait until it is read.
2380 * Copying the data may be faster if it's small. */
2381 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_MAP
);
2384 static void wined3d_cs_exec_add_dirty_texture_region(struct wined3d_cs
*cs
, const void *data
)
2386 const struct wined3d_cs_add_dirty_texture_region
*op
= data
;
2387 struct wined3d_texture
*texture
= op
->texture
;
2388 unsigned int sub_resource_idx
, i
;
2389 struct wined3d_context
*context
;
2391 context
= context_acquire(cs
->device
, NULL
, 0);
2392 sub_resource_idx
= op
->layer
* texture
->level_count
;
2393 for (i
= 0; i
< texture
->level_count
; ++i
, ++sub_resource_idx
)
2395 if (wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
))
2396 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
2398 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
2400 context_release(context
);
2402 wined3d_resource_release(&texture
->resource
);
2405 void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs
*cs
,
2406 struct wined3d_texture
*texture
, unsigned int layer
)
2408 struct wined3d_cs_add_dirty_texture_region
*op
;
2410 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2411 op
->opcode
= WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
;
2412 op
->texture
= texture
;
2415 wined3d_resource_acquire(&texture
->resource
);
2417 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2420 static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
2422 const struct wined3d_cs_clear_unordered_access_view
*op
= data
;
2423 struct wined3d_unordered_access_view
*view
= op
->view
;
2424 struct wined3d_context
*context
;
2426 context
= context_acquire(cs
->device
, NULL
, 0);
2427 cs
->device
->adapter
->adapter_ops
->adapter_clear_uav(context
, view
, &op
->clear_value
);
2428 context_release(context
);
2430 wined3d_resource_release(view
->resource
);
2433 void wined3d_cs_emit_clear_unordered_access_view_uint(struct wined3d_cs
*cs
,
2434 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
)
2436 struct wined3d_cs_clear_unordered_access_view
*op
;
2438 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2439 op
->opcode
= WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
;
2441 op
->clear_value
= *clear_value
;
2443 wined3d_resource_acquire(view
->resource
);
2445 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2448 static void wined3d_cs_exec_copy_uav_counter(struct wined3d_cs
*cs
, const void *data
)
2450 const struct wined3d_cs_copy_uav_counter
*op
= data
;
2451 struct wined3d_unordered_access_view
*view
= op
->view
;
2452 struct wined3d_context
*context
;
2454 context
= context_acquire(cs
->device
, NULL
, 0);
2455 wined3d_unordered_access_view_copy_counter(view
, op
->buffer
, op
->offset
, context
);
2456 context_release(context
);
2458 wined3d_resource_release(&op
->buffer
->resource
);
2461 void wined3d_cs_emit_copy_uav_counter(struct wined3d_cs
*cs
, struct wined3d_buffer
*dst_buffer
,
2462 unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
2464 struct wined3d_cs_copy_uav_counter
*op
;
2466 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2467 op
->opcode
= WINED3D_CS_OP_COPY_UAV_COUNTER
;
2468 op
->buffer
= dst_buffer
;
2469 op
->offset
= offset
;
2472 wined3d_resource_acquire(&dst_buffer
->resource
);
2474 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2477 static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs
*cs
, const void *data
)
2479 const struct wined3d_cs_generate_mipmaps
*op
= data
;
2480 struct wined3d_shader_resource_view
*view
= op
->view
;
2482 shader_resource_view_generate_mipmaps(view
);
2483 wined3d_resource_release(view
->resource
);
2486 void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs
*cs
, struct wined3d_shader_resource_view
*view
)
2488 struct wined3d_cs_generate_mipmaps
*op
;
2490 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2491 op
->opcode
= WINED3D_CS_OP_GENERATE_MIPMAPS
;
2494 wined3d_resource_acquire(view
->resource
);
2496 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2499 static void wined3d_cs_emit_stop(struct wined3d_cs
*cs
)
2501 struct wined3d_cs_stop
*op
;
2503 op
= wined3d_cs_require_space(cs
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2504 op
->opcode
= WINED3D_CS_OP_STOP
;
2506 wined3d_cs_submit(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2507 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2510 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
2512 /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop
,
2513 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
2514 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
2515 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
2516 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
2517 /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush
,
2518 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
2519 /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports
,
2520 /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects
,
2521 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view
,
2522 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
2523 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
2524 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source
,
2525 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq
,
2526 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output
,
2527 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
2528 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer
,
2529 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
2530 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view
,
2531 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view
,
2532 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler
,
2533 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
2534 /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state
,
2535 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
2536 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
2537 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
2538 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
2539 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
2540 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
2541 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
2542 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
2543 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
2544 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
2545 /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants
,
2546 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
2547 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
2548 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
2549 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
2550 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
2551 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
2552 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
2553 /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource
,
2554 /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource
,
2555 /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region
,
2556 /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view
,
2557 /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter
,
2558 /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps
,
2561 static void *wined3d_cs_st_require_space(struct wined3d_cs
*cs
, size_t size
, enum wined3d_cs_queue_id queue_id
)
2563 if (size
> (cs
->data_size
- cs
->end
))
2568 new_size
= max(size
, cs
->data_size
* 2);
2570 new_data
= heap_realloc(cs
->data
, new_size
);
2572 new_data
= heap_alloc(new_size
);
2576 cs
->data_size
= new_size
;
2577 cs
->start
= cs
->end
= 0;
2578 cs
->data
= new_data
;
2583 return (BYTE
*)cs
->data
+ cs
->start
;
2586 static void wined3d_cs_st_submit(struct wined3d_cs
*cs
, enum wined3d_cs_queue_id queue_id
)
2588 enum wined3d_cs_op opcode
;
2594 cs
->start
= cs
->end
;
2596 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
2597 if (opcode
>= WINED3D_CS_OP_STOP
)
2598 ERR("Invalid opcode %#x.\n", opcode
);
2600 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
2602 if (cs
->data
== data
)
2603 cs
->start
= cs
->end
= start
;
2608 static void wined3d_cs_st_finish(struct wined3d_cs
*cs
, enum wined3d_cs_queue_id queue_id
)
2612 static const struct wined3d_cs_ops wined3d_cs_st_ops
=
2614 wined3d_cs_st_require_space
,
2615 wined3d_cs_st_submit
,
2616 wined3d_cs_st_finish
,
2617 wined3d_cs_st_push_constants
,
2620 static BOOL
wined3d_cs_queue_is_empty(const struct wined3d_cs
*cs
, const struct wined3d_cs_queue
*queue
)
2622 wined3d_from_cs(cs
);
2623 return *(volatile LONG
*)&queue
->head
== queue
->tail
;
2626 static void wined3d_cs_queue_submit(struct wined3d_cs_queue
*queue
, struct wined3d_cs
*cs
)
2628 struct wined3d_cs_packet
*packet
;
2631 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
];
2632 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
2633 InterlockedExchange(&queue
->head
, (queue
->head
+ packet_size
) & (WINED3D_CS_QUEUE_SIZE
- 1));
2635 if (InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
2636 SetEvent(cs
->event
);
2639 static void wined3d_cs_mt_submit(struct wined3d_cs
*cs
, enum wined3d_cs_queue_id queue_id
)
2641 if (cs
->thread_id
== GetCurrentThreadId())
2642 return wined3d_cs_st_submit(cs
, queue_id
);
2644 wined3d_cs_queue_submit(&cs
->queue
[queue_id
], cs
);
2647 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue
, size_t size
, struct wined3d_cs
*cs
)
2649 size_t queue_size
= ARRAY_SIZE(queue
->data
);
2650 size_t header_size
, packet_size
, remaining
;
2651 struct wined3d_cs_packet
*packet
;
2653 header_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[0]);
2654 size
= (size
+ header_size
- 1) & ~(header_size
- 1);
2655 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[size
]);
2656 if (packet_size
>= WINED3D_CS_QUEUE_SIZE
)
2658 ERR("Packet size %lu >= queue size %u.\n",
2659 (unsigned long)packet_size
, WINED3D_CS_QUEUE_SIZE
);
2663 remaining
= queue_size
- queue
->head
;
2664 if (remaining
< packet_size
)
2666 size_t nop_size
= remaining
- header_size
;
2667 struct wined3d_cs_nop
*nop
;
2669 TRACE("Inserting a nop for %lu + %lu bytes.\n",
2670 (unsigned long)header_size
, (unsigned long)nop_size
);
2672 nop
= wined3d_cs_queue_require_space(queue
, nop_size
, cs
);
2674 nop
->opcode
= WINED3D_CS_OP_NOP
;
2676 wined3d_cs_queue_submit(queue
, cs
);
2677 assert(!queue
->head
);
2682 LONG tail
= *(volatile LONG
*)&queue
->tail
;
2683 LONG head
= queue
->head
;
2689 new_pos
= (head
+ packet_size
) & (WINED3D_CS_QUEUE_SIZE
- 1);
2690 /* Head ahead of tail. We checked the remaining size above, so we only
2691 * need to make sure we don't make head equal to tail. */
2692 if (head
> tail
&& (new_pos
!= tail
))
2694 /* Tail ahead of head. Make sure the new head is before the tail as
2695 * well. Note that new_pos is 0 when it's at the end of the queue. */
2696 if (new_pos
< tail
&& new_pos
)
2699 TRACE("Waiting for free space. Head %u, tail %u, packet size %lu.\n",
2700 head
, tail
, (unsigned long)packet_size
);
2703 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
];
2704 packet
->size
= size
;
2705 return packet
->data
;
2708 static void *wined3d_cs_mt_require_space(struct wined3d_cs
*cs
, size_t size
, enum wined3d_cs_queue_id queue_id
)
2710 if (cs
->thread_id
== GetCurrentThreadId())
2711 return wined3d_cs_st_require_space(cs
, size
, queue_id
);
2713 return wined3d_cs_queue_require_space(&cs
->queue
[queue_id
], size
, cs
);
2716 static void wined3d_cs_mt_finish(struct wined3d_cs
*cs
, enum wined3d_cs_queue_id queue_id
)
2718 if (cs
->thread_id
== GetCurrentThreadId())
2719 return wined3d_cs_st_finish(cs
, queue_id
);
2721 while (cs
->queue
[queue_id
].head
!= *(volatile LONG
*)&cs
->queue
[queue_id
].tail
)
2725 static const struct wined3d_cs_ops wined3d_cs_mt_ops
=
2727 wined3d_cs_mt_require_space
,
2728 wined3d_cs_mt_submit
,
2729 wined3d_cs_mt_finish
,
2730 wined3d_cs_mt_push_constants
,
2733 static void poll_queries(struct wined3d_cs
*cs
)
2735 struct wined3d_query
*query
, *cursor
;
2737 LIST_FOR_EACH_ENTRY_SAFE(query
, cursor
, &cs
->query_poll_list
, struct wined3d_query
, poll_list_entry
)
2739 if (!query
->query_ops
->query_poll(query
, 0))
2742 list_remove(&query
->poll_list_entry
);
2743 list_init(&query
->poll_list_entry
);
2744 InterlockedIncrement(&query
->counter_retrieved
);
2748 static void wined3d_cs_wait_event(struct wined3d_cs
*cs
)
2750 InterlockedExchange(&cs
->waiting_for_event
, TRUE
);
2752 /* The main thread might have enqueued a command and blocked on it after
2753 * the CS thread decided to enter wined3d_cs_wait_event(), but before
2754 * "waiting_for_event" was set.
2756 * Likewise, we can race with the main thread when resetting
2757 * "waiting_for_event", in which case we would need to call
2758 * WaitForSingleObject() because the main thread called SetEvent(). */
2759 if (!(wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
])
2760 && wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_MAP
]))
2761 && InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
2764 WaitForSingleObject(cs
->event
, INFINITE
);
2767 static DWORD WINAPI
wined3d_cs_run(void *ctx
)
2769 struct wined3d_cs_packet
*packet
;
2770 struct wined3d_cs_queue
*queue
;
2771 unsigned int spin_count
= 0;
2772 struct wined3d_cs
*cs
= ctx
;
2773 enum wined3d_cs_op opcode
;
2774 HMODULE wined3d_module
;
2775 unsigned int poll
= 0;
2778 TRACE("Started.\n");
2780 /* Copy the module handle to a local variable to avoid racing with the
2781 * thread freeing "cs" before the FreeLibraryAndExitThread() call. */
2782 wined3d_module
= cs
->wined3d_module
;
2784 list_init(&cs
->query_poll_list
);
2785 cs
->thread_id
= GetCurrentThreadId();
2788 if (++poll
== WINED3D_CS_QUERY_POLL_INTERVAL
)
2794 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
2795 if (wined3d_cs_queue_is_empty(cs
, queue
))
2797 queue
= &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
];
2798 if (wined3d_cs_queue_is_empty(cs
, queue
))
2800 if (++spin_count
>= WINED3D_CS_SPIN_COUNT
&& list_empty(&cs
->query_poll_list
))
2801 wined3d_cs_wait_event(cs
);
2808 packet
= (struct wined3d_cs_packet
*)&queue
->data
[tail
];
2811 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
2813 TRACE("Executing %s.\n", debug_cs_op(opcode
));
2814 if (opcode
>= WINED3D_CS_OP_STOP
)
2816 if (opcode
> WINED3D_CS_OP_STOP
)
2817 ERR("Invalid opcode %#x.\n", opcode
);
2821 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
2822 TRACE("%s executed.\n", debug_cs_op(opcode
));
2825 tail
+= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
2826 tail
&= (WINED3D_CS_QUEUE_SIZE
- 1);
2827 InterlockedExchange(&queue
->tail
, tail
);
2830 cs
->queue
[WINED3D_CS_QUEUE_MAP
].tail
= cs
->queue
[WINED3D_CS_QUEUE_MAP
].head
;
2831 cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].tail
= cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].head
;
2832 TRACE("Stopped.\n");
2833 FreeLibraryAndExitThread(wined3d_module
, 0);
2836 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
)
2838 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
2839 struct wined3d_cs
*cs
;
2841 if (!(cs
= heap_alloc_zero(sizeof(*cs
))))
2844 cs
->ops
= &wined3d_cs_st_ops
;
2845 cs
->device
= device
;
2847 state_init(&cs
->state
, &cs
->fb
, d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
);
2849 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
2850 if (!(cs
->data
= heap_alloc(cs
->data_size
)))
2853 if (wined3d_settings
.cs_multithreaded
2854 && !RtlIsCriticalSectionLockedByThread(NtCurrentTeb()->Peb
->LoaderLock
))
2856 cs
->ops
= &wined3d_cs_mt_ops
;
2858 if (!(cs
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
2860 ERR("Failed to create command stream event.\n");
2861 heap_free(cs
->data
);
2865 if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
2866 (const WCHAR
*)wined3d_cs_run
, &cs
->wined3d_module
)))
2868 ERR("Failed to get wined3d module handle.\n");
2869 CloseHandle(cs
->event
);
2870 heap_free(cs
->data
);
2874 if (!(cs
->thread
= CreateThread(NULL
, 0, wined3d_cs_run
, cs
, 0, NULL
)))
2876 ERR("Failed to create wined3d command stream thread.\n");
2877 FreeLibrary(cs
->wined3d_module
);
2878 CloseHandle(cs
->event
);
2879 heap_free(cs
->data
);
2887 state_cleanup(&cs
->state
);
2892 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
2896 wined3d_cs_emit_stop(cs
);
2897 CloseHandle(cs
->thread
);
2898 if (!CloseHandle(cs
->event
))
2899 ERR("Closing event failed.\n");
2902 state_cleanup(&cs
->state
);
2903 heap_free(cs
->data
);