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 "wined3d_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
23 WINE_DECLARE_DEBUG_CHANNEL(d3d_sync
);
24 WINE_DECLARE_DEBUG_CHANNEL(fps
);
26 #define WINED3D_INITIAL_CS_SIZE 4096
28 struct wined3d_deferred_upload
30 struct wined3d_resource
*resource
;
31 unsigned int sub_resource_idx
;
33 struct wined3d_box box
;
34 uint32_t upload_flags
;
37 struct wined3d_deferred_query_issue
39 struct wined3d_query
*query
;
43 struct wined3d_command_list
47 struct wined3d_device
*device
;
52 SIZE_T resource_count
;
53 struct wined3d_resource
**resources
;
56 struct wined3d_deferred_upload
*uploads
;
58 /* List of command lists queued for execution on this command list. We might
59 * be the only thing holding a pointer to another command list, so we need
60 * to hold a reference here (and in wined3d_deferred_context) as well. */
61 SIZE_T command_list_count
;
62 struct wined3d_command_list
**command_lists
;
65 struct wined3d_deferred_query_issue
*queries
;
68 static void invalidate_client_address(struct wined3d_resource
*resource
)
70 struct wined3d_client_resource
*client
= &resource
->client
;
72 memset(&client
->addr
, 0, sizeof(client
->addr
));
78 WINED3D_CS_OP_PRESENT
,
80 WINED3D_CS_OP_DISPATCH
,
83 WINED3D_CS_OP_SET_PREDICATION
,
84 WINED3D_CS_OP_SET_VIEWPORTS
,
85 WINED3D_CS_OP_SET_SCISSOR_RECTS
,
86 WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
,
87 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
,
88 WINED3D_CS_OP_SET_VERTEX_DECLARATION
,
89 WINED3D_CS_OP_SET_STREAM_SOURCES
,
90 WINED3D_CS_OP_SET_STREAM_OUTPUTS
,
91 WINED3D_CS_OP_SET_INDEX_BUFFER
,
92 WINED3D_CS_OP_SET_CONSTANT_BUFFERS
,
93 WINED3D_CS_OP_SET_TEXTURE
,
94 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
,
95 WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
,
96 WINED3D_CS_OP_SET_SAMPLERS
,
97 WINED3D_CS_OP_SET_SHADER
,
98 WINED3D_CS_OP_SET_BLEND_STATE
,
99 WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
,
100 WINED3D_CS_OP_SET_RASTERIZER_STATE
,
101 WINED3D_CS_OP_SET_RENDER_STATE
,
102 WINED3D_CS_OP_SET_TEXTURE_STATE
,
103 WINED3D_CS_OP_SET_SAMPLER_STATE
,
104 WINED3D_CS_OP_SET_TRANSFORM
,
105 WINED3D_CS_OP_SET_CLIP_PLANE
,
106 WINED3D_CS_OP_SET_COLOR_KEY
,
107 WINED3D_CS_OP_SET_MATERIAL
,
108 WINED3D_CS_OP_SET_LIGHT
,
109 WINED3D_CS_OP_SET_LIGHT_ENABLE
,
110 WINED3D_CS_OP_SET_FEATURE_LEVEL
,
111 WINED3D_CS_OP_PUSH_CONSTANTS
,
112 WINED3D_CS_OP_RESET_STATE
,
113 WINED3D_CS_OP_CALLBACK
,
114 WINED3D_CS_OP_QUERY_ISSUE
,
115 WINED3D_CS_OP_PRELOAD_RESOURCE
,
116 WINED3D_CS_OP_UNLOAD_RESOURCE
,
119 WINED3D_CS_OP_BLT_SUB_RESOURCE
,
120 WINED3D_CS_OP_UPDATE_SUB_RESOURCE
,
121 WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
,
122 WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
,
123 WINED3D_CS_OP_COPY_UAV_COUNTER
,
124 WINED3D_CS_OP_GENERATE_MIPMAPS
,
125 WINED3D_CS_OP_EXECUTE_COMMAND_LIST
,
129 struct wined3d_cs_packet
135 struct wined3d_cs_nop
137 enum wined3d_cs_op opcode
;
140 struct wined3d_cs_present
142 enum wined3d_cs_op opcode
;
143 HWND dst_window_override
;
144 struct wined3d_swapchain
*swapchain
;
147 unsigned int swap_interval
;
151 struct wined3d_cs_clear
153 enum wined3d_cs_op opcode
;
155 unsigned int rt_count
;
156 struct wined3d_fb_state fb
;
158 struct wined3d_color color
;
161 unsigned int rect_count
;
165 struct wined3d_cs_dispatch
167 enum wined3d_cs_op opcode
;
168 struct wined3d_dispatch_parameters parameters
;
171 struct wined3d_cs_draw
173 enum wined3d_cs_op opcode
;
174 enum wined3d_primitive_type primitive_type
;
175 GLint patch_vertex_count
;
176 struct wined3d_draw_parameters parameters
;
179 struct wined3d_cs_flush
181 enum wined3d_cs_op opcode
;
184 struct wined3d_cs_set_predication
186 enum wined3d_cs_op opcode
;
187 struct wined3d_query
*predicate
;
191 struct wined3d_cs_set_viewports
193 enum wined3d_cs_op opcode
;
194 unsigned int viewport_count
;
195 struct wined3d_viewport viewports
[1];
198 struct wined3d_cs_set_scissor_rects
200 enum wined3d_cs_op opcode
;
201 unsigned int rect_count
;
205 struct wined3d_cs_set_rendertarget_views
207 enum wined3d_cs_op opcode
;
208 unsigned int start_idx
;
210 struct wined3d_rendertarget_view
*views
[1];
213 struct wined3d_cs_set_depth_stencil_view
215 enum wined3d_cs_op opcode
;
216 struct wined3d_rendertarget_view
*view
;
219 struct wined3d_cs_set_vertex_declaration
221 enum wined3d_cs_op opcode
;
222 struct wined3d_vertex_declaration
*declaration
;
225 struct wined3d_cs_set_stream_sources
227 enum wined3d_cs_op opcode
;
228 unsigned int start_idx
;
230 struct wined3d_stream_state streams
[1];
233 struct wined3d_cs_set_stream_outputs
235 enum wined3d_cs_op opcode
;
236 struct wined3d_stream_output outputs
[WINED3D_MAX_STREAM_OUTPUT_BUFFERS
];
239 struct wined3d_cs_set_index_buffer
241 enum wined3d_cs_op opcode
;
242 struct wined3d_buffer
*buffer
;
243 enum wined3d_format_id format_id
;
247 struct wined3d_cs_set_constant_buffers
249 enum wined3d_cs_op opcode
;
250 enum wined3d_shader_type type
;
251 unsigned int start_idx
;
253 struct wined3d_constant_buffer_state buffers
[1];
256 struct wined3d_cs_set_texture
258 enum wined3d_cs_op opcode
;
260 struct wined3d_texture
*texture
;
263 struct wined3d_cs_set_color_key
265 enum wined3d_cs_op opcode
;
266 struct wined3d_texture
*texture
;
269 struct wined3d_color_key color_key
;
272 struct wined3d_cs_set_shader_resource_views
274 enum wined3d_cs_op opcode
;
275 enum wined3d_shader_type type
;
276 unsigned int start_idx
;
278 struct wined3d_shader_resource_view
*views
[1];
281 struct wined3d_cs_set_unordered_access_views
283 enum wined3d_cs_op opcode
;
284 enum wined3d_pipeline pipeline
;
285 unsigned int start_idx
;
289 struct wined3d_unordered_access_view
*view
;
290 unsigned int initial_count
;
294 struct wined3d_cs_set_samplers
296 enum wined3d_cs_op opcode
;
297 enum wined3d_shader_type type
;
298 unsigned int start_idx
;
300 struct wined3d_sampler
*samplers
[1];
303 struct wined3d_cs_set_shader
305 enum wined3d_cs_op opcode
;
306 enum wined3d_shader_type type
;
307 struct wined3d_shader
*shader
;
310 struct wined3d_cs_set_blend_state
312 enum wined3d_cs_op opcode
;
313 struct wined3d_blend_state
*state
;
314 struct wined3d_color factor
;
315 unsigned int sample_mask
;
318 struct wined3d_cs_set_depth_stencil_state
320 enum wined3d_cs_op opcode
;
321 struct wined3d_depth_stencil_state
*state
;
322 unsigned int stencil_ref
;
325 struct wined3d_cs_set_rasterizer_state
327 enum wined3d_cs_op opcode
;
328 struct wined3d_rasterizer_state
*state
;
331 struct wined3d_cs_set_render_state
333 enum wined3d_cs_op opcode
;
334 enum wined3d_render_state state
;
338 struct wined3d_cs_set_texture_state
340 enum wined3d_cs_op opcode
;
342 enum wined3d_texture_stage_state state
;
346 struct wined3d_cs_set_sampler_state
348 enum wined3d_cs_op opcode
;
350 enum wined3d_sampler_state state
;
354 struct wined3d_cs_set_transform
356 enum wined3d_cs_op opcode
;
357 enum wined3d_transform_state state
;
358 struct wined3d_matrix matrix
;
361 struct wined3d_cs_set_clip_plane
363 enum wined3d_cs_op opcode
;
365 struct wined3d_vec4 plane
;
368 struct wined3d_cs_set_material
370 enum wined3d_cs_op opcode
;
371 struct wined3d_material material
;
374 struct wined3d_cs_set_light
376 enum wined3d_cs_op opcode
;
377 struct wined3d_light_info light
;
380 struct wined3d_cs_set_light_enable
382 enum wined3d_cs_op opcode
;
387 struct wined3d_cs_set_feature_level
389 enum wined3d_cs_op opcode
;
390 enum wined3d_feature_level level
;
393 struct wined3d_cs_push_constants
395 enum wined3d_cs_op opcode
;
396 enum wined3d_push_constants type
;
397 unsigned int start_idx
;
402 struct wined3d_cs_reset_state
404 enum wined3d_cs_op opcode
;
408 struct wined3d_cs_callback
410 enum wined3d_cs_op opcode
;
411 void (*callback
)(void *object
);
415 struct wined3d_cs_query_issue
417 enum wined3d_cs_op opcode
;
418 struct wined3d_query
*query
;
422 struct wined3d_cs_preload_resource
424 enum wined3d_cs_op opcode
;
425 struct wined3d_resource
*resource
;
428 struct wined3d_cs_unload_resource
430 enum wined3d_cs_op opcode
;
431 struct wined3d_resource
*resource
;
434 struct wined3d_cs_map
436 enum wined3d_cs_op opcode
;
437 struct wined3d_resource
*resource
;
438 unsigned int sub_resource_idx
;
440 const struct wined3d_box
*box
;
445 struct wined3d_cs_unmap
447 enum wined3d_cs_op opcode
;
448 struct wined3d_resource
*resource
;
449 unsigned int sub_resource_idx
;
453 struct wined3d_cs_blt_sub_resource
455 enum wined3d_cs_op opcode
;
456 struct wined3d_resource
*dst_resource
;
457 unsigned int dst_sub_resource_idx
;
458 struct wined3d_box dst_box
;
459 struct wined3d_resource
*src_resource
;
460 unsigned int src_sub_resource_idx
;
461 struct wined3d_box src_box
;
463 struct wined3d_blt_fx fx
;
464 enum wined3d_texture_filter_type filter
;
467 struct wined3d_cs_update_sub_resource
469 enum wined3d_cs_op opcode
;
470 struct wined3d_resource
*resource
;
471 unsigned int sub_resource_idx
;
472 struct wined3d_box box
;
474 unsigned int row_pitch
, slice_pitch
;
477 struct wined3d_cs_add_dirty_texture_region
479 enum wined3d_cs_op opcode
;
480 struct wined3d_texture
*texture
;
484 struct wined3d_cs_clear_unordered_access_view
486 enum wined3d_cs_op opcode
;
487 struct wined3d_unordered_access_view
*view
;
488 struct wined3d_uvec4 clear_value
;
492 struct wined3d_cs_copy_uav_counter
494 enum wined3d_cs_op opcode
;
495 struct wined3d_buffer
*buffer
;
497 struct wined3d_unordered_access_view
*view
;
500 struct wined3d_cs_generate_mipmaps
502 enum wined3d_cs_op opcode
;
503 struct wined3d_shader_resource_view
*view
;
506 struct wined3d_cs_execute_command_list
508 enum wined3d_cs_op opcode
;
509 struct wined3d_command_list
*list
;
512 struct wined3d_cs_stop
514 enum wined3d_cs_op opcode
;
517 static inline void *wined3d_device_context_require_space(struct wined3d_device_context
*context
,
518 size_t size
, enum wined3d_cs_queue_id queue_id
)
520 return context
->ops
->require_space(context
, size
, queue_id
);
523 static inline void wined3d_device_context_submit(struct wined3d_device_context
*context
,
524 enum wined3d_cs_queue_id queue_id
)
526 context
->ops
->submit(context
, queue_id
);
529 static inline void wined3d_device_context_finish(struct wined3d_device_context
*context
,
530 enum wined3d_cs_queue_id queue_id
)
532 context
->ops
->finish(context
, queue_id
);
535 static inline void wined3d_device_context_acquire_resource(struct wined3d_device_context
*context
,
536 struct wined3d_resource
*resource
)
538 context
->ops
->acquire_resource(context
, resource
);
541 static struct wined3d_cs
*wined3d_cs_from_context(struct wined3d_device_context
*context
)
543 return CONTAINING_RECORD(context
, struct wined3d_cs
, c
);
546 static const char *debug_cs_op(enum wined3d_cs_op op
)
550 #define WINED3D_TO_STR(type) case type: return #type
551 WINED3D_TO_STR(WINED3D_CS_OP_NOP
);
552 WINED3D_TO_STR(WINED3D_CS_OP_PRESENT
);
553 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR
);
554 WINED3D_TO_STR(WINED3D_CS_OP_DISPATCH
);
555 WINED3D_TO_STR(WINED3D_CS_OP_DRAW
);
556 WINED3D_TO_STR(WINED3D_CS_OP_FLUSH
);
557 WINED3D_TO_STR(WINED3D_CS_OP_SET_PREDICATION
);
558 WINED3D_TO_STR(WINED3D_CS_OP_SET_VIEWPORTS
);
559 WINED3D_TO_STR(WINED3D_CS_OP_SET_SCISSOR_RECTS
);
560 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
);
561 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
);
562 WINED3D_TO_STR(WINED3D_CS_OP_SET_VERTEX_DECLARATION
);
563 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCES
);
564 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_OUTPUTS
);
565 WINED3D_TO_STR(WINED3D_CS_OP_SET_INDEX_BUFFER
);
566 WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFERS
);
567 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE
);
568 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
);
569 WINED3D_TO_STR(WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
);
570 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLERS
);
571 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER
);
572 WINED3D_TO_STR(WINED3D_CS_OP_SET_BLEND_STATE
);
573 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
);
574 WINED3D_TO_STR(WINED3D_CS_OP_SET_RASTERIZER_STATE
);
575 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDER_STATE
);
576 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE_STATE
);
577 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLER_STATE
);
578 WINED3D_TO_STR(WINED3D_CS_OP_SET_TRANSFORM
);
579 WINED3D_TO_STR(WINED3D_CS_OP_SET_CLIP_PLANE
);
580 WINED3D_TO_STR(WINED3D_CS_OP_SET_COLOR_KEY
);
581 WINED3D_TO_STR(WINED3D_CS_OP_SET_MATERIAL
);
582 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT
);
583 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT_ENABLE
);
584 WINED3D_TO_STR(WINED3D_CS_OP_SET_FEATURE_LEVEL
);
585 WINED3D_TO_STR(WINED3D_CS_OP_PUSH_CONSTANTS
);
586 WINED3D_TO_STR(WINED3D_CS_OP_RESET_STATE
);
587 WINED3D_TO_STR(WINED3D_CS_OP_CALLBACK
);
588 WINED3D_TO_STR(WINED3D_CS_OP_QUERY_ISSUE
);
589 WINED3D_TO_STR(WINED3D_CS_OP_PRELOAD_RESOURCE
);
590 WINED3D_TO_STR(WINED3D_CS_OP_UNLOAD_RESOURCE
);
591 WINED3D_TO_STR(WINED3D_CS_OP_MAP
);
592 WINED3D_TO_STR(WINED3D_CS_OP_UNMAP
);
593 WINED3D_TO_STR(WINED3D_CS_OP_BLT_SUB_RESOURCE
);
594 WINED3D_TO_STR(WINED3D_CS_OP_UPDATE_SUB_RESOURCE
);
595 WINED3D_TO_STR(WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
);
596 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
);
597 WINED3D_TO_STR(WINED3D_CS_OP_COPY_UAV_COUNTER
);
598 WINED3D_TO_STR(WINED3D_CS_OP_GENERATE_MIPMAPS
);
599 WINED3D_TO_STR(WINED3D_CS_OP_EXECUTE_COMMAND_LIST
);
600 WINED3D_TO_STR(WINED3D_CS_OP_STOP
);
601 #undef WINED3D_TO_STR
603 return wine_dbg_sprintf("UNKNOWN_OP(%#x)", op
);
606 static struct wined3d_cs_packet
*wined3d_next_cs_packet(const uint8_t *data
, SIZE_T
*offset
)
608 struct wined3d_cs_packet
*packet
= (struct wined3d_cs_packet
*)&data
[*offset
];
610 *offset
+= offsetof(struct wined3d_cs_packet
, data
[packet
->size
]);
615 static void wined3d_cs_exec_nop(struct wined3d_cs
*cs
, const void *data
)
619 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
621 struct wined3d_texture
*logo_texture
, *cursor_texture
, *back_buffer
;
622 struct wined3d_rendertarget_view
*dsv
= cs
->state
.fb
.depth_stencil
;
623 const struct wined3d_cs_present
*op
= data
;
624 const struct wined3d_swapchain_desc
*desc
;
625 struct wined3d_swapchain
*swapchain
;
628 swapchain
= op
->swapchain
;
629 desc
= &swapchain
->state
.desc
;
630 back_buffer
= swapchain
->back_buffers
[0];
631 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
633 if ((logo_texture
= swapchain
->device
->logo_texture
))
635 RECT rect
= {0, 0, logo_texture
->resource
.width
, logo_texture
->resource
.height
};
637 /* Blit the logo into the upper left corner of the back-buffer. */
638 wined3d_device_context_blt(&cs
->c
, back_buffer
, 0, &rect
, logo_texture
, 0,
639 &rect
, WINED3D_BLT_SRC_CKEY
, NULL
, WINED3D_TEXF_POINT
);
642 if ((cursor_texture
= swapchain
->device
->cursor_texture
)
643 && swapchain
->device
->bCursorVisible
&& !swapchain
->device
->hardwareCursor
)
647 swapchain
->device
->xScreenSpace
- swapchain
->device
->xHotSpot
,
648 swapchain
->device
->yScreenSpace
- swapchain
->device
->yHotSpot
,
649 swapchain
->device
->xScreenSpace
+ swapchain
->device
->cursorWidth
- swapchain
->device
->xHotSpot
,
650 swapchain
->device
->yScreenSpace
+ swapchain
->device
->cursorHeight
- swapchain
->device
->yHotSpot
,
654 0, 0, cursor_texture
->resource
.width
, cursor_texture
->resource
.height
656 const RECT clip_rect
= {0, 0, back_buffer
->resource
.width
, back_buffer
->resource
.height
};
658 TRACE("Rendering the software cursor.\n");
661 MapWindowPoints(NULL
, swapchain
->win_handle
, (POINT
*)&dst_rect
, 2);
662 if (wined3d_clip_blit(&clip_rect
, &dst_rect
, &src_rect
))
663 wined3d_device_context_blt(&cs
->c
, back_buffer
, 0, &dst_rect
, cursor_texture
, 0,
664 &src_rect
, WINED3D_BLT_ALPHA_TEST
, NULL
, WINED3D_TEXF_POINT
);
667 swapchain
->swapchain_ops
->swapchain_present(swapchain
, &op
->src_rect
, &op
->dst_rect
, op
->swap_interval
, op
->flags
);
669 /* Discard buffers if the swap effect allows it. */
670 back_buffer
= swapchain
->back_buffers
[desc
->backbuffer_count
- 1];
671 if (desc
->swap_effect
== WINED3D_SWAP_EFFECT_DISCARD
|| desc
->swap_effect
== WINED3D_SWAP_EFFECT_FLIP_DISCARD
)
672 wined3d_texture_validate_location(back_buffer
, 0, WINED3D_LOCATION_DISCARDED
);
674 if (dsv
&& dsv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
676 struct wined3d_texture
*ds
= texture_from_resource(dsv
->resource
);
678 if ((desc
->flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
|| ds
->flags
& WINED3D_TEXTURE_DISCARD
))
679 wined3d_rendertarget_view_validate_location(dsv
, WINED3D_LOCATION_DISCARDED
);
684 DWORD time
= GetTickCount();
687 /* every 1.5 seconds */
688 if (time
- swapchain
->prev_time
> 1500)
690 TRACE_(fps
)("%p @ approx %.2ffps\n",
691 swapchain
, 1000.0 * swapchain
->frames
/ (time
- swapchain
->prev_time
));
692 swapchain
->prev_time
= time
;
693 swapchain
->frames
= 0;
697 wined3d_resource_release(&swapchain
->front_buffer
->resource
);
698 for (i
= 0; i
< desc
->backbuffer_count
; ++i
)
700 wined3d_resource_release(&swapchain
->back_buffers
[i
]->resource
);
703 InterlockedDecrement(&cs
->pending_presents
);
706 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
707 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
,
708 unsigned int swap_interval
, DWORD flags
)
710 struct wined3d_cs_present
*op
;
714 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
715 op
->opcode
= WINED3D_CS_OP_PRESENT
;
716 op
->dst_window_override
= dst_window_override
;
717 op
->swapchain
= swapchain
;
718 op
->src_rect
= *src_rect
;
719 op
->dst_rect
= *dst_rect
;
720 op
->swap_interval
= swap_interval
;
723 pending
= InterlockedIncrement(&cs
->pending_presents
);
725 wined3d_resource_acquire(&swapchain
->front_buffer
->resource
);
726 for (i
= 0; i
< swapchain
->state
.desc
.backbuffer_count
; ++i
)
728 wined3d_resource_acquire(&swapchain
->back_buffers
[i
]->resource
);
731 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
733 /* Limit input latency by limiting the number of presents that we can get
734 * ahead of the worker thread. */
735 while (pending
>= swapchain
->max_frame_latency
)
738 pending
= InterlockedCompareExchange(&cs
->pending_presents
, 0, 0);
742 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
744 struct wined3d_device
*device
= cs
->c
.device
;
745 const struct wined3d_cs_clear
*op
= data
;
748 device
->blitter
->ops
->blitter_clear(device
->blitter
, device
, op
->rt_count
, &op
->fb
,
749 op
->rect_count
, op
->rects
, &op
->draw_rect
, op
->flags
, &op
->color
, op
->depth
, op
->stencil
);
751 if (op
->flags
& WINED3DCLEAR_TARGET
)
753 for (i
= 0; i
< op
->rt_count
; ++i
)
755 if (op
->fb
.render_targets
[i
])
756 wined3d_resource_release(op
->fb
.render_targets
[i
]->resource
);
759 if (op
->flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
760 wined3d_resource_release(op
->fb
.depth_stencil
->resource
);
763 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
764 DWORD flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
766 const struct wined3d_state
*state
= cs
->c
.state
;
767 const struct wined3d_viewport
*vp
= &state
->viewports
[0];
768 struct wined3d_rendertarget_view
*view
;
769 struct wined3d_cs_clear
*op
;
770 unsigned int rt_count
, i
;
772 rt_count
= flags
& WINED3DCLEAR_TARGET
? cs
->c
.device
->adapter
->d3d_info
.limits
.max_rt_count
: 0;
774 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]),
775 WINED3D_CS_QUEUE_DEFAULT
);
776 op
->opcode
= WINED3D_CS_OP_CLEAR
;
777 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
778 op
->rt_count
= rt_count
;
780 SetRect(&op
->draw_rect
, vp
->x
, vp
->y
, vp
->x
+ vp
->width
, vp
->y
+ vp
->height
);
781 if (state
->rasterizer_state
&& state
->rasterizer_state
->desc
.scissor
)
782 IntersectRect(&op
->draw_rect
, &op
->draw_rect
, &state
->scissor_rects
[0]);
785 op
->stencil
= stencil
;
786 op
->rect_count
= rect_count
;
787 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
789 for (i
= 0; i
< rt_count
; ++i
)
791 if ((view
= state
->fb
.render_targets
[i
]))
792 wined3d_resource_acquire(view
->resource
);
794 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
796 view
= state
->fb
.depth_stencil
;
797 wined3d_resource_acquire(view
->resource
);
800 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
803 void wined3d_device_context_emit_clear_rendertarget_view(struct wined3d_device_context
*context
,
804 struct wined3d_rendertarget_view
*view
, const RECT
*rect
, unsigned int flags
,
805 const struct wined3d_color
*color
, float depth
, unsigned int stencil
)
807 struct wined3d_cs_clear
*op
;
810 size
= FIELD_OFFSET(struct wined3d_cs_clear
, rects
[1]);
811 op
= wined3d_device_context_require_space(context
, size
, WINED3D_CS_QUEUE_DEFAULT
);
813 op
->opcode
= WINED3D_CS_OP_CLEAR
;
814 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
815 if (flags
& WINED3DCLEAR_TARGET
)
818 op
->fb
.render_targets
[0] = view
;
819 op
->fb
.depth_stencil
= NULL
;
825 op
->fb
.render_targets
[0] = NULL
;
826 op
->fb
.depth_stencil
= view
;
828 op
->stencil
= stencil
;
830 SetRect(&op
->draw_rect
, 0, 0, view
->width
, view
->height
);
832 op
->rects
[0] = *rect
;
834 wined3d_device_context_acquire_resource(context
, view
->resource
);
836 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
837 if (flags
& WINED3DCLEAR_SYNCHRONOUS
)
838 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
841 static void acquire_shader_resources(struct wined3d_device_context
*context
, unsigned int shader_mask
)
843 const struct wined3d_state
*state
= context
->state
;
844 struct wined3d_shader_sampler_map_entry
*entry
;
845 struct wined3d_shader_resource_view
*view
;
846 struct wined3d_shader
*shader
;
849 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
851 if (!(shader_mask
& (1u << i
)))
854 if (!(shader
= state
->shader
[i
]))
857 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
859 if (state
->cb
[i
][j
].buffer
)
860 wined3d_device_context_acquire_resource(context
, &state
->cb
[i
][j
].buffer
->resource
);
863 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
865 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
867 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
870 wined3d_device_context_acquire_resource(context
, view
->resource
);
875 static void release_shader_resources(const struct wined3d_state
*state
, unsigned int shader_mask
)
877 struct wined3d_shader_sampler_map_entry
*entry
;
878 struct wined3d_shader_resource_view
*view
;
879 struct wined3d_shader
*shader
;
882 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
884 if (!(shader_mask
& (1u << i
)))
887 if (!(shader
= state
->shader
[i
]))
890 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
892 if (state
->cb
[i
][j
].buffer
)
893 wined3d_resource_release(&state
->cb
[i
][j
].buffer
->resource
);
896 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
898 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
900 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
903 wined3d_resource_release(view
->resource
);
908 static void acquire_unordered_access_resources(struct wined3d_device_context
*context
,
909 const struct wined3d_shader
*shader
, struct wined3d_unordered_access_view
* const *views
)
916 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
918 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
924 wined3d_device_context_acquire_resource(context
, views
[i
]->resource
);
928 static void release_unordered_access_resources(const struct wined3d_shader
*shader
,
929 struct wined3d_unordered_access_view
* const *views
)
936 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
938 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
944 wined3d_resource_release(views
[i
]->resource
);
948 static void wined3d_cs_exec_dispatch(struct wined3d_cs
*cs
, const void *data
)
950 const struct wined3d_cs_dispatch
*op
= data
;
951 struct wined3d_state
*state
= &cs
->state
;
953 if (!state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
])
954 WARN("No compute shader bound, skipping dispatch.\n");
956 cs
->c
.device
->adapter
->adapter_ops
->adapter_dispatch_compute(cs
->c
.device
, state
, &op
->parameters
);
958 if (op
->parameters
.indirect
)
959 wined3d_resource_release(&op
->parameters
.u
.indirect
.buffer
->resource
);
961 release_shader_resources(state
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
962 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
963 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
966 static void acquire_compute_pipeline_resources(struct wined3d_device_context
*context
)
968 const struct wined3d_state
*state
= context
->state
;
970 acquire_shader_resources(context
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
971 acquire_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
972 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
975 void CDECL
wined3d_device_context_dispatch(struct wined3d_device_context
*context
,
976 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
978 struct wined3d_cs_dispatch
*op
;
980 wined3d_device_context_lock(context
);
981 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
982 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
983 op
->parameters
.indirect
= FALSE
;
984 op
->parameters
.u
.direct
.group_count_x
= group_count_x
;
985 op
->parameters
.u
.direct
.group_count_y
= group_count_y
;
986 op
->parameters
.u
.direct
.group_count_z
= group_count_z
;
988 acquire_compute_pipeline_resources(context
);
990 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
991 wined3d_device_context_unlock(context
);
994 void CDECL
wined3d_device_context_dispatch_indirect(struct wined3d_device_context
*context
,
995 struct wined3d_buffer
*buffer
, unsigned int offset
)
997 struct wined3d_cs_dispatch
*op
;
999 wined3d_device_context_lock(context
);
1000 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1001 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
1002 op
->parameters
.indirect
= TRUE
;
1003 op
->parameters
.u
.indirect
.buffer
= buffer
;
1004 op
->parameters
.u
.indirect
.offset
= offset
;
1006 acquire_compute_pipeline_resources(context
);
1007 wined3d_device_context_acquire_resource(context
, &buffer
->resource
);
1009 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1010 wined3d_device_context_unlock(context
);
1013 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
1015 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
1016 const struct wined3d_shader
*geometry_shader
;
1017 struct wined3d_device
*device
= cs
->c
.device
;
1018 int base_vertex_idx
, load_base_vertex_idx
;
1019 struct wined3d_state
*state
= &cs
->state
;
1020 const struct wined3d_cs_draw
*op
= data
;
1023 base_vertex_idx
= 0;
1024 if (!op
->parameters
.indirect
)
1026 const struct wined3d_direct_draw_parameters
*direct
= &op
->parameters
.u
.direct
;
1028 if (op
->parameters
.indexed
&& d3d_info
->draw_base_vertex_offset
)
1029 base_vertex_idx
= direct
->base_vertex_idx
;
1030 else if (!op
->parameters
.indexed
)
1031 base_vertex_idx
= direct
->start_idx
;
1034 /* ARB_draw_indirect always supports a base vertex offset. */
1035 if (!op
->parameters
.indirect
&& !d3d_info
->draw_base_vertex_offset
)
1036 load_base_vertex_idx
= op
->parameters
.u
.direct
.base_vertex_idx
;
1038 load_base_vertex_idx
= 0;
1040 if (state
->base_vertex_index
!= base_vertex_idx
)
1042 state
->base_vertex_index
= base_vertex_idx
;
1043 for (i
= 0; i
< device
->context_count
; ++i
)
1044 device
->contexts
[i
]->constant_update_mask
|= WINED3D_SHADER_CONST_BASE_VERTEX_ID
;
1047 if (state
->load_base_vertex_index
!= load_base_vertex_idx
)
1049 state
->load_base_vertex_index
= load_base_vertex_idx
;
1050 device_invalidate_state(cs
->c
.device
, STATE_BASEVERTEXINDEX
);
1053 if (state
->primitive_type
!= op
->primitive_type
)
1055 if ((geometry_shader
= state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]) && !geometry_shader
->function
)
1056 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
));
1057 if (state
->primitive_type
== WINED3D_PT_POINTLIST
|| op
->primitive_type
== WINED3D_PT_POINTLIST
)
1058 device_invalidate_state(cs
->c
.device
, STATE_POINT_ENABLE
);
1059 state
->primitive_type
= op
->primitive_type
;
1061 state
->patch_vertex_count
= op
->patch_vertex_count
;
1063 cs
->c
.device
->adapter
->adapter_ops
->adapter_draw_primitive(cs
->c
.device
, state
, &op
->parameters
);
1065 if (op
->parameters
.indirect
)
1067 struct wined3d_buffer
*buffer
= op
->parameters
.u
.indirect
.buffer
;
1068 wined3d_resource_release(&buffer
->resource
);
1071 if (op
->parameters
.indexed
)
1072 wined3d_resource_release(&state
->index_buffer
->resource
);
1073 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
1075 if (state
->streams
[i
].buffer
)
1076 wined3d_resource_release(&state
->streams
[i
].buffer
->resource
);
1078 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
1080 if (state
->stream_output
[i
].buffer
)
1081 wined3d_resource_release(&state
->stream_output
[i
].buffer
->resource
);
1083 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
1085 if (state
->textures
[i
])
1086 wined3d_resource_release(&state
->textures
[i
]->resource
);
1088 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
1090 if (state
->fb
.render_targets
[i
])
1091 wined3d_resource_release(state
->fb
.render_targets
[i
]->resource
);
1093 if (state
->fb
.depth_stencil
)
1094 wined3d_resource_release(state
->fb
.depth_stencil
->resource
);
1095 release_shader_resources(state
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
1096 release_unordered_access_resources(state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
1097 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
1100 static void acquire_graphics_pipeline_resources(struct wined3d_device_context
*context
,
1101 BOOL indexed
, const struct wined3d_d3d_info
*d3d_info
)
1103 const struct wined3d_state
*state
= context
->state
;
1107 wined3d_device_context_acquire_resource(context
, &state
->index_buffer
->resource
);
1108 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
1110 if (state
->streams
[i
].buffer
)
1111 wined3d_device_context_acquire_resource(context
, &state
->streams
[i
].buffer
->resource
);
1113 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
1115 if (state
->stream_output
[i
].buffer
)
1116 wined3d_device_context_acquire_resource(context
, &state
->stream_output
[i
].buffer
->resource
);
1118 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
1120 if (state
->textures
[i
])
1121 wined3d_device_context_acquire_resource(context
, &state
->textures
[i
]->resource
);
1123 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
1125 if (state
->fb
.render_targets
[i
])
1126 wined3d_device_context_acquire_resource(context
, state
->fb
.render_targets
[i
]->resource
);
1128 if (state
->fb
.depth_stencil
)
1129 wined3d_device_context_acquire_resource(context
, state
->fb
.depth_stencil
->resource
);
1130 acquire_shader_resources(context
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
1131 acquire_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
1132 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
1135 void wined3d_device_context_emit_draw(struct wined3d_device_context
*context
,
1136 enum wined3d_primitive_type primitive_type
, unsigned int patch_vertex_count
, int base_vertex_idx
,
1137 unsigned int start_idx
, unsigned int index_count
, unsigned int start_instance
, unsigned int instance_count
,
1140 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1141 struct wined3d_cs_draw
*op
;
1143 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1144 op
->opcode
= WINED3D_CS_OP_DRAW
;
1145 op
->primitive_type
= primitive_type
;
1146 op
->patch_vertex_count
= patch_vertex_count
;
1147 op
->parameters
.indirect
= FALSE
;
1148 op
->parameters
.u
.direct
.base_vertex_idx
= base_vertex_idx
;
1149 op
->parameters
.u
.direct
.start_idx
= start_idx
;
1150 op
->parameters
.u
.direct
.index_count
= index_count
;
1151 op
->parameters
.u
.direct
.start_instance
= start_instance
;
1152 op
->parameters
.u
.direct
.instance_count
= instance_count
;
1153 op
->parameters
.indexed
= indexed
;
1155 acquire_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1157 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1160 void CDECL
wined3d_device_context_draw_indirect(struct wined3d_device_context
*context
,
1161 struct wined3d_buffer
*buffer
, unsigned int offset
, bool indexed
)
1163 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1164 const struct wined3d_state
*state
= context
->state
;
1165 struct wined3d_cs_draw
*op
;
1167 wined3d_device_context_lock(context
);
1168 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1169 op
->opcode
= WINED3D_CS_OP_DRAW
;
1170 op
->primitive_type
= state
->primitive_type
;
1171 op
->patch_vertex_count
= state
->patch_vertex_count
;
1172 op
->parameters
.indirect
= TRUE
;
1173 op
->parameters
.u
.indirect
.buffer
= buffer
;
1174 op
->parameters
.u
.indirect
.offset
= offset
;
1175 op
->parameters
.indexed
= indexed
;
1177 acquire_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1178 wined3d_device_context_acquire_resource(context
, &buffer
->resource
);
1180 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1181 wined3d_device_context_unlock(context
);
1184 static void wined3d_cs_exec_flush(struct wined3d_cs
*cs
, const void *data
)
1186 struct wined3d_context
*context
;
1188 context
= context_acquire(cs
->c
.device
, NULL
, 0);
1189 cs
->c
.device
->adapter
->adapter_ops
->adapter_flush_context(context
);
1190 context_release(context
);
1193 static void wined3d_cs_flush(struct wined3d_device_context
*context
)
1195 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
1196 struct wined3d_cs_flush
*op
;
1198 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1199 op
->opcode
= WINED3D_CS_OP_FLUSH
;
1201 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1202 cs
->queries_flushed
= TRUE
;
1205 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
1207 const struct wined3d_cs_set_predication
*op
= data
;
1209 cs
->state
.predicate
= op
->predicate
;
1210 cs
->state
.predicate_value
= op
->value
;
1213 void wined3d_device_context_emit_set_predication(struct wined3d_device_context
*context
,
1214 struct wined3d_query
*predicate
, BOOL value
)
1216 struct wined3d_cs_set_predication
*op
;
1218 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1219 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
1220 op
->predicate
= predicate
;
1223 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1226 static void wined3d_cs_exec_set_viewports(struct wined3d_cs
*cs
, const void *data
)
1228 const struct wined3d_cs_set_viewports
*op
= data
;
1230 if (op
->viewport_count
)
1231 memcpy(cs
->state
.viewports
, op
->viewports
, op
->viewport_count
* sizeof(*op
->viewports
));
1233 memset(cs
->state
.viewports
, 0, sizeof(*cs
->state
.viewports
));
1234 cs
->state
.viewport_count
= op
->viewport_count
;
1235 device_invalidate_state(cs
->c
.device
, STATE_VIEWPORT
);
1238 void wined3d_device_context_emit_set_viewports(struct wined3d_device_context
*context
, unsigned int viewport_count
,
1239 const struct wined3d_viewport
*viewports
)
1241 struct wined3d_cs_set_viewports
*op
;
1243 op
= wined3d_device_context_require_space(context
,
1244 FIELD_OFFSET(struct wined3d_cs_set_viewports
,viewports
[viewport_count
]), WINED3D_CS_QUEUE_DEFAULT
);
1245 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORTS
;
1246 memcpy(op
->viewports
, viewports
, viewport_count
* sizeof(*viewports
));
1247 op
->viewport_count
= viewport_count
;
1249 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1252 static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs
*cs
, const void *data
)
1254 const struct wined3d_cs_set_scissor_rects
*op
= data
;
1257 memcpy(cs
->state
.scissor_rects
, op
->rects
, op
->rect_count
* sizeof(*op
->rects
));
1259 SetRectEmpty(cs
->state
.scissor_rects
);
1260 cs
->state
.scissor_rect_count
= op
->rect_count
;
1261 device_invalidate_state(cs
->c
.device
, STATE_SCISSORRECT
);
1264 void wined3d_device_context_emit_set_scissor_rects(struct wined3d_device_context
*context
,
1265 unsigned int rect_count
, const RECT
*rects
)
1267 struct wined3d_cs_set_scissor_rects
*op
;
1269 op
= wined3d_device_context_require_space(context
, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects
, rects
[rect_count
]),
1270 WINED3D_CS_QUEUE_DEFAULT
);
1271 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECTS
;
1272 memcpy(op
->rects
, rects
, rect_count
* sizeof(*rects
));
1273 op
->rect_count
= rect_count
;
1275 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1278 static void wined3d_cs_exec_set_rendertarget_views(struct wined3d_cs
*cs
, const void *data
)
1280 const struct wined3d_cs_set_rendertarget_views
*op
= data
;
1281 struct wined3d_device
*device
= cs
->c
.device
;
1284 for (i
= 0; i
< op
->count
; ++i
)
1286 struct wined3d_rendertarget_view
*prev
= cs
->state
.fb
.render_targets
[op
->start_idx
+ i
];
1287 struct wined3d_rendertarget_view
*view
= op
->views
[i
];
1288 bool prev_alpha_swizzle
, curr_alpha_swizzle
;
1289 bool prev_srgb_write
, curr_srgb_write
;
1291 cs
->state
.fb
.render_targets
[op
->start_idx
+ i
] = view
;
1293 prev_alpha_swizzle
= prev
&& prev
->format
->id
== WINED3DFMT_A8_UNORM
;
1294 curr_alpha_swizzle
= view
&& view
->format
->id
== WINED3DFMT_A8_UNORM
;
1295 if (prev_alpha_swizzle
!= curr_alpha_swizzle
)
1296 device_invalidate_state(device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1298 if (!(device
->adapter
->d3d_info
.wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
1299 || cs
->state
.render_states
[WINED3D_RS_SRGBWRITEENABLE
])
1301 prev_srgb_write
= prev
&& prev
->format_flags
& WINED3DFMT_FLAG_SRGB_WRITE
;
1302 curr_srgb_write
= view
&& view
->format_flags
& WINED3DFMT_FLAG_SRGB_WRITE
;
1303 if (prev_srgb_write
!= curr_srgb_write
)
1304 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE
));
1308 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1311 void wined3d_device_context_emit_set_rendertarget_views(struct wined3d_device_context
*context
,
1312 unsigned int start_idx
, unsigned int count
, struct wined3d_rendertarget_view
*const *views
)
1314 struct wined3d_cs_set_rendertarget_views
*op
;
1316 op
= wined3d_device_context_require_space(context
,
1317 offsetof(struct wined3d_cs_set_rendertarget_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1318 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
;
1319 op
->start_idx
= start_idx
;
1321 memcpy(op
->views
, views
, count
* sizeof(*views
));
1323 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1326 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
1328 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
1329 struct wined3d_device
*device
= cs
->c
.device
;
1330 struct wined3d_rendertarget_view
*prev
;
1332 if ((prev
= cs
->state
.fb
.depth_stencil
) && prev
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
1334 struct wined3d_texture
*prev_texture
= texture_from_resource(prev
->resource
);
1336 if (device
->swapchains
[0]->state
.desc
.flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
1337 || prev_texture
->flags
& WINED3D_TEXTURE_DISCARD
)
1338 wined3d_texture_validate_location(prev_texture
,
1339 prev
->sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
1342 cs
->state
.fb
.depth_stencil
= op
->view
;
1344 if (!prev
!= !op
->view
)
1346 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
1347 device_invalidate_state(device
, STATE_DEPTH_STENCIL
);
1348 device_invalidate_state(device
, STATE_STENCIL_REF
);
1349 device_invalidate_state(device
, STATE_RASTERIZER
);
1353 if (prev
->format
->depth_bias_scale
!= op
->view
->format
->depth_bias_scale
)
1354 device_invalidate_state(device
, STATE_RASTERIZER
);
1355 if (prev
->format
->stencil_size
!= op
->view
->format
->stencil_size
)
1356 device_invalidate_state(device
, STATE_STENCIL_REF
);
1359 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1362 void wined3d_device_context_emit_set_depth_stencil_view(struct wined3d_device_context
*context
,
1363 struct wined3d_rendertarget_view
*view
)
1365 struct wined3d_cs_set_depth_stencil_view
*op
;
1367 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1368 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
1371 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1374 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
1376 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
1378 cs
->state
.vertex_declaration
= op
->declaration
;
1379 device_invalidate_state(cs
->c
.device
, STATE_VDECL
);
1382 void wined3d_device_context_emit_set_vertex_declaration(struct wined3d_device_context
*context
,
1383 struct wined3d_vertex_declaration
*declaration
)
1385 struct wined3d_cs_set_vertex_declaration
*op
;
1387 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1388 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
1389 op
->declaration
= declaration
;
1391 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1394 static void wined3d_cs_exec_set_stream_sources(struct wined3d_cs
*cs
, const void *data
)
1396 const struct wined3d_cs_set_stream_sources
*op
= data
;
1399 for (i
= 0; i
< op
->count
; ++i
)
1401 struct wined3d_buffer
*prev
= cs
->state
.streams
[op
->start_idx
+ i
].buffer
;
1402 struct wined3d_buffer
*buffer
= op
->streams
[i
].buffer
;
1405 InterlockedIncrement(&buffer
->resource
.bind_count
);
1407 InterlockedDecrement(&prev
->resource
.bind_count
);
1410 memcpy(&cs
->state
.streams
[op
->start_idx
], op
->streams
, op
->count
* sizeof(*op
->streams
));
1411 device_invalidate_state(cs
->c
.device
, STATE_STREAMSRC
);
1414 void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context
*context
,
1415 unsigned int start_idx
, unsigned int count
, const struct wined3d_stream_state
*streams
)
1417 struct wined3d_cs_set_stream_sources
*op
;
1419 op
= wined3d_device_context_require_space(context
,
1420 offsetof(struct wined3d_cs_set_stream_sources
, streams
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1421 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCES
;
1422 op
->start_idx
= start_idx
;
1424 memcpy(op
->streams
, streams
, count
* sizeof(*streams
));
1426 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1429 static void wined3d_cs_exec_set_stream_outputs(struct wined3d_cs
*cs
, const void *data
)
1431 const struct wined3d_cs_set_stream_outputs
*op
= data
;
1434 for (i
= 0; i
< WINED3D_MAX_STREAM_OUTPUT_BUFFERS
; ++i
)
1436 struct wined3d_buffer
*prev
= cs
->state
.stream_output
[i
].buffer
;
1437 struct wined3d_buffer
*buffer
= op
->outputs
[i
].buffer
;
1440 InterlockedIncrement(&buffer
->resource
.bind_count
);
1442 InterlockedDecrement(&prev
->resource
.bind_count
);
1445 memcpy(cs
->state
.stream_output
, op
->outputs
, sizeof(op
->outputs
));
1446 device_invalidate_state(cs
->c
.device
, STATE_STREAM_OUTPUT
);
1449 void wined3d_device_context_emit_set_stream_outputs(struct wined3d_device_context
*context
,
1450 const struct wined3d_stream_output outputs
[WINED3D_MAX_STREAM_OUTPUT_BUFFERS
])
1452 struct wined3d_cs_set_stream_outputs
*op
;
1454 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1455 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUTS
;
1456 memcpy(op
->outputs
, outputs
, sizeof(op
->outputs
));
1458 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1461 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
1463 const struct wined3d_cs_set_index_buffer
*op
= data
;
1464 struct wined3d_buffer
*prev
;
1466 prev
= cs
->state
.index_buffer
;
1467 cs
->state
.index_buffer
= op
->buffer
;
1468 cs
->state
.index_format
= op
->format_id
;
1469 cs
->state
.index_offset
= op
->offset
;
1472 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1474 InterlockedDecrement(&prev
->resource
.bind_count
);
1476 device_invalidate_state(cs
->c
.device
, STATE_INDEXBUFFER
);
1479 void wined3d_device_context_emit_set_index_buffer(struct wined3d_device_context
*context
, struct wined3d_buffer
*buffer
,
1480 enum wined3d_format_id format_id
, unsigned int offset
)
1482 struct wined3d_cs_set_index_buffer
*op
;
1484 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1485 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
1486 op
->buffer
= buffer
;
1487 op
->format_id
= format_id
;
1488 op
->offset
= offset
;
1490 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1493 static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs
*cs
, const void *data
)
1495 const struct wined3d_cs_set_constant_buffers
*op
= data
;
1498 for (i
= 0; i
< op
->count
; ++i
)
1500 struct wined3d_buffer
*prev
= cs
->state
.cb
[op
->type
][op
->start_idx
+ i
].buffer
;
1501 struct wined3d_buffer
*buffer
= op
->buffers
[i
].buffer
;
1503 cs
->state
.cb
[op
->type
][op
->start_idx
+ i
] = op
->buffers
[i
];
1506 InterlockedIncrement(&buffer
->resource
.bind_count
);
1508 InterlockedDecrement(&prev
->resource
.bind_count
);
1511 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1514 void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context
*context
,
1515 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1516 const struct wined3d_constant_buffer_state
*buffers
)
1518 struct wined3d_cs_set_constant_buffers
*op
;
1520 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_constant_buffers
, buffers
[count
]),
1521 WINED3D_CS_QUEUE_DEFAULT
);
1522 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFERS
;
1524 op
->start_idx
= start_idx
;
1526 memcpy(op
->buffers
, buffers
, count
* sizeof(*buffers
));
1528 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1531 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
1533 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
1534 const struct wined3d_cs_set_texture
*op
= data
;
1535 struct wined3d_texture
*prev
;
1536 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
1538 prev
= cs
->state
.textures
[op
->stage
];
1539 cs
->state
.textures
[op
->stage
] = op
->texture
;
1543 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
1544 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
1545 unsigned int old_fmt_flags
= prev
? prev
->resource
.format_flags
: 0;
1546 unsigned int new_fmt_flags
= op
->texture
->resource
.format_flags
;
1548 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
1549 op
->texture
->sampler
= op
->stage
;
1551 if (!prev
|| wined3d_texture_gl(op
->texture
)->target
!= wined3d_texture_gl(prev
)->target
1552 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
1553 && !(can_use_texture_swizzle(d3d_info
, new_format
) && can_use_texture_swizzle(d3d_info
, old_format
)))
1554 || (new_fmt_flags
& WINED3DFMT_FLAG_SHADOW
) != (old_fmt_flags
& WINED3DFMT_FLAG_SHADOW
))
1555 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1557 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1559 /* The source arguments for color and alpha ops have different
1560 * meanings when a NULL texture is bound, so the COLOR_OP and
1561 * ALPHA_OP have to be dirtified. */
1562 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1563 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1566 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1567 new_use_color_key
= TRUE
;
1572 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
1576 /* Search for other stages the texture is bound to. Shouldn't
1577 * happen if applications bind textures to a single stage only. */
1578 TRACE("Searching for other stages the texture is bound to.\n");
1579 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
1581 if (cs
->state
.textures
[i
] == prev
)
1583 TRACE("Texture is also bound to stage %u.\n", i
);
1590 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1592 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1593 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1596 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1597 old_use_color_key
= TRUE
;
1600 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->stage
));
1602 if (new_use_color_key
!= old_use_color_key
)
1603 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1605 if (new_use_color_key
)
1606 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1609 void wined3d_device_context_emit_set_texture(struct wined3d_device_context
*context
, unsigned int stage
,
1610 struct wined3d_texture
*texture
)
1612 struct wined3d_cs_set_texture
*op
;
1614 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1615 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
1617 op
->texture
= texture
;
1619 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1622 static void wined3d_cs_exec_set_shader_resource_views(struct wined3d_cs
*cs
, const void *data
)
1624 const struct wined3d_cs_set_shader_resource_views
*op
= data
;
1627 for (i
= 0; i
< op
->count
; ++i
)
1629 struct wined3d_shader_resource_view
*prev
= cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
];
1630 struct wined3d_shader_resource_view
*view
= op
->views
[i
];
1632 cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
] = view
;
1635 InterlockedIncrement(&view
->resource
->bind_count
);
1637 InterlockedDecrement(&prev
->resource
->bind_count
);
1640 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1641 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1643 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1646 void wined3d_device_context_emit_set_shader_resource_views(struct wined3d_device_context
*context
,
1647 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1648 struct wined3d_shader_resource_view
*const *views
)
1650 struct wined3d_cs_set_shader_resource_views
*op
;
1652 op
= wined3d_device_context_require_space(context
,
1653 offsetof(struct wined3d_cs_set_shader_resource_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1654 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
;
1656 op
->start_idx
= start_idx
;
1658 memcpy(op
->views
, views
, count
* sizeof(*views
));
1660 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1663 static void wined3d_cs_exec_set_unordered_access_views(struct wined3d_cs
*cs
, const void *data
)
1665 const struct wined3d_cs_set_unordered_access_views
*op
= data
;
1668 for (i
= 0; i
< op
->count
; ++i
)
1670 struct wined3d_unordered_access_view
*prev
= cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
];
1671 struct wined3d_unordered_access_view
*view
= op
->uavs
[i
].view
;
1672 unsigned int initial_count
= op
->uavs
[i
].initial_count
;
1674 cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
] = view
;
1677 InterlockedIncrement(&view
->resource
->bind_count
);
1679 InterlockedDecrement(&prev
->resource
->bind_count
);
1681 if (view
&& initial_count
!= ~0u)
1682 wined3d_unordered_access_view_set_counter(view
, initial_count
);
1685 device_invalidate_state(cs
->c
.device
, STATE_UNORDERED_ACCESS_VIEW_BINDING(op
->pipeline
));
1688 void wined3d_device_context_emit_set_unordered_access_views(struct wined3d_device_context
*context
,
1689 enum wined3d_pipeline pipeline
, unsigned int start_idx
, unsigned int count
,
1690 struct wined3d_unordered_access_view
*const *views
, const unsigned int *initial_counts
)
1692 struct wined3d_cs_set_unordered_access_views
*op
;
1695 op
= wined3d_device_context_require_space(context
,
1696 offsetof(struct wined3d_cs_set_unordered_access_views
, uavs
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1697 op
->opcode
= WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
;
1698 op
->pipeline
= pipeline
;
1699 op
->start_idx
= start_idx
;
1701 for (i
= 0; i
< count
; ++i
)
1703 op
->uavs
[i
].view
= views
[i
];
1704 op
->uavs
[i
].initial_count
= initial_counts
? initial_counts
[i
] : ~0u;
1707 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1710 static void wined3d_cs_exec_set_samplers(struct wined3d_cs
*cs
, const void *data
)
1712 const struct wined3d_cs_set_samplers
*op
= data
;
1715 for (i
= 0; i
< op
->count
; ++i
)
1716 cs
->state
.sampler
[op
->type
][op
->start_idx
+ i
] = op
->samplers
[i
];
1718 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1719 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1721 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1724 void wined3d_device_context_emit_set_samplers(struct wined3d_device_context
*context
, enum wined3d_shader_type type
,
1725 unsigned int start_idx
, unsigned int count
, struct wined3d_sampler
*const *samplers
)
1727 struct wined3d_cs_set_samplers
*op
;
1729 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_samplers
, samplers
[count
]),
1730 WINED3D_CS_QUEUE_DEFAULT
);
1731 op
->opcode
= WINED3D_CS_OP_SET_SAMPLERS
;
1733 op
->start_idx
= start_idx
;
1735 memcpy(op
->samplers
, samplers
, count
* sizeof(*samplers
));
1737 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1740 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
1742 const struct wined3d_cs_set_shader
*op
= data
;
1744 /* CB binding may have been skipped earlier if the shader wasn't set, so make it happen. */
1745 if (!cs
->state
.shader
[op
->type
] && op
->shader
)
1746 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1747 cs
->state
.shader
[op
->type
] = op
->shader
;
1748 device_invalidate_state(cs
->c
.device
, STATE_SHADER(op
->type
));
1749 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1750 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1752 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1755 void wined3d_device_context_emit_set_shader(struct wined3d_device_context
*context
,
1756 enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
1758 struct wined3d_cs_set_shader
*op
;
1760 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1761 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
1763 op
->shader
= shader
;
1765 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1768 static void wined3d_cs_exec_set_blend_state(struct wined3d_cs
*cs
, const void *data
)
1770 const struct wined3d_cs_set_blend_state
*op
= data
;
1771 struct wined3d_state
*state
= &cs
->state
;
1773 if (state
->blend_state
!= op
->state
)
1775 state
->blend_state
= op
->state
;
1776 device_invalidate_state(cs
->c
.device
, STATE_BLEND
);
1778 state
->blend_factor
= op
->factor
;
1779 device_invalidate_state(cs
->c
.device
, STATE_BLEND_FACTOR
);
1780 state
->sample_mask
= op
->sample_mask
;
1781 device_invalidate_state(cs
->c
.device
, STATE_SAMPLE_MASK
);
1784 void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context
*context
,
1785 struct wined3d_blend_state
*state
, const struct wined3d_color
*blend_factor
, unsigned int sample_mask
)
1787 struct wined3d_cs_set_blend_state
*op
;
1789 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1790 op
->opcode
= WINED3D_CS_OP_SET_BLEND_STATE
;
1792 op
->factor
= *blend_factor
;
1793 op
->sample_mask
= sample_mask
;
1795 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1798 static void wined3d_cs_exec_set_depth_stencil_state(struct wined3d_cs
*cs
, const void *data
)
1800 const struct wined3d_cs_set_depth_stencil_state
*op
= data
;
1801 struct wined3d_state
*state
= &cs
->state
;
1803 if (state
->depth_stencil_state
!= op
->state
)
1805 state
->depth_stencil_state
= op
->state
;
1806 device_invalidate_state(cs
->c
.device
, STATE_DEPTH_STENCIL
);
1808 state
->stencil_ref
= op
->stencil_ref
;
1809 device_invalidate_state(cs
->c
.device
, STATE_STENCIL_REF
);
1812 void wined3d_device_context_emit_set_depth_stencil_state(struct wined3d_device_context
*context
,
1813 struct wined3d_depth_stencil_state
*state
, unsigned int stencil_ref
)
1815 struct wined3d_cs_set_depth_stencil_state
*op
;
1817 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1818 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
;
1820 op
->stencil_ref
= stencil_ref
;
1822 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1825 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs
, const void *data
)
1827 const struct wined3d_cs_set_rasterizer_state
*op
= data
;
1829 cs
->state
.rasterizer_state
= op
->state
;
1830 device_invalidate_state(cs
->c
.device
, STATE_RASTERIZER
);
1833 void wined3d_device_context_emit_set_rasterizer_state(struct wined3d_device_context
*context
,
1834 struct wined3d_rasterizer_state
*rasterizer_state
)
1836 struct wined3d_cs_set_rasterizer_state
*op
;
1838 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1839 op
->opcode
= WINED3D_CS_OP_SET_RASTERIZER_STATE
;
1840 op
->state
= rasterizer_state
;
1842 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1845 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
1847 const struct wined3d_cs_set_render_state
*op
= data
;
1849 cs
->state
.render_states
[op
->state
] = op
->value
;
1850 device_invalidate_state(cs
->c
.device
, STATE_RENDER(op
->state
));
1853 void wined3d_device_context_emit_set_render_state(struct wined3d_device_context
*context
,
1854 enum wined3d_render_state state
, unsigned int value
)
1856 struct wined3d_cs_set_render_state
*op
;
1858 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1859 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
1863 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1866 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
1868 const struct wined3d_cs_set_texture_state
*op
= data
;
1870 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
1871 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
1874 void wined3d_device_context_emit_set_texture_state(struct wined3d_device_context
*context
, unsigned int stage
,
1875 enum wined3d_texture_stage_state state
, unsigned int value
)
1877 struct wined3d_cs_set_texture_state
*op
;
1879 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1880 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
1885 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1888 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
1890 const struct wined3d_cs_set_sampler_state
*op
= data
;
1892 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
1893 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->sampler_idx
));
1896 void wined3d_device_context_emit_set_sampler_state(struct wined3d_device_context
*context
, unsigned int sampler_idx
,
1897 enum wined3d_sampler_state state
, unsigned int value
)
1899 struct wined3d_cs_set_sampler_state
*op
;
1901 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1902 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
1903 op
->sampler_idx
= sampler_idx
;
1907 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1910 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
1912 const struct wined3d_cs_set_transform
*op
= data
;
1914 cs
->state
.transforms
[op
->state
] = op
->matrix
;
1915 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->c
.device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
1916 device_invalidate_state(cs
->c
.device
, STATE_TRANSFORM(op
->state
));
1919 void wined3d_device_context_emit_set_transform(struct wined3d_device_context
*context
,
1920 enum wined3d_transform_state state
, const struct wined3d_matrix
*matrix
)
1922 struct wined3d_cs_set_transform
*op
;
1924 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1925 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
1927 op
->matrix
= *matrix
;
1929 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1932 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
1934 const struct wined3d_cs_set_clip_plane
*op
= data
;
1936 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
1937 device_invalidate_state(cs
->c
.device
, STATE_CLIPPLANE(op
->plane_idx
));
1940 void wined3d_device_context_emit_set_clip_plane(struct wined3d_device_context
*context
,
1941 unsigned int plane_idx
, const struct wined3d_vec4
*plane
)
1943 struct wined3d_cs_set_clip_plane
*op
;
1945 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1946 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
1947 op
->plane_idx
= plane_idx
;
1950 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1953 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
1955 const struct wined3d_cs_set_color_key
*op
= data
;
1956 struct wined3d_texture
*texture
= op
->texture
;
1962 case WINED3D_CKEY_DST_BLT
:
1963 texture
->async
.dst_blt_color_key
= op
->color_key
;
1964 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
1967 case WINED3D_CKEY_DST_OVERLAY
:
1968 texture
->async
.dst_overlay_color_key
= op
->color_key
;
1969 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
1972 case WINED3D_CKEY_SRC_BLT
:
1973 if (texture
== cs
->state
.textures
[0])
1975 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1976 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
1977 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1980 texture
->async
.src_blt_color_key
= op
->color_key
;
1981 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
1984 case WINED3D_CKEY_SRC_OVERLAY
:
1985 texture
->async
.src_overlay_color_key
= op
->color_key
;
1986 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
1994 case WINED3D_CKEY_DST_BLT
:
1995 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
1998 case WINED3D_CKEY_DST_OVERLAY
:
1999 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
2002 case WINED3D_CKEY_SRC_BLT
:
2003 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
2004 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
2006 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
2009 case WINED3D_CKEY_SRC_OVERLAY
:
2010 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
2016 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
2017 WORD flags
, const struct wined3d_color_key
*color_key
)
2019 struct wined3d_cs_set_color_key
*op
;
2021 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2022 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
2023 op
->texture
= texture
;
2027 op
->color_key
= *color_key
;
2033 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2036 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
2038 const struct wined3d_cs_set_material
*op
= data
;
2040 cs
->state
.material
= op
->material
;
2041 device_invalidate_state(cs
->c
.device
, STATE_MATERIAL
);
2044 void wined3d_device_context_emit_set_material(struct wined3d_device_context
*context
,
2045 const struct wined3d_material
*material
)
2047 struct wined3d_cs_set_material
*op
;
2049 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2050 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
2051 op
->material
= *material
;
2053 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2056 static void wined3d_cs_exec_set_light(struct wined3d_cs
*cs
, const void *data
)
2058 const struct wined3d_cs_set_light
*op
= data
;
2059 struct wined3d_light_info
*light_info
;
2060 unsigned int light_idx
, hash_idx
;
2062 light_idx
= op
->light
.OriginalIndex
;
2064 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, light_idx
)))
2066 TRACE("Adding new light.\n");
2067 if (!(light_info
= heap_alloc_zero(sizeof(*light_info
))))
2069 ERR("Failed to allocate light info.\n");
2073 hash_idx
= LIGHTMAP_HASHFUNC(light_idx
);
2074 list_add_head(&cs
->state
.light_state
.light_map
[hash_idx
], &light_info
->entry
);
2075 light_info
->glIndex
= -1;
2076 light_info
->OriginalIndex
= light_idx
;
2079 if (light_info
->glIndex
!= -1)
2081 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
2082 device_invalidate_state(cs
->c
.device
, STATE_LIGHT_TYPE
);
2083 device_invalidate_state(cs
->c
.device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
2086 light_info
->OriginalParms
= op
->light
.OriginalParms
;
2087 light_info
->position
= op
->light
.position
;
2088 light_info
->direction
= op
->light
.direction
;
2089 light_info
->exponent
= op
->light
.exponent
;
2090 light_info
->cutoff
= op
->light
.cutoff
;
2093 void wined3d_device_context_emit_set_light(struct wined3d_device_context
*context
,
2094 const struct wined3d_light_info
*light
)
2096 struct wined3d_cs_set_light
*op
;
2098 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2099 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
2102 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2105 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
2107 const struct wined3d_cs_set_light_enable
*op
= data
;
2108 struct wined3d_device
*device
= cs
->c
.device
;
2109 struct wined3d_light_info
*light_info
;
2112 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, op
->idx
)))
2114 ERR("Light doesn't exist.\n");
2118 prev_idx
= light_info
->glIndex
;
2119 wined3d_light_state_enable_light(&cs
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
);
2120 if (light_info
->glIndex
!= prev_idx
)
2122 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
2123 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
2127 void wined3d_device_context_emit_set_light_enable(struct wined3d_device_context
*context
, unsigned int idx
, BOOL enable
)
2129 struct wined3d_cs_set_light_enable
*op
;
2131 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2132 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
2134 op
->enable
= enable
;
2136 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2139 static void wined3d_cs_exec_set_feature_level(struct wined3d_cs
*cs
, const void *data
)
2141 const struct wined3d_cs_set_feature_level
*op
= data
;
2143 cs
->state
.feature_level
= op
->level
;
2146 void wined3d_device_context_emit_set_feature_level(struct wined3d_device_context
*context
,
2147 enum wined3d_feature_level level
)
2149 struct wined3d_cs_set_feature_level
*op
;
2151 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2152 op
->opcode
= WINED3D_CS_OP_SET_FEATURE_LEVEL
;
2155 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2164 wined3d_cs_push_constant_info
[] =
2166 /* WINED3D_PUSH_CONSTANTS_VS_F */
2167 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
2168 /* WINED3D_PUSH_CONSTANTS_PS_F */
2169 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
2170 /* WINED3D_PUSH_CONSTANTS_VS_I */
2171 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
2172 /* WINED3D_PUSH_CONSTANTS_PS_I */
2173 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
2174 /* WINED3D_PUSH_CONSTANTS_VS_B */
2175 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
2176 /* WINED3D_PUSH_CONSTANTS_PS_B */
2177 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
2180 static void wined3d_cs_st_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2181 unsigned int start_idx
, unsigned int count
, const void *constants
)
2183 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2184 struct wined3d_device
*device
= cs
->c
.device
;
2185 unsigned int context_count
;
2189 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
2190 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
2191 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
2192 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
2194 offset
= wined3d_cs_push_constant_info
[p
].offset
+ start_idx
* wined3d_cs_push_constant_info
[p
].size
;
2195 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* wined3d_cs_push_constant_info
[p
].size
);
2196 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
2198 device
->contexts
[i
]->constant_update_mask
|= wined3d_cs_push_constant_info
[p
].mask
;
2202 static void wined3d_cs_exec_push_constants(struct wined3d_cs
*cs
, const void *data
)
2204 const struct wined3d_cs_push_constants
*op
= data
;
2206 wined3d_cs_st_push_constants(&cs
->c
, op
->type
, op
->start_idx
, op
->count
, op
->constants
);
2209 static void wined3d_cs_mt_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2210 unsigned int start_idx
, unsigned int count
, const void *constants
)
2212 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2213 struct wined3d_cs_push_constants
*op
;
2216 size
= count
* wined3d_cs_push_constant_info
[p
].size
;
2217 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_push_constants
, constants
[size
]),
2218 WINED3D_CS_QUEUE_DEFAULT
);
2219 op
->opcode
= WINED3D_CS_OP_PUSH_CONSTANTS
;
2221 op
->start_idx
= start_idx
;
2223 memcpy(op
->constants
, constants
, size
);
2225 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2228 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
2230 const struct wined3d_device
*device
= cs
->c
.device
;
2231 const struct wined3d_cs_reset_state
*op
= data
;
2232 const struct wined3d_state_entry
*state_table
;
2235 state_cleanup(&cs
->state
);
2236 wined3d_state_reset(&cs
->state
, &device
->adapter
->d3d_info
);
2239 state_table
= device
->state_table
;
2240 for (state
= 0; state
<= STATE_HIGHEST
; ++state
)
2242 if (state_table
[state
].representative
)
2243 device_invalidate_state(device
, state
);
2248 void wined3d_device_context_emit_reset_state(struct wined3d_device_context
*context
, bool invalidate
)
2250 struct wined3d_cs_reset_state
*op
;
2252 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2253 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
2254 op
->invalidate
= invalidate
;
2256 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2259 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
2261 const struct wined3d_cs_callback
*op
= data
;
2263 op
->callback(op
->object
);
2266 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2268 struct wined3d_cs_callback
*op
;
2270 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2271 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
2272 op
->callback
= callback
;
2273 op
->object
= object
;
2275 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2278 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2280 wined3d_cs_emit_callback(cs
, callback
, object
);
2283 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2285 wined3d_cs_emit_callback(cs
, callback
, object
);
2288 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
2290 const struct wined3d_cs_query_issue
*op
= data
;
2291 struct wined3d_query
*query
= op
->query
;
2294 poll
= query
->query_ops
->query_issue(query
, op
->flags
);
2299 if (poll
&& list_empty(&query
->poll_list_entry
))
2301 if (query
->buffer_object
)
2302 InterlockedIncrement(&query
->counter_retrieved
);
2304 list_add_tail(&cs
->query_poll_list
, &query
->poll_list_entry
);
2308 /* This can happen if occlusion queries are restarted. This discards the
2309 * old result, since polling it could result in a GL error. */
2310 if ((op
->flags
& WINED3DISSUE_BEGIN
) && !poll
&& !list_empty(&query
->poll_list_entry
))
2312 list_remove(&query
->poll_list_entry
);
2313 list_init(&query
->poll_list_entry
);
2314 InterlockedIncrement(&query
->counter_retrieved
);
2318 /* This can happen when an occlusion query is ended without being started,
2319 * in which case we don't want to poll, but still have to counter-balance
2320 * the increment of the main counter.
2322 * This can also happen if an event query is re-issued before the first
2323 * fence was reached. In this case the query is already in the list and
2324 * the poll function will check the new fence. We have to counter-balance
2325 * the discarded increment. */
2326 if (op
->flags
& WINED3DISSUE_END
)
2327 InterlockedIncrement(&query
->counter_retrieved
);
2330 static void wined3d_cs_issue_query(struct wined3d_device_context
*context
,
2331 struct wined3d_query
*query
, unsigned int flags
)
2333 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2334 struct wined3d_cs_query_issue
*op
;
2336 if (flags
& WINED3DISSUE_END
)
2337 ++query
->counter_main
;
2339 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2340 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
2344 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2345 cs
->queries_flushed
= FALSE
;
2347 if (flags
& WINED3DISSUE_BEGIN
)
2348 query
->state
= QUERY_BUILDING
;
2350 query
->state
= QUERY_SIGNALLED
;
2353 static void wined3d_cs_acquire_command_list(struct wined3d_device_context
*context
, struct wined3d_command_list
*list
)
2355 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2358 if (list
->query_count
)
2360 cs
->queries_flushed
= FALSE
;
2362 for (i
= 0; i
< list
->query_count
; ++i
)
2364 if (list
->queries
[i
].flags
& WINED3DISSUE_END
)
2366 list
->queries
[i
].query
->counter_main
++;
2367 list
->queries
[i
].query
->state
= QUERY_SIGNALLED
;
2371 list
->queries
[i
].query
->state
= QUERY_BUILDING
;
2376 for (i
= 0; i
< list
->resource_count
; ++i
)
2377 wined3d_resource_acquire(list
->resources
[i
]);
2379 for (i
= 0; i
< list
->command_list_count
; ++i
)
2380 wined3d_cs_acquire_command_list(context
, list
->command_lists
[i
]);
2382 for (i
= 0; i
< list
->upload_count
; ++i
)
2383 invalidate_client_address(list
->uploads
[i
].resource
);
2386 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
2388 const struct wined3d_cs_preload_resource
*op
= data
;
2389 struct wined3d_resource
*resource
= op
->resource
;
2391 resource
->resource_ops
->resource_preload(resource
);
2392 wined3d_resource_release(resource
);
2395 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2397 struct wined3d_cs_preload_resource
*op
;
2399 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2400 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
2401 op
->resource
= resource
;
2403 wined3d_resource_acquire(resource
);
2405 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2408 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
2410 const struct wined3d_cs_unload_resource
*op
= data
;
2411 struct wined3d_resource
*resource
= op
->resource
;
2413 resource
->resource_ops
->resource_unload(resource
);
2414 wined3d_resource_release(resource
);
2417 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2419 struct wined3d_cs_unload_resource
*op
;
2421 invalidate_client_address(resource
);
2423 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2424 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
2425 op
->resource
= resource
;
2427 wined3d_resource_acquire(resource
);
2429 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2432 static void wined3d_device_context_upload_bo(struct wined3d_device_context
*context
,
2433 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2434 const struct upload_bo
*bo
, unsigned int row_pitch
, unsigned int slice_pitch
)
2436 struct wined3d_cs_update_sub_resource
*op
;
2438 TRACE("context %p, resource %p, sub_resource_idx %u, box %s, bo %s, flags %#x, row_pitch %u, slice_pitch %u.\n",
2439 context
, resource
, sub_resource_idx
, debug_box(box
),
2440 debug_const_bo_address(&bo
->addr
), bo
->flags
, row_pitch
, slice_pitch
);
2442 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2443 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2444 op
->resource
= resource
;
2445 op
->sub_resource_idx
= sub_resource_idx
;
2448 op
->row_pitch
= row_pitch
;
2449 op
->slice_pitch
= slice_pitch
;
2451 wined3d_device_context_acquire_resource(context
, resource
);
2453 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2456 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
2458 const struct wined3d_cs_map
*op
= data
;
2459 struct wined3d_resource
*resource
= op
->resource
;
2461 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
2462 op
->sub_resource_idx
, op
->map_ptr
, op
->box
, op
->flags
);
2465 HRESULT
wined3d_device_context_emit_map(struct wined3d_device_context
*context
,
2466 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
2467 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
2469 struct wined3d_cs_map
*op
;
2472 /* Mapping resources from the worker thread isn't an issue by itself, but
2473 * increasing the map count would be visible to applications. */
2474 wined3d_not_from_cs(context
->device
->cs
);
2476 if ((flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2477 && context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, map_desc
, box
, flags
))
2479 TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n",
2480 map_desc
->data
, map_desc
->row_pitch
, map_desc
->slice_pitch
);
2484 wined3d_resource_wait_idle(resource
);
2486 /* We might end up invalidating the resource on the CS thread. */
2487 invalidate_client_address(resource
);
2489 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2490 return E_OUTOFMEMORY
;
2491 op
->opcode
= WINED3D_CS_OP_MAP
;
2492 op
->resource
= resource
;
2493 op
->sub_resource_idx
= sub_resource_idx
;
2494 op
->map_ptr
= &map_desc
->data
;
2499 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2500 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2503 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
2504 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
2508 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
2510 const struct wined3d_cs_unmap
*op
= data
;
2511 struct wined3d_resource
*resource
= op
->resource
;
2513 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
2516 HRESULT
wined3d_device_context_emit_unmap(struct wined3d_device_context
*context
,
2517 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
2519 struct wined3d_cs_unmap
*op
;
2520 struct wined3d_box box
;
2521 struct upload_bo bo
;
2524 if (context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
))
2526 unsigned int row_pitch
, slice_pitch
;
2528 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
, &row_pitch
, &slice_pitch
);
2529 if (bo
.flags
& UPLOAD_BO_UPLOAD_ON_UNMAP
)
2530 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
, row_pitch
, slice_pitch
);
2534 wined3d_not_from_cs(context
->device
->cs
);
2536 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2537 return E_OUTOFMEMORY
;
2538 op
->opcode
= WINED3D_CS_OP_UNMAP
;
2539 op
->resource
= resource
;
2540 op
->sub_resource_idx
= sub_resource_idx
;
2543 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2544 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2549 static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2551 const struct wined3d_cs_blt_sub_resource
*op
= data
;
2553 if (op
->dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
2555 wined3d_buffer_copy(buffer_from_resource(op
->dst_resource
), op
->dst_box
.left
,
2556 buffer_from_resource(op
->src_resource
), op
->src_box
.left
,
2557 op
->src_box
.right
- op
->src_box
.left
);
2559 else if (op
->dst_resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
2561 struct wined3d_texture
*src_texture
, *dst_texture
;
2562 unsigned int level
, update_w
, update_h
, update_d
;
2563 unsigned int row_pitch
, slice_pitch
;
2564 struct wined3d_context
*context
;
2565 struct wined3d_bo_address addr
;
2566 unsigned int location
;
2568 if (op
->flags
& ~WINED3D_BLT_RAW
)
2570 FIXME("Flags %#x not implemented for %s resources.\n",
2571 op
->flags
, debug_d3dresourcetype(op
->dst_resource
->type
));
2575 if (!(op
->flags
& WINED3D_BLT_RAW
) && op
->src_resource
->format
!= op
->dst_resource
->format
)
2577 FIXME("Format conversion not implemented for %s resources.\n",
2578 debug_d3dresourcetype(op
->dst_resource
->type
));
2582 update_w
= op
->dst_box
.right
- op
->dst_box
.left
;
2583 update_h
= op
->dst_box
.bottom
- op
->dst_box
.top
;
2584 update_d
= op
->dst_box
.back
- op
->dst_box
.front
;
2585 if (op
->src_box
.right
- op
->src_box
.left
!= update_w
2586 || op
->src_box
.bottom
- op
->src_box
.top
!= update_h
2587 || op
->src_box
.back
- op
->src_box
.front
!= update_d
)
2589 FIXME("Stretching not implemented for %s resources.\n",
2590 debug_d3dresourcetype(op
->dst_resource
->type
));
2594 dst_texture
= texture_from_resource(op
->dst_resource
);
2595 src_texture
= texture_from_resource(op
->src_resource
);
2597 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2599 location
= src_texture
->resource
.map_binding
;
2600 if (location
== WINED3D_LOCATION_SYSMEM
2601 && wined3d_texture_can_use_pbo(src_texture
, &context
->device
->adapter
->d3d_info
))
2602 location
= WINED3D_LOCATION_BUFFER
;
2604 if (!wined3d_texture_load_location(src_texture
, op
->src_sub_resource_idx
,
2607 ERR("Failed to load source sub-resource into %s.\n",
2608 wined3d_debug_location(location
));
2609 context_release(context
);
2613 level
= op
->dst_sub_resource_idx
% dst_texture
->level_count
;
2614 if (update_w
== wined3d_texture_get_level_width(dst_texture
, level
)
2615 && update_h
== wined3d_texture_get_level_height(dst_texture
, level
)
2616 && update_d
== wined3d_texture_get_level_depth(dst_texture
, level
))
2618 wined3d_texture_prepare_location(dst_texture
, op
->dst_sub_resource_idx
,
2619 context
, WINED3D_LOCATION_TEXTURE_RGB
);
2621 else if (!wined3d_texture_load_location(dst_texture
, op
->dst_sub_resource_idx
,
2622 context
, WINED3D_LOCATION_TEXTURE_RGB
))
2624 ERR("Failed to load destination sub-resource.\n");
2625 context_release(context
);
2629 wined3d_texture_get_memory(src_texture
, op
->src_sub_resource_idx
, &addr
, location
);
2630 wined3d_texture_get_pitch(src_texture
, op
->src_sub_resource_idx
% src_texture
->level_count
,
2631 &row_pitch
, &slice_pitch
);
2633 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&addr
),
2634 dst_texture
->resource
.format
, &op
->src_box
, row_pitch
, slice_pitch
, dst_texture
,
2635 op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
2636 op
->dst_box
.left
, op
->dst_box
.top
, op
->dst_box
.front
);
2637 wined3d_texture_validate_location(dst_texture
, op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2638 wined3d_texture_invalidate_location(dst_texture
, op
->dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2640 context_release(context
);
2644 if (FAILED(texture2d_blt(texture_from_resource(op
->dst_resource
), op
->dst_sub_resource_idx
,
2645 &op
->dst_box
, texture_from_resource(op
->src_resource
), op
->src_sub_resource_idx
,
2646 &op
->src_box
, op
->flags
, &op
->fx
, op
->filter
)))
2647 FIXME("Blit failed.\n");
2651 if (op
->src_resource
)
2652 wined3d_resource_release(op
->src_resource
);
2653 wined3d_resource_release(op
->dst_resource
);
2656 void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context
*context
,
2657 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
, const struct wined3d_box
*dst_box
,
2658 struct wined3d_resource
*src_resource
, unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
,
2659 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
2661 struct wined3d_cs_blt_sub_resource
*op
;
2663 /* If we are replacing the whole resource, the CS thread might discard and
2664 * rename the buffer object, in which case ours is no longer valid. */
2665 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
&& dst_box
->right
- dst_box
->left
== dst_resource
->size
)
2666 invalidate_client_address(dst_resource
);
2668 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2669 op
->opcode
= WINED3D_CS_OP_BLT_SUB_RESOURCE
;
2670 op
->dst_resource
= dst_resource
;
2671 op
->dst_sub_resource_idx
= dst_sub_resource_idx
;
2672 op
->dst_box
= *dst_box
;
2673 op
->src_resource
= src_resource
;
2674 op
->src_sub_resource_idx
= src_sub_resource_idx
;
2675 op
->src_box
= *src_box
;
2680 memset(&op
->fx
, 0, sizeof(op
->fx
));
2681 op
->filter
= filter
;
2683 wined3d_device_context_acquire_resource(context
, dst_resource
);
2685 wined3d_device_context_acquire_resource(context
, src_resource
);
2687 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2688 if (flags
& WINED3D_BLT_SYNCHRONOUS
)
2689 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
2692 static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2694 const struct wined3d_cs_update_sub_resource
*op
= data
;
2695 struct wined3d_resource
*resource
= op
->resource
;
2696 const struct wined3d_box
*box
= &op
->box
;
2697 unsigned int width
, height
, depth
, level
;
2698 struct wined3d_context
*context
;
2699 struct wined3d_texture
*texture
;
2700 struct wined3d_box src_box
;
2702 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2704 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2706 wined3d_buffer_update_sub_resource(buffer_from_resource(resource
),
2707 context
, &op
->bo
, box
->left
, box
->right
- box
->left
);
2711 texture
= wined3d_texture_from_resource(resource
);
2713 level
= op
->sub_resource_idx
% texture
->level_count
;
2714 width
= wined3d_texture_get_level_width(texture
, level
);
2715 height
= wined3d_texture_get_level_height(texture
, level
);
2716 depth
= wined3d_texture_get_level_depth(texture
, level
);
2718 /* Only load the sub-resource for partial updates. */
2719 if (!box
->left
&& !box
->top
&& !box
->front
2720 && box
->right
== width
&& box
->bottom
== height
&& box
->back
== depth
)
2721 wined3d_texture_prepare_location(texture
, op
->sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
2723 wined3d_texture_load_location(texture
, op
->sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
2725 wined3d_box_set(&src_box
, 0, 0, box
->right
- box
->left
, box
->bottom
- box
->top
, 0, box
->back
- box
->front
);
2726 texture
->texture_ops
->texture_upload_data(context
, &op
->bo
.addr
, texture
->resource
.format
, &src_box
,
2727 op
->row_pitch
, op
->slice_pitch
, texture
, op
->sub_resource_idx
,
2728 WINED3D_LOCATION_TEXTURE_RGB
, box
->left
, box
->top
, box
->front
);
2730 wined3d_texture_validate_location(texture
, op
->sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2731 wined3d_texture_invalidate_location(texture
, op
->sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2734 context_release(context
);
2736 wined3d_resource_release(resource
);
2739 void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_context
*context
,
2740 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2741 const void *data
, unsigned int row_pitch
, unsigned int slice_pitch
)
2743 struct wined3d_cs_update_sub_resource
*op
;
2744 struct wined3d_map_desc map_desc
;
2745 struct wined3d_box dummy_box
;
2746 struct upload_bo bo
;
2748 /* If we are replacing the whole resource, the CS thread might discard and
2749 * rename the buffer object, in which case ours is no longer valid. */
2750 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& box
->right
- box
->left
== resource
->size
)
2751 invalidate_client_address(resource
);
2753 if (context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, &map_desc
, box
, WINED3D_MAP_WRITE
))
2755 wined3d_format_copy_data(resource
->format
, data
, row_pitch
, slice_pitch
, map_desc
.data
, map_desc
.row_pitch
,
2756 map_desc
.slice_pitch
, box
->right
- box
->left
, box
->bottom
- box
->top
, box
->back
- box
->front
);
2757 context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &dummy_box
, &bo
);
2758 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
,
2759 box
, &bo
, map_desc
.row_pitch
, map_desc
.slice_pitch
);
2763 wined3d_resource_wait_idle(resource
);
2765 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2766 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2767 op
->resource
= resource
;
2768 op
->sub_resource_idx
= sub_resource_idx
;
2770 op
->bo
.addr
.buffer_object
= 0;
2771 op
->bo
.addr
.addr
= data
;
2773 op
->row_pitch
= row_pitch
;
2774 op
->slice_pitch
= slice_pitch
;
2776 wined3d_device_context_acquire_resource(context
, resource
);
2778 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2779 /* The data pointer may go away, so we need to wait until it is read.
2780 * Copying the data may be faster if it's small. */
2781 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2784 static void wined3d_cs_exec_add_dirty_texture_region(struct wined3d_cs
*cs
, const void *data
)
2786 const struct wined3d_cs_add_dirty_texture_region
*op
= data
;
2787 struct wined3d_texture
*texture
= op
->texture
;
2788 unsigned int sub_resource_idx
, i
;
2789 struct wined3d_context
*context
;
2791 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2792 sub_resource_idx
= op
->layer
* texture
->level_count
;
2793 for (i
= 0; i
< texture
->level_count
; ++i
, ++sub_resource_idx
)
2795 if (wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
))
2796 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
2798 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
2800 context_release(context
);
2802 wined3d_resource_release(&texture
->resource
);
2805 void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs
*cs
,
2806 struct wined3d_texture
*texture
, unsigned int layer
)
2808 struct wined3d_cs_add_dirty_texture_region
*op
;
2810 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2811 op
->opcode
= WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
;
2812 op
->texture
= texture
;
2815 wined3d_resource_acquire(&texture
->resource
);
2817 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2820 static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
2822 const struct wined3d_cs_clear_unordered_access_view
*op
= data
;
2823 struct wined3d_unordered_access_view
*view
= op
->view
;
2824 struct wined3d_context
*context
;
2826 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2827 cs
->c
.device
->adapter
->adapter_ops
->adapter_clear_uav(context
, view
, &op
->clear_value
, op
->fp
);
2828 context_release(context
);
2830 wined3d_resource_release(view
->resource
);
2833 void wined3d_device_context_emit_clear_uav(struct wined3d_device_context
*context
,
2834 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
, bool fp
)
2836 struct wined3d_cs_clear_unordered_access_view
*op
;
2838 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2839 op
->opcode
= WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
;
2841 op
->clear_value
= *clear_value
;
2844 wined3d_device_context_acquire_resource(context
, view
->resource
);
2846 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2849 static void wined3d_cs_exec_copy_uav_counter(struct wined3d_cs
*cs
, const void *data
)
2851 const struct wined3d_cs_copy_uav_counter
*op
= data
;
2852 struct wined3d_unordered_access_view
*view
= op
->view
;
2853 struct wined3d_context
*context
;
2855 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2856 wined3d_unordered_access_view_copy_counter(view
, op
->buffer
, op
->offset
, context
);
2857 context_release(context
);
2859 wined3d_resource_release(&op
->buffer
->resource
);
2862 void wined3d_device_context_emit_copy_uav_counter(struct wined3d_device_context
*context
,
2863 struct wined3d_buffer
*dst_buffer
, unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
2865 struct wined3d_cs_copy_uav_counter
*op
;
2867 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2868 op
->opcode
= WINED3D_CS_OP_COPY_UAV_COUNTER
;
2869 op
->buffer
= dst_buffer
;
2870 op
->offset
= offset
;
2873 wined3d_device_context_acquire_resource(context
, &dst_buffer
->resource
);
2875 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2878 static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs
*cs
, const void *data
)
2880 const struct wined3d_cs_generate_mipmaps
*op
= data
;
2881 struct wined3d_shader_resource_view
*view
= op
->view
;
2882 struct wined3d_context
*context
;
2884 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2885 cs
->c
.device
->adapter
->adapter_ops
->adapter_generate_mipmap(context
, view
);
2886 context_release(context
);
2888 wined3d_resource_release(view
->resource
);
2891 void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context
*context
,
2892 struct wined3d_shader_resource_view
*view
)
2894 struct wined3d_cs_generate_mipmaps
*op
;
2896 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2897 op
->opcode
= WINED3D_CS_OP_GENERATE_MIPMAPS
;
2900 wined3d_device_context_acquire_resource(context
, view
->resource
);
2902 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2905 static void wined3d_cs_emit_stop(struct wined3d_cs
*cs
)
2907 struct wined3d_cs_stop
*op
;
2909 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2910 op
->opcode
= WINED3D_CS_OP_STOP
;
2912 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2913 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2916 static void wined3d_cs_acquire_resource(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
)
2918 wined3d_resource_acquire(resource
);
2921 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
);
2923 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
2925 /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop
,
2926 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
2927 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
2928 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
2929 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
2930 /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush
,
2931 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
2932 /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports
,
2933 /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects
,
2934 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEWS */ wined3d_cs_exec_set_rendertarget_views
,
2935 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
2936 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
2937 /* WINED3D_CS_OP_SET_STREAM_SOURCES */ wined3d_cs_exec_set_stream_sources
,
2938 /* WINED3D_CS_OP_SET_STREAM_OUTPUTS */ wined3d_cs_exec_set_stream_outputs
,
2939 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
2940 /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers
,
2941 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
2942 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS */ wined3d_cs_exec_set_shader_resource_views
,
2943 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS */ wined3d_cs_exec_set_unordered_access_views
,
2944 /* WINED3D_CS_OP_SET_SAMPLERS */ wined3d_cs_exec_set_samplers
,
2945 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
2946 /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state
,
2947 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE */ wined3d_cs_exec_set_depth_stencil_state
,
2948 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
2949 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
2950 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
2951 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
2952 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
2953 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
2954 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
2955 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
2956 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
2957 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
2958 /* WINED3D_CS_OP_SET_FEATURE_LEVEL */ wined3d_cs_exec_set_feature_level
,
2959 /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants
,
2960 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
2961 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
2962 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
2963 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
2964 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
2965 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
2966 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
2967 /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource
,
2968 /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource
,
2969 /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region
,
2970 /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view
,
2971 /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter
,
2972 /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps
,
2973 /* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list
,
2976 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
)
2978 const struct wined3d_cs_execute_command_list
*op
= data
;
2979 SIZE_T start
= 0, end
= op
->list
->data_size
;
2980 const BYTE
*cs_data
= op
->list
->data
;
2982 TRACE("Executing command list %p.\n", op
->list
);
2986 const struct wined3d_cs_packet
*packet
= wined3d_next_cs_packet(cs_data
, &start
);
2987 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
2989 if (opcode
>= WINED3D_CS_OP_STOP
)
2990 ERR("Invalid opcode %#x.\n", opcode
);
2992 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
2993 TRACE("%s executed.\n", debug_cs_op(opcode
));
2997 void wined3d_device_context_emit_execute_command_list(struct wined3d_device_context
*context
,
2998 struct wined3d_command_list
*list
, bool restore_state
)
3000 struct wined3d_cs_execute_command_list
*op
;
3002 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
3003 op
->opcode
= WINED3D_CS_OP_EXECUTE_COMMAND_LIST
;
3006 context
->ops
->acquire_command_list(context
, list
);
3008 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
3011 wined3d_device_context_set_state(context
, context
->state
);
3013 wined3d_device_context_reset_state(context
);
3016 static void *wined3d_cs_st_require_space(struct wined3d_device_context
*context
,
3017 size_t size
, enum wined3d_cs_queue_id queue_id
)
3019 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3021 if (size
> (cs
->data_size
- cs
->end
))
3026 new_size
= max(size
, cs
->data_size
* 2);
3028 new_data
= heap_realloc(cs
->data
, new_size
);
3030 new_data
= heap_alloc(new_size
);
3034 cs
->data_size
= new_size
;
3035 cs
->start
= cs
->end
= 0;
3036 cs
->data
= new_data
;
3041 return (BYTE
*)cs
->data
+ cs
->start
;
3044 static void wined3d_cs_st_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3046 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3047 enum wined3d_cs_op opcode
;
3053 cs
->start
= cs
->end
;
3055 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
3056 if (opcode
>= WINED3D_CS_OP_STOP
)
3057 ERR("Invalid opcode %#x.\n", opcode
);
3059 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
3061 if (cs
->data
== data
)
3062 cs
->start
= cs
->end
= start
;
3067 static void wined3d_cs_st_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3071 static bool wined3d_cs_map_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
3072 unsigned int sub_resource_idx
, struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
3074 /* Limit NOOVERWRITE maps to buffers for now; there are too many ways that
3075 * a texture can be invalidated to even count. */
3076 if (wined3d_map_persistent() && resource
->type
== WINED3D_RTYPE_BUFFER
3077 && (flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
)))
3079 struct wined3d_client_resource
*client
= &resource
->client
;
3080 struct wined3d_device
*device
= context
->device
;
3081 const struct wined3d_bo
*bo
;
3084 if (flags
& WINED3D_MAP_DISCARD
)
3086 if (!device
->adapter
->adapter_ops
->adapter_alloc_bo(device
, resource
, sub_resource_idx
, &client
->addr
))
3090 bo
= client
->addr
.buffer_object
;
3091 map_ptr
= bo
? bo
->map_ptr
: NULL
;
3092 map_ptr
+= (uintptr_t)client
->addr
.addr
;
3096 TRACE("Sub-resource is not persistently mapped.\n");
3100 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
3101 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3103 client
->mapped_upload
.addr
= *wined3d_const_bo_address(&client
->addr
);
3104 client
->mapped_upload
.flags
= 0;
3107 map_ptr
+= bo
->memory_offset
;
3109 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
;
3111 map_desc
->data
= resource_offset_map_pointer(resource
, sub_resource_idx
, map_ptr
, box
);
3113 if (flags
& WINED3D_MAP_DISCARD
)
3114 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_RENAME_ON_UNMAP
;
3116 client
->mapped_box
= *box
;
3118 TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client
->mapped_upload
.addr
),
3119 client
->mapped_upload
.flags
);
3126 static bool wined3d_bo_address_is_null(struct wined3d_const_bo_address
*addr
)
3128 return !addr
->buffer_object
&& !addr
->addr
;
3131 static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
3132 unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*bo
)
3134 struct wined3d_client_resource
*client
= &resource
->client
;
3136 if (wined3d_bo_address_is_null(&client
->mapped_upload
.addr
))
3139 *bo
= client
->mapped_upload
;
3140 *box
= client
->mapped_box
;
3141 memset(&client
->mapped_upload
, 0, sizeof(client
->mapped_upload
));
3142 memset(&client
->mapped_box
, 0, sizeof(client
->mapped_box
));
3146 static const struct wined3d_device_context_ops wined3d_cs_st_ops
=
3148 wined3d_cs_st_require_space
,
3149 wined3d_cs_st_submit
,
3150 wined3d_cs_st_finish
,
3151 wined3d_cs_st_push_constants
,
3152 wined3d_cs_map_upload_bo
,
3153 wined3d_cs_unmap_upload_bo
,
3154 wined3d_cs_issue_query
,
3156 wined3d_cs_acquire_resource
,
3157 wined3d_cs_acquire_command_list
,
3160 static BOOL
wined3d_cs_queue_is_empty(const struct wined3d_cs
*cs
, const struct wined3d_cs_queue
*queue
)
3162 wined3d_from_cs(cs
);
3163 return *(volatile LONG
*)&queue
->head
== queue
->tail
;
3166 static void wined3d_cs_queue_submit(struct wined3d_cs_queue
*queue
, struct wined3d_cs
*cs
)
3168 struct wined3d_cs_packet
*packet
;
3171 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
];
3172 TRACE("Queuing op %s at %p.\n", debug_cs_op(*(const enum wined3d_cs_op
*)packet
->data
), packet
);
3173 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
3174 InterlockedExchange(&queue
->head
, (queue
->head
+ packet_size
) & (WINED3D_CS_QUEUE_SIZE
- 1));
3176 if (InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3177 SetEvent(cs
->event
);
3180 static void wined3d_cs_mt_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3182 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3184 if (cs
->thread_id
== GetCurrentThreadId())
3185 return wined3d_cs_st_submit(context
, queue_id
);
3187 wined3d_cs_queue_submit(&cs
->queue
[queue_id
], cs
);
3190 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue
, size_t size
, struct wined3d_cs
*cs
)
3192 size_t queue_size
= ARRAY_SIZE(queue
->data
);
3193 size_t header_size
, packet_size
, remaining
;
3194 struct wined3d_cs_packet
*packet
;
3196 header_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[0]);
3197 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[size
]);
3198 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
3199 size
= packet_size
- header_size
;
3200 if (packet_size
>= WINED3D_CS_QUEUE_SIZE
)
3202 ERR("Packet size %lu >= queue size %u.\n",
3203 (unsigned long)packet_size
, WINED3D_CS_QUEUE_SIZE
);
3207 remaining
= queue_size
- queue
->head
;
3208 if (remaining
< packet_size
)
3210 size_t nop_size
= remaining
- header_size
;
3211 struct wined3d_cs_nop
*nop
;
3213 TRACE("Inserting a nop for %lu + %lu bytes.\n",
3214 (unsigned long)header_size
, (unsigned long)nop_size
);
3216 nop
= wined3d_cs_queue_require_space(queue
, nop_size
, cs
);
3218 nop
->opcode
= WINED3D_CS_OP_NOP
;
3220 wined3d_cs_queue_submit(queue
, cs
);
3221 assert(!queue
->head
);
3226 LONG tail
= *(volatile LONG
*)&queue
->tail
;
3227 LONG head
= queue
->head
;
3233 new_pos
= (head
+ packet_size
) & (WINED3D_CS_QUEUE_SIZE
- 1);
3234 /* Head ahead of tail. We checked the remaining size above, so we only
3235 * need to make sure we don't make head equal to tail. */
3236 if (head
> tail
&& (new_pos
!= tail
))
3238 /* Tail ahead of head. Make sure the new head is before the tail as
3239 * well. Note that new_pos is 0 when it's at the end of the queue. */
3240 if (new_pos
< tail
&& new_pos
)
3243 TRACE("Waiting for free space. Head %u, tail %u, packet size %lu.\n",
3244 head
, tail
, (unsigned long)packet_size
);
3247 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
];
3248 packet
->size
= size
;
3249 return packet
->data
;
3252 static void *wined3d_cs_mt_require_space(struct wined3d_device_context
*context
,
3253 size_t size
, enum wined3d_cs_queue_id queue_id
)
3255 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3257 if (cs
->thread_id
== GetCurrentThreadId())
3258 return wined3d_cs_st_require_space(context
, size
, queue_id
);
3260 return wined3d_cs_queue_require_space(&cs
->queue
[queue_id
], size
, cs
);
3263 static void wined3d_cs_mt_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3265 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3267 if (cs
->thread_id
== GetCurrentThreadId())
3268 return wined3d_cs_st_finish(context
, queue_id
);
3270 while (cs
->queue
[queue_id
].head
!= *(volatile LONG
*)&cs
->queue
[queue_id
].tail
)
3274 static const struct wined3d_device_context_ops wined3d_cs_mt_ops
=
3276 wined3d_cs_mt_require_space
,
3277 wined3d_cs_mt_submit
,
3278 wined3d_cs_mt_finish
,
3279 wined3d_cs_mt_push_constants
,
3280 wined3d_cs_map_upload_bo
,
3281 wined3d_cs_unmap_upload_bo
,
3282 wined3d_cs_issue_query
,
3284 wined3d_cs_acquire_resource
,
3285 wined3d_cs_acquire_command_list
,
3288 static void poll_queries(struct wined3d_cs
*cs
)
3290 struct wined3d_query
*query
, *cursor
;
3292 LIST_FOR_EACH_ENTRY_SAFE(query
, cursor
, &cs
->query_poll_list
, struct wined3d_query
, poll_list_entry
)
3294 if (!query
->query_ops
->query_poll(query
, 0))
3297 list_remove(&query
->poll_list_entry
);
3298 list_init(&query
->poll_list_entry
);
3299 InterlockedIncrement(&query
->counter_retrieved
);
3303 static void wined3d_cs_wait_event(struct wined3d_cs
*cs
)
3305 InterlockedExchange(&cs
->waiting_for_event
, TRUE
);
3307 /* The main thread might have enqueued a command and blocked on it after
3308 * the CS thread decided to enter wined3d_cs_wait_event(), but before
3309 * "waiting_for_event" was set.
3311 * Likewise, we can race with the main thread when resetting
3312 * "waiting_for_event", in which case we would need to call
3313 * WaitForSingleObject() because the main thread called SetEvent(). */
3314 if (!(wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
])
3315 && wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_MAP
]))
3316 && InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3319 WaitForSingleObject(cs
->event
, INFINITE
);
3322 static void wined3d_cs_command_lock(const struct wined3d_cs
*cs
)
3324 if (cs
->serialize_commands
)
3325 EnterCriticalSection(&wined3d_command_cs
);
3328 static void wined3d_cs_command_unlock(const struct wined3d_cs
*cs
)
3330 if (cs
->serialize_commands
)
3331 LeaveCriticalSection(&wined3d_command_cs
);
3334 static DWORD WINAPI
wined3d_cs_run(void *ctx
)
3336 struct wined3d_cs_packet
*packet
;
3337 struct wined3d_cs_queue
*queue
;
3338 unsigned int spin_count
= 0;
3339 struct wined3d_cs
*cs
= ctx
;
3340 enum wined3d_cs_op opcode
;
3341 HMODULE wined3d_module
;
3342 unsigned int poll
= 0;
3345 TRACE("Started.\n");
3347 /* Copy the module handle to a local variable to avoid racing with the
3348 * thread freeing "cs" before the FreeLibraryAndExitThread() call. */
3349 wined3d_module
= cs
->wined3d_module
;
3351 list_init(&cs
->query_poll_list
);
3352 cs
->thread_id
= GetCurrentThreadId();
3355 if (++poll
== WINED3D_CS_QUERY_POLL_INTERVAL
)
3357 wined3d_cs_command_lock(cs
);
3359 wined3d_cs_command_unlock(cs
);
3363 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3364 if (wined3d_cs_queue_is_empty(cs
, queue
))
3366 queue
= &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
];
3367 if (wined3d_cs_queue_is_empty(cs
, queue
))
3369 if (++spin_count
>= WINED3D_CS_SPIN_COUNT
&& list_empty(&cs
->query_poll_list
))
3370 wined3d_cs_wait_event(cs
);
3377 packet
= wined3d_next_cs_packet(queue
->data
, &tail
);
3380 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3382 TRACE("Executing %s at %p.\n", debug_cs_op(opcode
), packet
);
3383 if (opcode
>= WINED3D_CS_OP_STOP
)
3385 if (opcode
> WINED3D_CS_OP_STOP
)
3386 ERR("Invalid opcode %#x.\n", opcode
);
3390 wined3d_cs_command_lock(cs
);
3391 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3392 wined3d_cs_command_unlock(cs
);
3393 TRACE("%s at %p executed.\n", debug_cs_op(opcode
), packet
);
3396 tail
&= (WINED3D_CS_QUEUE_SIZE
- 1);
3397 InterlockedExchange(&queue
->tail
, tail
);
3400 cs
->queue
[WINED3D_CS_QUEUE_MAP
].tail
= cs
->queue
[WINED3D_CS_QUEUE_MAP
].head
;
3401 cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].tail
= cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].head
;
3402 TRACE("Stopped.\n");
3403 FreeLibraryAndExitThread(wined3d_module
, 0);
3406 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
,
3407 const enum wined3d_feature_level
*levels
, unsigned int level_count
)
3409 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3410 struct wined3d_cs
*cs
;
3412 if (!(cs
= heap_alloc_zero(sizeof(*cs
))))
3415 if (FAILED(wined3d_state_create(device
, levels
, level_count
, &cs
->c
.state
)))
3421 cs
->c
.ops
= &wined3d_cs_st_ops
;
3422 cs
->c
.device
= device
;
3423 cs
->serialize_commands
= TRACE_ON(d3d_sync
) || wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_SERIALIZE
;
3425 if (cs
->serialize_commands
)
3426 ERR_(d3d_sync
)("Forcing serialization of all command streams.\n");
3428 state_init(&cs
->state
, d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
, cs
->c
.state
->feature_level
);
3430 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
3431 if (!(cs
->data
= heap_alloc(cs
->data_size
)))
3434 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
3435 && !RtlIsCriticalSectionLockedByThread(NtCurrentTeb()->Peb
->LoaderLock
))
3437 cs
->c
.ops
= &wined3d_cs_mt_ops
;
3439 if (!(cs
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
3441 ERR("Failed to create command stream event.\n");
3442 heap_free(cs
->data
);
3446 if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
3447 (const WCHAR
*)wined3d_cs_run
, &cs
->wined3d_module
)))
3449 ERR("Failed to get wined3d module handle.\n");
3450 CloseHandle(cs
->event
);
3451 heap_free(cs
->data
);
3455 if (!(cs
->thread
= CreateThread(NULL
, 0, wined3d_cs_run
, cs
, 0, NULL
)))
3457 ERR("Failed to create wined3d command stream thread.\n");
3458 FreeLibrary(cs
->wined3d_module
);
3459 CloseHandle(cs
->event
);
3460 heap_free(cs
->data
);
3468 wined3d_state_destroy(cs
->c
.state
);
3469 state_cleanup(&cs
->state
);
3474 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
3478 wined3d_cs_emit_stop(cs
);
3479 CloseHandle(cs
->thread
);
3480 if (!CloseHandle(cs
->event
))
3481 ERR("Closing event failed.\n");
3484 wined3d_state_destroy(cs
->c
.state
);
3485 state_cleanup(&cs
->state
);
3486 heap_free(cs
->data
);
3490 static void wined3d_cs_packet_decref_objects(const struct wined3d_cs_packet
*packet
)
3492 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3497 case WINED3D_CS_OP_SET_SAMPLERS
:
3499 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3501 for (i
= 0; i
< op
->count
; ++i
)
3503 if (op
->samplers
[i
])
3504 wined3d_sampler_decref(op
->samplers
[i
]);
3509 case WINED3D_CS_OP_SET_SHADER
:
3511 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3514 wined3d_shader_decref(op
->shader
);
3518 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3520 struct wined3d_cs_set_depth_stencil_state
*op
;
3522 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3524 wined3d_depth_stencil_state_decref(op
->state
);
3528 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3530 struct wined3d_cs_set_rasterizer_state
*op
;
3532 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3534 wined3d_rasterizer_state_decref(op
->state
);
3538 case WINED3D_CS_OP_SET_BLEND_STATE
:
3540 struct wined3d_cs_set_blend_state
*op
;
3542 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3544 wined3d_blend_state_decref(op
->state
);
3548 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3550 struct wined3d_cs_set_rendertarget_views
*op
;
3552 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3553 for (i
= 0; i
< op
->count
; ++i
)
3556 wined3d_rendertarget_view_decref(op
->views
[i
]);
3561 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3563 struct wined3d_cs_set_shader_resource_views
*op
;
3565 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3566 for (i
= 0; i
< op
->count
; ++i
)
3569 wined3d_shader_resource_view_decref(op
->views
[i
]);
3574 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3576 struct wined3d_cs_set_unordered_access_views
*op
;
3578 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3579 for (i
= 0; i
< op
->count
; ++i
)
3581 if (op
->uavs
[i
].view
)
3582 wined3d_unordered_access_view_decref(op
->uavs
[i
].view
);
3587 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3589 struct wined3d_cs_set_depth_stencil_view
*op
;
3591 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3593 wined3d_rendertarget_view_decref(op
->view
);
3597 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3599 struct wined3d_cs_set_constant_buffers
*op
;
3601 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3602 for (i
= 0; i
< op
->count
; ++i
)
3604 if (op
->buffers
[i
].buffer
)
3605 wined3d_buffer_decref(op
->buffers
[i
].buffer
);
3610 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3612 struct wined3d_cs_clear_unordered_access_view
*op
;
3614 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3615 wined3d_unordered_access_view_decref(op
->view
);
3619 case WINED3D_CS_OP_CLEAR
:
3621 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3623 for (i
= 0; i
< op
->rt_count
; ++i
)
3625 if (op
->fb
.render_targets
[i
])
3626 wined3d_rendertarget_view_decref(op
->fb
.render_targets
[i
]);
3628 if (op
->fb
.depth_stencil
)
3629 wined3d_rendertarget_view_decref(op
->fb
.depth_stencil
);
3633 case WINED3D_CS_OP_DISPATCH
:
3635 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3637 if (op
->parameters
.indirect
)
3638 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3642 case WINED3D_CS_OP_DRAW
:
3644 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3646 if (op
->parameters
.indirect
)
3647 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3651 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3653 struct wined3d_cs_set_index_buffer
*op
;
3655 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3657 wined3d_buffer_decref(op
->buffer
);
3666 static void wined3d_cs_packet_incref_objects(struct wined3d_cs_packet
*packet
)
3668 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3673 case WINED3D_CS_OP_SET_SAMPLERS
:
3675 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3677 for (i
= 0; i
< op
->count
; ++i
)
3679 if (op
->samplers
[i
])
3680 wined3d_sampler_incref(op
->samplers
[i
]);
3685 case WINED3D_CS_OP_SET_SHADER
:
3687 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3690 wined3d_shader_incref(op
->shader
);
3694 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3696 struct wined3d_cs_set_depth_stencil_state
*op
;
3698 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3700 wined3d_depth_stencil_state_incref(op
->state
);
3704 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3706 struct wined3d_cs_set_rasterizer_state
*op
;
3708 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3710 wined3d_rasterizer_state_incref(op
->state
);
3714 case WINED3D_CS_OP_SET_BLEND_STATE
:
3716 struct wined3d_cs_set_blend_state
*op
;
3718 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3720 wined3d_blend_state_incref(op
->state
);
3724 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3726 struct wined3d_cs_set_rendertarget_views
*op
;
3728 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3729 for (i
= 0; i
< op
->count
; ++i
)
3732 wined3d_rendertarget_view_incref(op
->views
[i
]);
3737 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3739 struct wined3d_cs_set_shader_resource_views
*op
;
3741 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3742 for (i
= 0; i
< op
->count
; ++i
)
3745 wined3d_shader_resource_view_incref(op
->views
[i
]);
3750 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3752 struct wined3d_cs_set_unordered_access_views
*op
;
3754 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3755 for (i
= 0; i
< op
->count
; ++i
)
3757 if (op
->uavs
[i
].view
)
3758 wined3d_unordered_access_view_incref(op
->uavs
[i
].view
);
3763 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3765 struct wined3d_cs_set_depth_stencil_view
*op
;
3767 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3769 wined3d_rendertarget_view_incref(op
->view
);
3773 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3775 struct wined3d_cs_set_constant_buffers
*op
;
3777 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3778 for (i
= 0; i
< op
->count
; ++i
)
3780 if (op
->buffers
[i
].buffer
)
3781 wined3d_buffer_incref(op
->buffers
[i
].buffer
);
3786 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3788 struct wined3d_cs_clear_unordered_access_view
*op
;
3790 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3791 wined3d_unordered_access_view_incref(op
->view
);
3795 case WINED3D_CS_OP_CLEAR
:
3797 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3799 for (i
= 0; i
< op
->rt_count
; ++i
)
3801 if (op
->fb
.render_targets
[i
])
3802 wined3d_rendertarget_view_incref(op
->fb
.render_targets
[i
]);
3804 if (op
->fb
.depth_stencil
)
3805 wined3d_rendertarget_view_incref(op
->fb
.depth_stencil
);
3809 case WINED3D_CS_OP_DISPATCH
:
3811 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3813 if (op
->parameters
.indirect
)
3814 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3818 case WINED3D_CS_OP_DRAW
:
3820 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3822 if (op
->parameters
.indirect
)
3823 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3827 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3829 struct wined3d_cs_set_index_buffer
*op
;
3831 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3833 wined3d_buffer_incref(op
->buffer
);
3842 struct wined3d_deferred_context
3844 struct wined3d_device_context c
;
3846 SIZE_T data_size
, data_capacity
;
3849 SIZE_T resource_count
, resources_capacity
;
3850 struct wined3d_resource
**resources
;
3852 SIZE_T upload_count
, uploads_capacity
;
3853 struct wined3d_deferred_upload
*uploads
;
3855 /* List of command lists queued for execution on this context. A command
3856 * list can be the only thing holding a pointer to another command list, so
3857 * we need to hold a reference here and in wined3d_command_list as well. */
3858 SIZE_T command_list_count
, command_lists_capacity
;
3859 struct wined3d_command_list
**command_lists
;
3861 SIZE_T query_count
, queries_capacity
;
3862 struct wined3d_deferred_query_issue
*queries
;
3865 static struct wined3d_deferred_context
*wined3d_deferred_context_from_context(struct wined3d_device_context
*context
)
3867 return CONTAINING_RECORD(context
, struct wined3d_deferred_context
, c
);
3870 static void *wined3d_deferred_context_require_space(struct wined3d_device_context
*context
,
3871 size_t size
, enum wined3d_cs_queue_id queue_id
)
3873 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
3874 struct wined3d_cs_packet
*packet
;
3875 size_t header_size
, packet_size
;
3877 if (queue_id
!= WINED3D_CS_QUEUE_DEFAULT
)
3880 header_size
= offsetof(struct wined3d_cs_packet
, data
[0]);
3881 packet_size
= offsetof(struct wined3d_cs_packet
, data
[size
]);
3882 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
3884 if (!wined3d_array_reserve(&deferred
->data
, &deferred
->data_capacity
, deferred
->data_size
+ packet_size
, 1))
3887 packet
= (struct wined3d_cs_packet
*)((BYTE
*)deferred
->data
+ deferred
->data_size
);
3888 TRACE("size was %zu, adding %zu\n", (size_t)deferred
->data_size
, packet_size
);
3889 packet
->size
= packet_size
- header_size
;
3890 return &packet
->data
;
3893 static void wined3d_deferred_context_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3895 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
3896 struct wined3d_cs_packet
*packet
;
3898 assert(queue_id
== WINED3D_CS_QUEUE_DEFAULT
);
3899 packet
= wined3d_next_cs_packet(deferred
->data
, &deferred
->data_size
);
3900 wined3d_cs_packet_incref_objects(packet
);
3903 static void wined3d_deferred_context_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3905 /* This should not happen; we cannot meaningfully finish a deferred context. */
3906 ERR("Ignoring finish() on a deferred context.\n");
3909 static void wined3d_deferred_context_push_constants(struct wined3d_device_context
*context
,
3910 enum wined3d_push_constants p
, unsigned int start_idx
, unsigned int count
, const void *constants
)
3912 FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context
, p
, start_idx
, count
, constants
);
3915 static struct wined3d_deferred_upload
*deferred_context_get_upload(struct wined3d_deferred_context
*deferred
,
3916 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
3918 SIZE_T i
= deferred
->upload_count
;
3922 struct wined3d_deferred_upload
*upload
= &deferred
->uploads
[i
];
3924 if (upload
->resource
== resource
&& upload
->sub_resource_idx
== sub_resource_idx
)
3931 static bool wined3d_deferred_context_map_upload_bo(struct wined3d_device_context
*context
,
3932 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
3933 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
3935 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
3936 const struct wined3d_format
*format
= resource
->format
;
3937 struct wined3d_deferred_upload
*upload
;
3941 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
3942 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3944 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
3945 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
3946 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
3948 if (!(flags
& WINED3D_MAP_WRITE
))
3950 WARN("Flags %#x are not valid on a deferred context.\n", flags
);
3954 if (flags
& ~(WINED3D_MAP_WRITE
| WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
3956 FIXME("Unhandled flags %#x.\n", flags
);
3960 if (flags
& WINED3D_MAP_NOOVERWRITE
)
3962 if (!(upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
3965 upload
->upload_flags
= 0;
3966 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
3970 if (!wined3d_array_reserve((void **)&deferred
->uploads
, &deferred
->uploads_capacity
,
3971 deferred
->upload_count
+ 1, sizeof(*deferred
->uploads
)))
3974 if (!(sysmem
= heap_alloc(size
+ RESOURCE_ALIGNMENT
- 1)))
3977 upload
= &deferred
->uploads
[deferred
->upload_count
++];
3978 upload
->upload_flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
;
3979 upload
->resource
= resource
;
3980 wined3d_resource_incref(resource
);
3981 upload
->sub_resource_idx
= sub_resource_idx
;
3982 upload
->sysmem
= sysmem
;
3985 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
3989 static bool wined3d_deferred_context_unmap_upload_bo(struct wined3d_device_context
*context
,
3990 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*bo
)
3992 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
3993 const struct wined3d_deferred_upload
*upload
;
3995 if ((upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
3998 bo
->addr
.buffer_object
= 0;
3999 bo
->addr
.addr
= (uint8_t *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4000 bo
->flags
= upload
->upload_flags
;
4007 static void wined3d_deferred_context_issue_query(struct wined3d_device_context
*context
,
4008 struct wined3d_query
*query
, unsigned int flags
)
4010 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4011 struct wined3d_cs_query_issue
*op
;
4013 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
4014 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
4018 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
4020 if (!wined3d_array_reserve((void **)&deferred
->queries
, &deferred
->queries_capacity
,
4021 deferred
->query_count
+ 1, sizeof(*deferred
->queries
)))
4023 ERR("Failed to reserve memory.\n");
4027 deferred
->queries
[deferred
->query_count
].flags
= flags
;
4028 wined3d_query_incref(deferred
->queries
[deferred
->query_count
++].query
= query
);
4031 static void wined3d_deferred_context_flush(struct wined3d_device_context
*context
)
4033 FIXME("context %p, stub!\n", context
);
4036 static void wined3d_deferred_context_acquire_resource(struct wined3d_device_context
*context
,
4037 struct wined3d_resource
*resource
)
4039 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4041 if (!wined3d_array_reserve((void **)&deferred
->resources
, &deferred
->resources_capacity
,
4042 deferred
->resource_count
+ 1, sizeof(*deferred
->resources
)))
4045 deferred
->resources
[deferred
->resource_count
++] = resource
;
4046 wined3d_resource_incref(resource
);
4049 static void wined3d_deferred_context_acquire_command_list(struct wined3d_device_context
*context
,
4050 struct wined3d_command_list
*list
)
4052 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4054 /* Grab a reference to the command list. Note that this implicitly prevents
4055 * any dependent command lists or resources from being freed as well. */
4056 if (!wined3d_array_reserve((void **)&deferred
->command_lists
, &deferred
->command_lists_capacity
,
4057 deferred
->command_list_count
+ 1, sizeof(*deferred
->command_lists
)))
4060 wined3d_command_list_incref(deferred
->command_lists
[deferred
->command_list_count
++] = list
);
4063 static const struct wined3d_device_context_ops wined3d_deferred_context_ops
=
4065 wined3d_deferred_context_require_space
,
4066 wined3d_deferred_context_submit
,
4067 wined3d_deferred_context_finish
,
4068 wined3d_deferred_context_push_constants
,
4069 wined3d_deferred_context_map_upload_bo
,
4070 wined3d_deferred_context_unmap_upload_bo
,
4071 wined3d_deferred_context_issue_query
,
4072 wined3d_deferred_context_flush
,
4073 wined3d_deferred_context_acquire_resource
,
4074 wined3d_deferred_context_acquire_command_list
,
4077 HRESULT CDECL
wined3d_deferred_context_create(struct wined3d_device
*device
, struct wined3d_device_context
**context
)
4079 struct wined3d_deferred_context
*object
;
4082 TRACE("device %p, context %p.\n", device
, context
);
4084 if (!(object
= heap_alloc_zero(sizeof(*object
))))
4085 return E_OUTOFMEMORY
;
4087 if (FAILED(hr
= wined3d_state_create(device
, &device
->cs
->c
.state
->feature_level
, 1, &object
->c
.state
)))
4093 object
->c
.ops
= &wined3d_deferred_context_ops
;
4094 object
->c
.device
= device
;
4096 /* Make sure the first command list gets the state reset when executed.
4097 * Resets for subsequent command lists are encoded in wined3d_deferred_context_record_command_list(). */
4098 wined3d_device_context_emit_reset_state(&object
->c
, true);
4100 TRACE("Created deferred context %p.\n", object
);
4101 *context
= &object
->c
;
4106 void CDECL
wined3d_deferred_context_destroy(struct wined3d_device_context
*context
)
4108 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4109 const struct wined3d_cs_packet
*packet
;
4110 SIZE_T i
, offset
= 0;
4112 TRACE("context %p.\n", context
);
4114 for (i
= 0; i
< deferred
->resource_count
; ++i
)
4115 wined3d_resource_decref(deferred
->resources
[i
]);
4116 heap_free(deferred
->resources
);
4118 for (i
= 0; i
< deferred
->upload_count
; ++i
)
4120 wined3d_resource_decref(deferred
->uploads
[i
].resource
);
4121 heap_free(deferred
->uploads
[i
].sysmem
);
4123 heap_free(deferred
->uploads
);
4125 for (i
= 0; i
< deferred
->command_list_count
; ++i
)
4126 wined3d_command_list_decref(deferred
->command_lists
[i
]);
4127 heap_free(deferred
->command_lists
);
4129 for (i
= 0; i
< deferred
->query_count
; ++i
)
4130 wined3d_query_decref(deferred
->queries
[i
].query
);
4131 heap_free(deferred
->queries
);
4133 while (offset
< deferred
->data_size
)
4135 packet
= wined3d_next_cs_packet(deferred
->data
, &offset
);
4136 wined3d_cs_packet_decref_objects(packet
);
4139 wined3d_state_destroy(deferred
->c
.state
);
4140 heap_free(deferred
->data
);
4141 heap_free(deferred
);
4144 HRESULT CDECL
wined3d_deferred_context_record_command_list(struct wined3d_device_context
*context
,
4145 bool restore
, struct wined3d_command_list
**list
)
4147 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4148 struct wined3d_command_list
*object
;
4151 TRACE("context %p, list %p.\n", context
, list
);
4153 wined3d_device_context_lock(context
);
4154 memory
= heap_alloc(sizeof(*object
) + deferred
->resource_count
* sizeof(*object
->resources
)
4155 + deferred
->upload_count
* sizeof(*object
->uploads
)
4156 + deferred
->command_list_count
* sizeof(*object
->command_lists
)
4157 + deferred
->query_count
* sizeof(*object
->queries
)
4158 + deferred
->data_size
);
4162 wined3d_device_context_unlock(context
);
4163 return E_OUTOFMEMORY
;
4167 memory
= &object
[1];
4168 memset(object
, 0, sizeof(*object
));
4169 object
->refcount
= 1;
4170 object
->device
= deferred
->c
.device
;
4172 object
->resources
= memory
;
4173 memory
= &object
->resources
[deferred
->resource_count
];
4174 object
->resource_count
= deferred
->resource_count
;
4175 memcpy(object
->resources
, deferred
->resources
, deferred
->resource_count
* sizeof(*object
->resources
));
4176 /* Transfer our references to the resources to the command list. */
4178 object
->uploads
= memory
;
4179 memory
= &object
->uploads
[deferred
->upload_count
];
4180 object
->upload_count
= deferred
->upload_count
;
4181 memcpy(object
->uploads
, deferred
->uploads
, deferred
->upload_count
* sizeof(*object
->uploads
));
4182 /* Transfer our references to the resources to the command list. */
4184 object
->command_lists
= memory
;
4185 memory
= &object
->command_lists
[deferred
->command_list_count
];
4186 object
->command_list_count
= deferred
->command_list_count
;
4187 memcpy(object
->command_lists
, deferred
->command_lists
,
4188 deferred
->command_list_count
* sizeof(*object
->command_lists
));
4189 /* Transfer our references to the command lists to the command list. */
4191 object
->queries
= memory
;
4192 memory
= &object
->queries
[deferred
->query_count
];
4193 object
->query_count
= deferred
->query_count
;
4194 memcpy(object
->queries
, deferred
->queries
, deferred
->query_count
* sizeof(*object
->queries
));
4195 /* Transfer our references to the queries to the command list. */
4197 object
->data
= memory
;
4198 object
->data_size
= deferred
->data_size
;
4199 memcpy(object
->data
, deferred
->data
, deferred
->data_size
);
4201 deferred
->data_size
= 0;
4202 deferred
->resource_count
= 0;
4203 deferred
->upload_count
= 0;
4204 deferred
->command_list_count
= 0;
4205 deferred
->query_count
= 0;
4207 /* This is in fact recorded into a subsequent command list. */
4209 wined3d_device_context_set_state(&deferred
->c
, deferred
->c
.state
);
4211 wined3d_device_context_reset_state(&deferred
->c
);
4213 TRACE("Created command list %p.\n", object
);
4215 wined3d_device_context_unlock(context
);
4220 static void wined3d_command_list_destroy_object(void *object
)
4222 struct wined3d_command_list
*list
= object
;
4225 TRACE("list %p.\n", list
);
4227 for (i
= 0; i
< list
->upload_count
; ++i
)
4228 heap_free(list
->uploads
[i
].sysmem
);
4233 ULONG CDECL
wined3d_command_list_incref(struct wined3d_command_list
*list
)
4235 ULONG refcount
= InterlockedIncrement(&list
->refcount
);
4237 TRACE("%p increasing refcount to %u.\n", list
, refcount
);
4242 ULONG CDECL
wined3d_command_list_decref(struct wined3d_command_list
*list
)
4244 ULONG refcount
= InterlockedDecrement(&list
->refcount
);
4245 struct wined3d_device
*device
= list
->device
;
4246 const struct wined3d_cs_packet
*packet
;
4249 TRACE("%p decreasing refcount to %u.\n", list
, refcount
);
4253 for (i
= 0; i
< list
->command_list_count
; ++i
)
4254 wined3d_command_list_decref(list
->command_lists
[i
]);
4255 for (i
= 0; i
< list
->resource_count
; ++i
)
4256 wined3d_resource_decref(list
->resources
[i
]);
4257 for (i
= 0; i
< list
->upload_count
; ++i
)
4258 wined3d_resource_decref(list
->uploads
[i
].resource
);
4259 for (i
= 0; i
< list
->query_count
; ++i
)
4260 wined3d_query_decref(list
->queries
[i
].query
);
4263 while (offset
< list
->data_size
)
4265 packet
= wined3d_next_cs_packet(list
->data
, &offset
);
4266 wined3d_cs_packet_decref_objects(packet
);
4269 wined3d_mutex_lock();
4270 wined3d_cs_destroy_object(device
->cs
, wined3d_command_list_destroy_object
, list
);
4271 wined3d_mutex_unlock();