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
19 #include "wined3d_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
22 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf
);
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
;
59 LONG
*upload_heap_refcount
;
61 /* List of command lists queued for execution on this command list. We might
62 * be the only thing holding a pointer to another command list, so we need
63 * to hold a reference here (and in wined3d_deferred_context) as well. */
64 SIZE_T command_list_count
;
65 struct wined3d_command_list
**command_lists
;
68 struct wined3d_deferred_query_issue
*queries
;
71 static void discard_client_address(struct wined3d_resource
*resource
)
73 struct wined3d_client_resource
*client
= &resource
->client
;
75 client
->addr
.buffer_object
= CLIENT_BO_DISCARDED
;
76 client
->addr
.addr
= NULL
;
79 static void invalidate_client_address(struct wined3d_resource
*resource
)
81 struct wined3d_client_resource
*client
= &resource
->client
;
83 memset(&client
->addr
, 0, sizeof(client
->addr
));
89 WINED3D_CS_OP_PRESENT
,
91 WINED3D_CS_OP_DISPATCH
,
94 WINED3D_CS_OP_SET_PREDICATION
,
95 WINED3D_CS_OP_SET_VIEWPORTS
,
96 WINED3D_CS_OP_SET_SCISSOR_RECTS
,
97 WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
,
98 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
,
99 WINED3D_CS_OP_SET_VERTEX_DECLARATION
,
100 WINED3D_CS_OP_SET_STREAM_SOURCES
,
101 WINED3D_CS_OP_SET_STREAM_OUTPUTS
,
102 WINED3D_CS_OP_SET_INDEX_BUFFER
,
103 WINED3D_CS_OP_SET_CONSTANT_BUFFERS
,
104 WINED3D_CS_OP_SET_TEXTURE
,
105 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
,
106 WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
,
107 WINED3D_CS_OP_SET_SAMPLERS
,
108 WINED3D_CS_OP_SET_SHADER
,
109 WINED3D_CS_OP_SET_BLEND_STATE
,
110 WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
,
111 WINED3D_CS_OP_SET_RASTERIZER_STATE
,
112 WINED3D_CS_OP_SET_DEPTH_BOUNDS
,
113 WINED3D_CS_OP_SET_RENDER_STATE
,
114 WINED3D_CS_OP_SET_TEXTURE_STATE
,
115 WINED3D_CS_OP_SET_SAMPLER_STATE
,
116 WINED3D_CS_OP_SET_TRANSFORM
,
117 WINED3D_CS_OP_SET_CLIP_PLANE
,
118 WINED3D_CS_OP_SET_COLOR_KEY
,
119 WINED3D_CS_OP_SET_MATERIAL
,
120 WINED3D_CS_OP_SET_LIGHT
,
121 WINED3D_CS_OP_SET_LIGHT_ENABLE
,
122 WINED3D_CS_OP_SET_FEATURE_LEVEL
,
123 WINED3D_CS_OP_PUSH_CONSTANTS
,
124 WINED3D_CS_OP_RESET_STATE
,
125 WINED3D_CS_OP_CALLBACK
,
126 WINED3D_CS_OP_QUERY_ISSUE
,
127 WINED3D_CS_OP_PRELOAD_RESOURCE
,
128 WINED3D_CS_OP_UNLOAD_RESOURCE
,
131 WINED3D_CS_OP_MAP_BO_ADDRESS
,
132 WINED3D_CS_OP_BLT_SUB_RESOURCE
,
133 WINED3D_CS_OP_UPDATE_SUB_RESOURCE
,
134 WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
,
135 WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
,
136 WINED3D_CS_OP_COPY_UAV_COUNTER
,
137 WINED3D_CS_OP_GENERATE_MIPMAPS
,
138 WINED3D_CS_OP_EXECUTE_COMMAND_LIST
,
142 struct wined3d_cs_packet
148 struct wined3d_cs_nop
150 enum wined3d_cs_op opcode
;
153 struct wined3d_cs_present
155 enum wined3d_cs_op opcode
;
156 HWND dst_window_override
;
157 struct wined3d_swapchain
*swapchain
;
160 unsigned int swap_interval
;
164 struct wined3d_cs_clear
166 enum wined3d_cs_op opcode
;
168 unsigned int rt_count
;
169 struct wined3d_fb_state fb
;
171 struct wined3d_color color
;
174 unsigned int rect_count
;
178 struct wined3d_cs_dispatch
180 enum wined3d_cs_op opcode
;
181 struct wined3d_dispatch_parameters parameters
;
184 struct wined3d_cs_draw
186 enum wined3d_cs_op opcode
;
187 enum wined3d_primitive_type primitive_type
;
188 GLint patch_vertex_count
;
189 struct wined3d_draw_parameters parameters
;
192 struct wined3d_cs_flush
194 enum wined3d_cs_op opcode
;
197 struct wined3d_cs_set_predication
199 enum wined3d_cs_op opcode
;
200 struct wined3d_query
*predicate
;
204 struct wined3d_cs_set_viewports
206 enum wined3d_cs_op opcode
;
207 unsigned int viewport_count
;
208 struct wined3d_viewport viewports
[1];
211 struct wined3d_cs_set_scissor_rects
213 enum wined3d_cs_op opcode
;
214 unsigned int rect_count
;
218 struct wined3d_cs_set_rendertarget_views
220 enum wined3d_cs_op opcode
;
221 unsigned int start_idx
;
223 struct wined3d_rendertarget_view
*views
[1];
226 struct wined3d_cs_set_depth_stencil_view
228 enum wined3d_cs_op opcode
;
229 struct wined3d_rendertarget_view
*view
;
232 struct wined3d_cs_set_vertex_declaration
234 enum wined3d_cs_op opcode
;
235 struct wined3d_vertex_declaration
*declaration
;
238 struct wined3d_cs_set_stream_sources
240 enum wined3d_cs_op opcode
;
241 unsigned int start_idx
;
243 struct wined3d_stream_state streams
[1];
246 struct wined3d_cs_set_stream_outputs
248 enum wined3d_cs_op opcode
;
249 struct wined3d_stream_output outputs
[WINED3D_MAX_STREAM_OUTPUT_BUFFERS
];
252 struct wined3d_cs_set_index_buffer
254 enum wined3d_cs_op opcode
;
255 struct wined3d_buffer
*buffer
;
256 enum wined3d_format_id format_id
;
260 struct wined3d_cs_set_constant_buffers
262 enum wined3d_cs_op opcode
;
263 enum wined3d_shader_type type
;
264 unsigned int start_idx
;
266 struct wined3d_constant_buffer_state buffers
[1];
269 struct wined3d_cs_set_texture
271 enum wined3d_cs_op opcode
;
273 struct wined3d_texture
*texture
;
276 struct wined3d_cs_set_color_key
278 enum wined3d_cs_op opcode
;
279 struct wined3d_texture
*texture
;
282 struct wined3d_color_key color_key
;
285 struct wined3d_cs_set_shader_resource_views
287 enum wined3d_cs_op opcode
;
288 enum wined3d_shader_type type
;
289 unsigned int start_idx
;
291 struct wined3d_shader_resource_view
*views
[1];
294 struct wined3d_cs_set_unordered_access_views
296 enum wined3d_cs_op opcode
;
297 enum wined3d_pipeline pipeline
;
298 unsigned int start_idx
;
302 struct wined3d_unordered_access_view
*view
;
303 unsigned int initial_count
;
307 struct wined3d_cs_set_samplers
309 enum wined3d_cs_op opcode
;
310 enum wined3d_shader_type type
;
311 unsigned int start_idx
;
313 struct wined3d_sampler
*samplers
[1];
316 struct wined3d_cs_set_shader
318 enum wined3d_cs_op opcode
;
319 enum wined3d_shader_type type
;
320 struct wined3d_shader
*shader
;
323 struct wined3d_cs_set_blend_state
325 enum wined3d_cs_op opcode
;
326 struct wined3d_blend_state
*state
;
327 struct wined3d_color factor
;
328 unsigned int sample_mask
;
331 struct wined3d_cs_set_depth_stencil_state
333 enum wined3d_cs_op opcode
;
334 struct wined3d_depth_stencil_state
*state
;
335 unsigned int stencil_ref
;
338 struct wined3d_cs_set_rasterizer_state
340 enum wined3d_cs_op opcode
;
341 struct wined3d_rasterizer_state
*state
;
344 struct wined3d_cs_set_depth_bounds
346 enum wined3d_cs_op opcode
;
348 float min_depth
, max_depth
;
351 struct wined3d_cs_set_render_state
353 enum wined3d_cs_op opcode
;
354 enum wined3d_render_state state
;
358 struct wined3d_cs_set_texture_state
360 enum wined3d_cs_op opcode
;
362 enum wined3d_texture_stage_state state
;
366 struct wined3d_cs_set_sampler_state
368 enum wined3d_cs_op opcode
;
370 enum wined3d_sampler_state state
;
374 struct wined3d_cs_set_transform
376 enum wined3d_cs_op opcode
;
377 enum wined3d_transform_state state
;
378 struct wined3d_matrix matrix
;
381 struct wined3d_cs_set_clip_plane
383 enum wined3d_cs_op opcode
;
385 struct wined3d_vec4 plane
;
388 struct wined3d_cs_set_material
390 enum wined3d_cs_op opcode
;
391 struct wined3d_material material
;
394 struct wined3d_cs_set_light
396 enum wined3d_cs_op opcode
;
397 struct wined3d_light_info light
;
400 struct wined3d_cs_set_light_enable
402 enum wined3d_cs_op opcode
;
407 struct wined3d_cs_set_feature_level
409 enum wined3d_cs_op opcode
;
410 enum wined3d_feature_level level
;
413 struct wined3d_cs_push_constants
415 enum wined3d_cs_op opcode
;
416 enum wined3d_push_constants type
;
417 unsigned int start_idx
;
422 struct wined3d_cs_reset_state
424 enum wined3d_cs_op opcode
;
428 struct wined3d_cs_callback
430 enum wined3d_cs_op opcode
;
431 void (*callback
)(void *object
);
435 struct wined3d_cs_query_issue
437 enum wined3d_cs_op opcode
;
438 struct wined3d_query
*query
;
442 struct wined3d_cs_preload_resource
444 enum wined3d_cs_op opcode
;
445 struct wined3d_resource
*resource
;
448 struct wined3d_cs_unload_resource
450 enum wined3d_cs_op opcode
;
451 struct wined3d_resource
*resource
;
454 struct wined3d_cs_map
456 enum wined3d_cs_op opcode
;
457 struct wined3d_resource
*resource
;
458 unsigned int sub_resource_idx
;
460 const struct wined3d_box
*box
;
465 struct wined3d_cs_unmap
467 enum wined3d_cs_op opcode
;
468 struct wined3d_resource
*resource
;
469 unsigned int sub_resource_idx
;
473 struct wined3d_cs_map_bo_address
475 enum wined3d_cs_op opcode
;
476 struct wined3d_bo_address addr
;
481 struct wined3d_cs_blt_sub_resource
483 enum wined3d_cs_op opcode
;
484 struct wined3d_resource
*dst_resource
;
485 unsigned int dst_sub_resource_idx
;
486 struct wined3d_box dst_box
;
487 struct wined3d_resource
*src_resource
;
488 unsigned int src_sub_resource_idx
;
489 struct wined3d_box src_box
;
491 struct wined3d_blt_fx fx
;
492 enum wined3d_texture_filter_type filter
;
495 struct wined3d_cs_update_sub_resource
497 enum wined3d_cs_op opcode
;
498 struct wined3d_resource
*resource
;
499 unsigned int sub_resource_idx
;
500 struct wined3d_box box
;
502 unsigned int row_pitch
, slice_pitch
;
505 struct wined3d_cs_add_dirty_texture_region
507 enum wined3d_cs_op opcode
;
508 struct wined3d_texture
*texture
;
512 struct wined3d_cs_clear_unordered_access_view
514 enum wined3d_cs_op opcode
;
515 struct wined3d_unordered_access_view
*view
;
516 struct wined3d_uvec4 clear_value
;
520 struct wined3d_cs_copy_uav_counter
522 enum wined3d_cs_op opcode
;
523 struct wined3d_buffer
*buffer
;
525 struct wined3d_unordered_access_view
*view
;
528 struct wined3d_cs_generate_mipmaps
530 enum wined3d_cs_op opcode
;
531 struct wined3d_shader_resource_view
*view
;
534 struct wined3d_cs_execute_command_list
536 enum wined3d_cs_op opcode
;
537 struct wined3d_command_list
*list
;
540 struct wined3d_cs_stop
542 enum wined3d_cs_op opcode
;
545 static inline void *wined3d_device_context_require_space(struct wined3d_device_context
*context
,
546 size_t size
, enum wined3d_cs_queue_id queue_id
)
548 return context
->ops
->require_space(context
, size
, queue_id
);
551 static inline void wined3d_device_context_submit(struct wined3d_device_context
*context
,
552 enum wined3d_cs_queue_id queue_id
)
554 context
->ops
->submit(context
, queue_id
);
557 static inline void wined3d_device_context_finish(struct wined3d_device_context
*context
,
558 enum wined3d_cs_queue_id queue_id
)
560 context
->ops
->finish(context
, queue_id
);
563 static inline void wined3d_device_context_reference_resource(struct wined3d_device_context
*context
,
564 struct wined3d_resource
*resource
)
566 context
->ops
->reference_resource(context
, resource
);
569 static struct wined3d_cs
*wined3d_cs_from_context(struct wined3d_device_context
*context
)
571 return CONTAINING_RECORD(context
, struct wined3d_cs
, c
);
574 static const char *debug_cs_op(enum wined3d_cs_op op
)
578 #define WINED3D_TO_STR(type) case type: return #type
579 WINED3D_TO_STR(WINED3D_CS_OP_NOP
);
580 WINED3D_TO_STR(WINED3D_CS_OP_PRESENT
);
581 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR
);
582 WINED3D_TO_STR(WINED3D_CS_OP_DISPATCH
);
583 WINED3D_TO_STR(WINED3D_CS_OP_DRAW
);
584 WINED3D_TO_STR(WINED3D_CS_OP_FLUSH
);
585 WINED3D_TO_STR(WINED3D_CS_OP_SET_PREDICATION
);
586 WINED3D_TO_STR(WINED3D_CS_OP_SET_VIEWPORTS
);
587 WINED3D_TO_STR(WINED3D_CS_OP_SET_SCISSOR_RECTS
);
588 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
);
589 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
);
590 WINED3D_TO_STR(WINED3D_CS_OP_SET_VERTEX_DECLARATION
);
591 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCES
);
592 WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_OUTPUTS
);
593 WINED3D_TO_STR(WINED3D_CS_OP_SET_INDEX_BUFFER
);
594 WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFERS
);
595 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE
);
596 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
);
597 WINED3D_TO_STR(WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
);
598 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLERS
);
599 WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER
);
600 WINED3D_TO_STR(WINED3D_CS_OP_SET_BLEND_STATE
);
601 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
);
602 WINED3D_TO_STR(WINED3D_CS_OP_SET_RASTERIZER_STATE
);
603 WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_BOUNDS
);
604 WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDER_STATE
);
605 WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE_STATE
);
606 WINED3D_TO_STR(WINED3D_CS_OP_SET_SAMPLER_STATE
);
607 WINED3D_TO_STR(WINED3D_CS_OP_SET_TRANSFORM
);
608 WINED3D_TO_STR(WINED3D_CS_OP_SET_CLIP_PLANE
);
609 WINED3D_TO_STR(WINED3D_CS_OP_SET_COLOR_KEY
);
610 WINED3D_TO_STR(WINED3D_CS_OP_SET_MATERIAL
);
611 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT
);
612 WINED3D_TO_STR(WINED3D_CS_OP_SET_LIGHT_ENABLE
);
613 WINED3D_TO_STR(WINED3D_CS_OP_SET_FEATURE_LEVEL
);
614 WINED3D_TO_STR(WINED3D_CS_OP_PUSH_CONSTANTS
);
615 WINED3D_TO_STR(WINED3D_CS_OP_RESET_STATE
);
616 WINED3D_TO_STR(WINED3D_CS_OP_CALLBACK
);
617 WINED3D_TO_STR(WINED3D_CS_OP_QUERY_ISSUE
);
618 WINED3D_TO_STR(WINED3D_CS_OP_PRELOAD_RESOURCE
);
619 WINED3D_TO_STR(WINED3D_CS_OP_UNLOAD_RESOURCE
);
620 WINED3D_TO_STR(WINED3D_CS_OP_MAP
);
621 WINED3D_TO_STR(WINED3D_CS_OP_UNMAP
);
622 WINED3D_TO_STR(WINED3D_CS_OP_MAP_BO_ADDRESS
);
623 WINED3D_TO_STR(WINED3D_CS_OP_BLT_SUB_RESOURCE
);
624 WINED3D_TO_STR(WINED3D_CS_OP_UPDATE_SUB_RESOURCE
);
625 WINED3D_TO_STR(WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
);
626 WINED3D_TO_STR(WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
);
627 WINED3D_TO_STR(WINED3D_CS_OP_COPY_UAV_COUNTER
);
628 WINED3D_TO_STR(WINED3D_CS_OP_GENERATE_MIPMAPS
);
629 WINED3D_TO_STR(WINED3D_CS_OP_EXECUTE_COMMAND_LIST
);
630 WINED3D_TO_STR(WINED3D_CS_OP_STOP
);
631 #undef WINED3D_TO_STR
633 return wine_dbg_sprintf("UNKNOWN_OP(%#x)", op
);
636 static struct wined3d_cs_packet
*wined3d_next_cs_packet(const uint8_t *data
, SIZE_T
*offset
, SIZE_T mask
)
638 struct wined3d_cs_packet
*packet
= (struct wined3d_cs_packet
*)&data
[*offset
& mask
];
640 *offset
+= offsetof(struct wined3d_cs_packet
, data
[packet
->size
]);
645 static void wined3d_cs_exec_nop(struct wined3d_cs
*cs
, const void *data
)
649 static void wined3d_cs_exec_present(struct wined3d_cs
*cs
, const void *data
)
651 struct wined3d_texture
*logo_texture
, *cursor_texture
, *back_buffer
;
652 struct wined3d_rendertarget_view
*dsv
= cs
->state
.fb
.depth_stencil
;
653 const struct wined3d_cs_present
*op
= data
;
654 const struct wined3d_swapchain_desc
*desc
;
655 struct wined3d_swapchain
*swapchain
;
657 swapchain
= op
->swapchain
;
658 desc
= &swapchain
->state
.desc
;
659 back_buffer
= swapchain
->back_buffers
[0];
660 wined3d_swapchain_set_window(swapchain
, op
->dst_window_override
);
662 if ((logo_texture
= swapchain
->device
->logo_texture
))
664 RECT rect
= {0, 0, logo_texture
->resource
.width
, logo_texture
->resource
.height
};
666 /* Blit the logo into the upper left corner of the back-buffer. */
667 wined3d_device_context_blt(&cs
->c
, back_buffer
, 0, &rect
, logo_texture
, 0,
668 &rect
, WINED3D_BLT_SRC_CKEY
, NULL
, WINED3D_TEXF_POINT
);
671 if ((cursor_texture
= swapchain
->device
->cursor_texture
)
672 && swapchain
->device
->bCursorVisible
&& !swapchain
->device
->hardwareCursor
)
676 swapchain
->device
->xScreenSpace
- swapchain
->device
->xHotSpot
,
677 swapchain
->device
->yScreenSpace
- swapchain
->device
->yHotSpot
,
678 swapchain
->device
->xScreenSpace
+ swapchain
->device
->cursorWidth
- swapchain
->device
->xHotSpot
,
679 swapchain
->device
->yScreenSpace
+ swapchain
->device
->cursorHeight
- swapchain
->device
->yHotSpot
,
683 0, 0, cursor_texture
->resource
.width
, cursor_texture
->resource
.height
685 const RECT clip_rect
= {0, 0, back_buffer
->resource
.width
, back_buffer
->resource
.height
};
687 TRACE("Rendering the software cursor.\n");
690 MapWindowPoints(NULL
, swapchain
->win_handle
, (POINT
*)&dst_rect
, 2);
691 if (wined3d_clip_blit(&clip_rect
, &dst_rect
, &src_rect
))
692 wined3d_device_context_blt(&cs
->c
, back_buffer
, 0, &dst_rect
, cursor_texture
, 0,
693 &src_rect
, WINED3D_BLT_ALPHA_TEST
, NULL
, WINED3D_TEXF_POINT
);
696 swapchain
->swapchain_ops
->swapchain_present(swapchain
, &op
->src_rect
, &op
->dst_rect
, op
->swap_interval
, op
->flags
);
698 /* Discard buffers if the swap effect allows it. */
699 back_buffer
= swapchain
->back_buffers
[desc
->backbuffer_count
- 1];
700 if (desc
->swap_effect
== WINED3D_SWAP_EFFECT_DISCARD
|| desc
->swap_effect
== WINED3D_SWAP_EFFECT_FLIP_DISCARD
)
701 wined3d_texture_validate_location(back_buffer
, 0, WINED3D_LOCATION_DISCARDED
);
703 if (dsv
&& dsv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
705 struct wined3d_texture
*ds
= texture_from_resource(dsv
->resource
);
707 if ((desc
->flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
|| ds
->flags
& WINED3D_TEXTURE_DISCARD
))
708 wined3d_rendertarget_view_validate_location(dsv
, WINED3D_LOCATION_DISCARDED
);
713 DWORD time
= GetTickCount();
716 /* every 1.5 seconds */
717 if (time
- swapchain
->prev_time
> 1500)
719 TRACE_(fps
)("%p @ approx %.2ffps\n",
720 swapchain
, 1000.0 * swapchain
->frames
/ (time
- swapchain
->prev_time
));
721 swapchain
->prev_time
= time
;
722 swapchain
->frames
= 0;
726 InterlockedDecrement(&cs
->pending_presents
);
729 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
730 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
,
731 unsigned int swap_interval
, uint32_t flags
)
733 struct wined3d_cs_present
*op
;
737 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
738 op
->opcode
= WINED3D_CS_OP_PRESENT
;
739 op
->dst_window_override
= dst_window_override
;
740 op
->swapchain
= swapchain
;
741 op
->src_rect
= *src_rect
;
742 op
->dst_rect
= *dst_rect
;
743 op
->swap_interval
= swap_interval
;
746 pending
= InterlockedIncrement(&cs
->pending_presents
);
748 wined3d_resource_reference(&swapchain
->front_buffer
->resource
);
749 for (i
= 0; i
< swapchain
->state
.desc
.backbuffer_count
; ++i
)
751 wined3d_resource_reference(&swapchain
->back_buffers
[i
]->resource
);
754 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
756 /* Limit input latency by limiting the number of presents that we can get
757 * ahead of the worker thread. */
758 while (pending
>= swapchain
->max_frame_latency
)
761 pending
= InterlockedCompareExchange(&cs
->pending_presents
, 0, 0);
765 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
767 struct wined3d_device
*device
= cs
->c
.device
;
768 const struct wined3d_cs_clear
*op
= data
;
770 device
->blitter
->ops
->blitter_clear(device
->blitter
, device
, op
->rt_count
, &op
->fb
,
771 op
->rect_count
, op
->rects
, &op
->draw_rect
, op
->flags
, &op
->color
, op
->depth
, op
->stencil
);
774 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
775 uint32_t flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
777 const struct wined3d_state
*state
= cs
->c
.state
;
778 const struct wined3d_viewport
*vp
= &state
->viewports
[0];
779 struct wined3d_rendertarget_view
*view
;
780 struct wined3d_cs_clear
*op
;
781 unsigned int rt_count
, i
;
783 rt_count
= flags
& WINED3DCLEAR_TARGET
? cs
->c
.device
->adapter
->d3d_info
.limits
.max_rt_count
: 0;
785 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]),
786 WINED3D_CS_QUEUE_DEFAULT
);
787 op
->opcode
= WINED3D_CS_OP_CLEAR
;
788 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
789 op
->rt_count
= rt_count
;
791 SetRect(&op
->draw_rect
, vp
->x
, vp
->y
, vp
->x
+ vp
->width
, vp
->y
+ vp
->height
);
792 if (state
->rasterizer_state
&& state
->rasterizer_state
->desc
.scissor
)
793 IntersectRect(&op
->draw_rect
, &op
->draw_rect
, &state
->scissor_rects
[0]);
796 op
->stencil
= stencil
;
797 op
->rect_count
= rect_count
;
798 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
800 for (i
= 0; i
< rt_count
; ++i
)
802 if ((view
= state
->fb
.render_targets
[i
]))
803 wined3d_resource_reference(view
->resource
);
805 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
807 view
= state
->fb
.depth_stencil
;
808 wined3d_resource_reference(view
->resource
);
811 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
814 void wined3d_device_context_emit_clear_rendertarget_view(struct wined3d_device_context
*context
,
815 struct wined3d_rendertarget_view
*view
, const RECT
*rect
, unsigned int flags
,
816 const struct wined3d_color
*color
, float depth
, unsigned int stencil
)
818 struct wined3d_cs_clear
*op
;
821 size
= FIELD_OFFSET(struct wined3d_cs_clear
, rects
[1]);
822 op
= wined3d_device_context_require_space(context
, size
, WINED3D_CS_QUEUE_DEFAULT
);
824 op
->opcode
= WINED3D_CS_OP_CLEAR
;
825 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
826 if (flags
& WINED3DCLEAR_TARGET
)
829 op
->fb
.render_targets
[0] = view
;
830 op
->fb
.depth_stencil
= NULL
;
836 op
->fb
.render_targets
[0] = NULL
;
837 op
->fb
.depth_stencil
= view
;
839 op
->stencil
= stencil
;
841 SetRect(&op
->draw_rect
, 0, 0, view
->width
, view
->height
);
843 op
->rects
[0] = *rect
;
845 wined3d_device_context_reference_resource(context
, view
->resource
);
847 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
848 if (flags
& WINED3DCLEAR_SYNCHRONOUS
)
849 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
852 static void reference_shader_resources(struct wined3d_device_context
*context
, unsigned int shader_mask
)
854 const struct wined3d_state
*state
= context
->state
;
855 struct wined3d_shader_sampler_map_entry
*entry
;
856 struct wined3d_shader_resource_view
*view
;
857 struct wined3d_shader
*shader
;
860 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
862 if (!(shader_mask
& (1u << i
)))
865 if (!(shader
= state
->shader
[i
]))
868 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
870 if (state
->cb
[i
][j
].buffer
)
871 wined3d_device_context_reference_resource(context
, &state
->cb
[i
][j
].buffer
->resource
);
874 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
876 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
878 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
881 wined3d_device_context_reference_resource(context
, view
->resource
);
886 static void reference_unordered_access_resources(struct wined3d_device_context
*context
,
887 const struct wined3d_shader
*shader
, struct wined3d_unordered_access_view
* const *views
)
894 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
896 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
902 wined3d_device_context_reference_resource(context
, views
[i
]->resource
);
906 static void wined3d_cs_exec_dispatch(struct wined3d_cs
*cs
, const void *data
)
908 const struct wined3d_cs_dispatch
*op
= data
;
909 struct wined3d_state
*state
= &cs
->state
;
911 if (!state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
])
912 WARN("No compute shader bound, skipping dispatch.\n");
914 cs
->c
.device
->adapter
->adapter_ops
->adapter_dispatch_compute(cs
->c
.device
, state
, &op
->parameters
);
917 static void reference_compute_pipeline_resources(struct wined3d_device_context
*context
)
919 const struct wined3d_state
*state
= context
->state
;
921 reference_shader_resources(context
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
922 reference_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
923 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
926 void CDECL
wined3d_device_context_dispatch(struct wined3d_device_context
*context
,
927 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
929 struct wined3d_cs_dispatch
*op
;
931 wined3d_device_context_lock(context
);
932 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
933 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
934 op
->parameters
.indirect
= FALSE
;
935 op
->parameters
.u
.direct
.group_count_x
= group_count_x
;
936 op
->parameters
.u
.direct
.group_count_y
= group_count_y
;
937 op
->parameters
.u
.direct
.group_count_z
= group_count_z
;
939 reference_compute_pipeline_resources(context
);
941 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
942 wined3d_device_context_unlock(context
);
945 void CDECL
wined3d_device_context_dispatch_indirect(struct wined3d_device_context
*context
,
946 struct wined3d_buffer
*buffer
, unsigned int offset
)
948 struct wined3d_cs_dispatch
*op
;
950 wined3d_device_context_lock(context
);
951 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
952 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
953 op
->parameters
.indirect
= TRUE
;
954 op
->parameters
.u
.indirect
.buffer
= buffer
;
955 op
->parameters
.u
.indirect
.offset
= offset
;
957 reference_compute_pipeline_resources(context
);
958 wined3d_device_context_reference_resource(context
, &buffer
->resource
);
960 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
961 wined3d_device_context_unlock(context
);
964 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
966 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
967 const struct wined3d_shader
*geometry_shader
;
968 struct wined3d_device
*device
= cs
->c
.device
;
969 int base_vertex_idx
, load_base_vertex_idx
;
970 struct wined3d_state
*state
= &cs
->state
;
971 const struct wined3d_cs_draw
*op
= data
;
975 if (!op
->parameters
.indirect
)
977 const struct wined3d_direct_draw_parameters
*direct
= &op
->parameters
.u
.direct
;
979 if (op
->parameters
.indexed
&& d3d_info
->draw_base_vertex_offset
)
980 base_vertex_idx
= direct
->base_vertex_idx
;
981 else if (!op
->parameters
.indexed
)
982 base_vertex_idx
= direct
->start_idx
;
985 /* ARB_draw_indirect always supports a base vertex offset. */
986 if (!op
->parameters
.indirect
&& !d3d_info
->draw_base_vertex_offset
)
987 load_base_vertex_idx
= op
->parameters
.u
.direct
.base_vertex_idx
;
989 load_base_vertex_idx
= 0;
991 if (state
->base_vertex_index
!= base_vertex_idx
)
993 state
->base_vertex_index
= base_vertex_idx
;
994 for (i
= 0; i
< device
->context_count
; ++i
)
995 device
->contexts
[i
]->constant_update_mask
|= WINED3D_SHADER_CONST_BASE_VERTEX_ID
;
998 if (state
->load_base_vertex_index
!= load_base_vertex_idx
)
1000 state
->load_base_vertex_index
= load_base_vertex_idx
;
1001 device_invalidate_state(cs
->c
.device
, STATE_BASEVERTEXINDEX
);
1004 if (state
->primitive_type
!= op
->primitive_type
)
1006 if ((geometry_shader
= state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]) && !geometry_shader
->function
)
1007 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
));
1008 if (state
->primitive_type
== WINED3D_PT_POINTLIST
|| op
->primitive_type
== WINED3D_PT_POINTLIST
)
1009 device_invalidate_state(cs
->c
.device
, STATE_POINT_ENABLE
);
1010 state
->primitive_type
= op
->primitive_type
;
1012 state
->patch_vertex_count
= op
->patch_vertex_count
;
1014 cs
->c
.device
->adapter
->adapter_ops
->adapter_draw_primitive(cs
->c
.device
, state
, &op
->parameters
);
1017 static void reference_graphics_pipeline_resources(struct wined3d_device_context
*context
,
1018 BOOL indexed
, const struct wined3d_d3d_info
*d3d_info
)
1020 const struct wined3d_state
*state
= context
->state
;
1024 wined3d_device_context_reference_resource(context
, &state
->index_buffer
->resource
);
1025 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
1027 if (state
->streams
[i
].buffer
)
1028 wined3d_device_context_reference_resource(context
, &state
->streams
[i
].buffer
->resource
);
1030 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
1032 if (state
->stream_output
[i
].buffer
)
1033 wined3d_device_context_reference_resource(context
, &state
->stream_output
[i
].buffer
->resource
);
1035 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
1037 if (state
->textures
[i
])
1038 wined3d_device_context_reference_resource(context
, &state
->textures
[i
]->resource
);
1040 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
1042 if (state
->fb
.render_targets
[i
])
1043 wined3d_device_context_reference_resource(context
, state
->fb
.render_targets
[i
]->resource
);
1045 if (state
->fb
.depth_stencil
)
1046 wined3d_device_context_reference_resource(context
, state
->fb
.depth_stencil
->resource
);
1047 reference_shader_resources(context
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
1048 reference_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
1049 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
1052 void wined3d_device_context_emit_draw(struct wined3d_device_context
*context
,
1053 enum wined3d_primitive_type primitive_type
, unsigned int patch_vertex_count
, int base_vertex_idx
,
1054 unsigned int start_idx
, unsigned int index_count
, unsigned int start_instance
, unsigned int instance_count
,
1057 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1058 struct wined3d_cs_draw
*op
;
1060 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1061 op
->opcode
= WINED3D_CS_OP_DRAW
;
1062 op
->primitive_type
= primitive_type
;
1063 op
->patch_vertex_count
= patch_vertex_count
;
1064 op
->parameters
.indirect
= FALSE
;
1065 op
->parameters
.u
.direct
.base_vertex_idx
= base_vertex_idx
;
1066 op
->parameters
.u
.direct
.start_idx
= start_idx
;
1067 op
->parameters
.u
.direct
.index_count
= index_count
;
1068 op
->parameters
.u
.direct
.start_instance
= start_instance
;
1069 op
->parameters
.u
.direct
.instance_count
= instance_count
;
1070 op
->parameters
.indexed
= indexed
;
1072 reference_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1074 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1077 void CDECL
wined3d_device_context_draw_indirect(struct wined3d_device_context
*context
,
1078 struct wined3d_buffer
*buffer
, unsigned int offset
, bool indexed
)
1080 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1081 const struct wined3d_state
*state
= context
->state
;
1082 struct wined3d_cs_draw
*op
;
1084 wined3d_device_context_lock(context
);
1085 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1086 op
->opcode
= WINED3D_CS_OP_DRAW
;
1087 op
->primitive_type
= state
->primitive_type
;
1088 op
->patch_vertex_count
= state
->patch_vertex_count
;
1089 op
->parameters
.indirect
= TRUE
;
1090 op
->parameters
.u
.indirect
.buffer
= buffer
;
1091 op
->parameters
.u
.indirect
.offset
= offset
;
1092 op
->parameters
.indexed
= indexed
;
1094 reference_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1095 wined3d_device_context_reference_resource(context
, &buffer
->resource
);
1097 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1098 wined3d_device_context_unlock(context
);
1101 static void wined3d_cs_exec_flush(struct wined3d_cs
*cs
, const void *data
)
1103 struct wined3d_context
*context
;
1105 context
= context_acquire(cs
->c
.device
, NULL
, 0);
1106 cs
->c
.device
->adapter
->adapter_ops
->adapter_flush_context(context
);
1107 context_release(context
);
1110 static void wined3d_cs_flush(struct wined3d_device_context
*context
)
1112 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
1113 struct wined3d_cs_flush
*op
;
1115 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1116 op
->opcode
= WINED3D_CS_OP_FLUSH
;
1118 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1119 cs
->queries_flushed
= TRUE
;
1122 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
1124 const struct wined3d_cs_set_predication
*op
= data
;
1126 cs
->state
.predicate
= op
->predicate
;
1127 cs
->state
.predicate_value
= op
->value
;
1130 void wined3d_device_context_emit_set_predication(struct wined3d_device_context
*context
,
1131 struct wined3d_query
*predicate
, BOOL value
)
1133 struct wined3d_cs_set_predication
*op
;
1135 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1136 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
1137 op
->predicate
= predicate
;
1140 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1143 static void wined3d_cs_exec_set_viewports(struct wined3d_cs
*cs
, const void *data
)
1145 const struct wined3d_cs_set_viewports
*op
= data
;
1147 if (op
->viewport_count
)
1148 memcpy(cs
->state
.viewports
, op
->viewports
, op
->viewport_count
* sizeof(*op
->viewports
));
1150 memset(cs
->state
.viewports
, 0, sizeof(*cs
->state
.viewports
));
1151 cs
->state
.viewport_count
= op
->viewport_count
;
1152 device_invalidate_state(cs
->c
.device
, STATE_VIEWPORT
);
1155 void wined3d_device_context_emit_set_viewports(struct wined3d_device_context
*context
, unsigned int viewport_count
,
1156 const struct wined3d_viewport
*viewports
)
1158 struct wined3d_cs_set_viewports
*op
;
1160 op
= wined3d_device_context_require_space(context
,
1161 FIELD_OFFSET(struct wined3d_cs_set_viewports
,viewports
[viewport_count
]), WINED3D_CS_QUEUE_DEFAULT
);
1162 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORTS
;
1163 memcpy(op
->viewports
, viewports
, viewport_count
* sizeof(*viewports
));
1164 op
->viewport_count
= viewport_count
;
1166 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1169 static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs
*cs
, const void *data
)
1171 const struct wined3d_cs_set_scissor_rects
*op
= data
;
1174 memcpy(cs
->state
.scissor_rects
, op
->rects
, op
->rect_count
* sizeof(*op
->rects
));
1176 SetRectEmpty(cs
->state
.scissor_rects
);
1177 cs
->state
.scissor_rect_count
= op
->rect_count
;
1178 device_invalidate_state(cs
->c
.device
, STATE_SCISSORRECT
);
1181 void wined3d_device_context_emit_set_scissor_rects(struct wined3d_device_context
*context
,
1182 unsigned int rect_count
, const RECT
*rects
)
1184 struct wined3d_cs_set_scissor_rects
*op
;
1186 op
= wined3d_device_context_require_space(context
, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects
, rects
[rect_count
]),
1187 WINED3D_CS_QUEUE_DEFAULT
);
1188 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECTS
;
1189 memcpy(op
->rects
, rects
, rect_count
* sizeof(*rects
));
1190 op
->rect_count
= rect_count
;
1192 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1195 static void wined3d_cs_exec_set_rendertarget_views(struct wined3d_cs
*cs
, const void *data
)
1197 const struct wined3d_cs_set_rendertarget_views
*op
= data
;
1198 struct wined3d_device
*device
= cs
->c
.device
;
1201 for (i
= 0; i
< op
->count
; ++i
)
1203 struct wined3d_rendertarget_view
*prev
= cs
->state
.fb
.render_targets
[op
->start_idx
+ i
];
1204 struct wined3d_rendertarget_view
*view
= op
->views
[i
];
1205 bool prev_alpha_swizzle
, curr_alpha_swizzle
;
1206 bool prev_srgb_write
, curr_srgb_write
;
1208 cs
->state
.fb
.render_targets
[op
->start_idx
+ i
] = view
;
1210 prev_alpha_swizzle
= prev
&& prev
->format
->id
== WINED3DFMT_A8_UNORM
;
1211 curr_alpha_swizzle
= view
&& view
->format
->id
== WINED3DFMT_A8_UNORM
;
1212 if (prev_alpha_swizzle
!= curr_alpha_swizzle
)
1213 device_invalidate_state(device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1215 if (!(device
->adapter
->d3d_info
.wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
1216 || cs
->state
.render_states
[WINED3D_RS_SRGBWRITEENABLE
])
1218 prev_srgb_write
= prev
&& prev
->format_caps
& WINED3D_FORMAT_CAP_SRGB_WRITE
;
1219 curr_srgb_write
= view
&& view
->format_caps
& WINED3D_FORMAT_CAP_SRGB_WRITE
;
1220 if (prev_srgb_write
!= curr_srgb_write
)
1221 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE
));
1225 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1228 void wined3d_device_context_emit_set_rendertarget_views(struct wined3d_device_context
*context
,
1229 unsigned int start_idx
, unsigned int count
, struct wined3d_rendertarget_view
*const *views
)
1231 struct wined3d_cs_set_rendertarget_views
*op
;
1233 op
= wined3d_device_context_require_space(context
,
1234 offsetof(struct wined3d_cs_set_rendertarget_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1235 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
;
1236 op
->start_idx
= start_idx
;
1238 memcpy(op
->views
, views
, count
* sizeof(*views
));
1240 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1243 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
1245 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
1246 struct wined3d_device
*device
= cs
->c
.device
;
1247 struct wined3d_rendertarget_view
*prev
;
1249 if ((prev
= cs
->state
.fb
.depth_stencil
) && prev
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
1251 struct wined3d_texture
*prev_texture
= texture_from_resource(prev
->resource
);
1253 if (device
->swapchains
[0]->state
.desc
.flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
1254 || prev_texture
->flags
& WINED3D_TEXTURE_DISCARD
)
1255 wined3d_texture_validate_location(prev_texture
,
1256 prev
->sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
1259 cs
->state
.fb
.depth_stencil
= op
->view
;
1261 if (!prev
!= !op
->view
)
1263 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
1264 device_invalidate_state(device
, STATE_DEPTH_STENCIL
);
1265 device_invalidate_state(device
, STATE_STENCIL_REF
);
1266 device_invalidate_state(device
, STATE_RASTERIZER
);
1270 if (prev
->format
->depth_bias_scale
!= op
->view
->format
->depth_bias_scale
)
1271 device_invalidate_state(device
, STATE_RASTERIZER
);
1272 if (prev
->format
->stencil_size
!= op
->view
->format
->stencil_size
)
1273 device_invalidate_state(device
, STATE_STENCIL_REF
);
1276 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1279 void wined3d_device_context_emit_set_depth_stencil_view(struct wined3d_device_context
*context
,
1280 struct wined3d_rendertarget_view
*view
)
1282 struct wined3d_cs_set_depth_stencil_view
*op
;
1284 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1285 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
1288 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1291 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
1293 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
1295 cs
->state
.vertex_declaration
= op
->declaration
;
1296 device_invalidate_state(cs
->c
.device
, STATE_VDECL
);
1299 void wined3d_device_context_emit_set_vertex_declaration(struct wined3d_device_context
*context
,
1300 struct wined3d_vertex_declaration
*declaration
)
1302 struct wined3d_cs_set_vertex_declaration
*op
;
1304 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1305 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
1306 op
->declaration
= declaration
;
1308 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1311 static void wined3d_cs_exec_set_stream_sources(struct wined3d_cs
*cs
, const void *data
)
1313 const struct wined3d_cs_set_stream_sources
*op
= data
;
1316 for (i
= 0; i
< op
->count
; ++i
)
1318 struct wined3d_buffer
*prev
= cs
->state
.streams
[op
->start_idx
+ i
].buffer
;
1319 struct wined3d_buffer
*buffer
= op
->streams
[i
].buffer
;
1322 InterlockedIncrement(&buffer
->resource
.bind_count
);
1324 InterlockedDecrement(&prev
->resource
.bind_count
);
1327 memcpy(&cs
->state
.streams
[op
->start_idx
], op
->streams
, op
->count
* sizeof(*op
->streams
));
1328 device_invalidate_state(cs
->c
.device
, STATE_STREAMSRC
);
1331 void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context
*context
,
1332 unsigned int start_idx
, unsigned int count
, const struct wined3d_stream_state
*streams
)
1334 struct wined3d_cs_set_stream_sources
*op
;
1336 op
= wined3d_device_context_require_space(context
,
1337 offsetof(struct wined3d_cs_set_stream_sources
, streams
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1338 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCES
;
1339 op
->start_idx
= start_idx
;
1341 memcpy(op
->streams
, streams
, count
* sizeof(*streams
));
1343 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1346 static void wined3d_cs_exec_set_stream_outputs(struct wined3d_cs
*cs
, const void *data
)
1348 const struct wined3d_cs_set_stream_outputs
*op
= data
;
1351 for (i
= 0; i
< WINED3D_MAX_STREAM_OUTPUT_BUFFERS
; ++i
)
1353 struct wined3d_buffer
*prev
= cs
->state
.stream_output
[i
].buffer
;
1354 struct wined3d_buffer
*buffer
= op
->outputs
[i
].buffer
;
1357 InterlockedIncrement(&buffer
->resource
.bind_count
);
1359 InterlockedDecrement(&prev
->resource
.bind_count
);
1362 memcpy(cs
->state
.stream_output
, op
->outputs
, sizeof(op
->outputs
));
1363 device_invalidate_state(cs
->c
.device
, STATE_STREAM_OUTPUT
);
1366 void wined3d_device_context_emit_set_stream_outputs(struct wined3d_device_context
*context
,
1367 const struct wined3d_stream_output outputs
[WINED3D_MAX_STREAM_OUTPUT_BUFFERS
])
1369 struct wined3d_cs_set_stream_outputs
*op
;
1371 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1372 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUTS
;
1373 memcpy(op
->outputs
, outputs
, sizeof(op
->outputs
));
1375 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1378 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
1380 const struct wined3d_cs_set_index_buffer
*op
= data
;
1381 struct wined3d_buffer
*prev
;
1383 prev
= cs
->state
.index_buffer
;
1384 cs
->state
.index_buffer
= op
->buffer
;
1385 cs
->state
.index_format
= op
->format_id
;
1386 cs
->state
.index_offset
= op
->offset
;
1389 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1391 InterlockedDecrement(&prev
->resource
.bind_count
);
1393 device_invalidate_state(cs
->c
.device
, STATE_INDEXBUFFER
);
1396 void wined3d_device_context_emit_set_index_buffer(struct wined3d_device_context
*context
, struct wined3d_buffer
*buffer
,
1397 enum wined3d_format_id format_id
, unsigned int offset
)
1399 struct wined3d_cs_set_index_buffer
*op
;
1401 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1402 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
1403 op
->buffer
= buffer
;
1404 op
->format_id
= format_id
;
1405 op
->offset
= offset
;
1407 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1410 static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs
*cs
, const void *data
)
1412 const struct wined3d_cs_set_constant_buffers
*op
= data
;
1415 for (i
= 0; i
< op
->count
; ++i
)
1417 struct wined3d_buffer
*prev
= cs
->state
.cb
[op
->type
][op
->start_idx
+ i
].buffer
;
1418 struct wined3d_buffer
*buffer
= op
->buffers
[i
].buffer
;
1420 cs
->state
.cb
[op
->type
][op
->start_idx
+ i
] = op
->buffers
[i
];
1423 InterlockedIncrement(&buffer
->resource
.bind_count
);
1425 InterlockedDecrement(&prev
->resource
.bind_count
);
1428 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1431 void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context
*context
,
1432 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1433 const struct wined3d_constant_buffer_state
*buffers
)
1435 struct wined3d_cs_set_constant_buffers
*op
;
1437 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_constant_buffers
, buffers
[count
]),
1438 WINED3D_CS_QUEUE_DEFAULT
);
1439 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFERS
;
1441 op
->start_idx
= start_idx
;
1443 memcpy(op
->buffers
, buffers
, count
* sizeof(*buffers
));
1445 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1448 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
1450 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
1451 const struct wined3d_cs_set_texture
*op
= data
;
1452 struct wined3d_texture
*prev
;
1453 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
1455 prev
= cs
->state
.textures
[op
->stage
];
1456 cs
->state
.textures
[op
->stage
] = op
->texture
;
1460 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
1461 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
1462 unsigned int old_fmt_caps
= prev
? prev
->resource
.format_caps
: 0;
1463 unsigned int new_fmt_caps
= op
->texture
->resource
.format_caps
;
1465 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
1466 op
->texture
->sampler
= op
->stage
;
1468 if (!prev
|| wined3d_texture_gl(op
->texture
)->target
!= wined3d_texture_gl(prev
)->target
1469 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
1470 && !(can_use_texture_swizzle(d3d_info
, new_format
) && can_use_texture_swizzle(d3d_info
, old_format
)))
1471 || (new_fmt_caps
& WINED3D_FORMAT_CAP_SHADOW
) != (old_fmt_caps
& WINED3D_FORMAT_CAP_SHADOW
))
1472 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1474 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1476 /* The source arguments for color and alpha ops have different
1477 * meanings when a NULL texture is bound, so the COLOR_OP and
1478 * ALPHA_OP have to be dirtified. */
1479 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1480 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1483 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1484 new_use_color_key
= TRUE
;
1489 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
1493 /* Search for other stages the texture is bound to. Shouldn't
1494 * happen if applications bind textures to a single stage only. */
1495 TRACE("Searching for other stages the texture is bound to.\n");
1496 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
1498 if (cs
->state
.textures
[i
] == prev
)
1500 TRACE("Texture is also bound to stage %u.\n", i
);
1507 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1509 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1510 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1513 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1514 old_use_color_key
= TRUE
;
1517 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->stage
));
1519 if (new_use_color_key
!= old_use_color_key
)
1520 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1522 if (new_use_color_key
)
1523 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1526 void wined3d_device_context_emit_set_texture(struct wined3d_device_context
*context
, unsigned int stage
,
1527 struct wined3d_texture
*texture
)
1529 struct wined3d_cs_set_texture
*op
;
1531 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1532 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
1534 op
->texture
= texture
;
1536 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1539 static void wined3d_cs_exec_set_shader_resource_views(struct wined3d_cs
*cs
, const void *data
)
1541 const struct wined3d_cs_set_shader_resource_views
*op
= data
;
1544 for (i
= 0; i
< op
->count
; ++i
)
1546 struct wined3d_shader_resource_view
*prev
= cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
];
1547 struct wined3d_shader_resource_view
*view
= op
->views
[i
];
1549 cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
] = view
;
1552 InterlockedIncrement(&view
->resource
->bind_count
);
1554 InterlockedDecrement(&prev
->resource
->bind_count
);
1557 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1558 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1560 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1563 void wined3d_device_context_emit_set_shader_resource_views(struct wined3d_device_context
*context
,
1564 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1565 struct wined3d_shader_resource_view
*const *views
)
1567 struct wined3d_cs_set_shader_resource_views
*op
;
1569 op
= wined3d_device_context_require_space(context
,
1570 offsetof(struct wined3d_cs_set_shader_resource_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1571 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
;
1573 op
->start_idx
= start_idx
;
1575 memcpy(op
->views
, views
, count
* sizeof(*views
));
1577 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1580 static void wined3d_cs_exec_set_unordered_access_views(struct wined3d_cs
*cs
, const void *data
)
1582 const struct wined3d_cs_set_unordered_access_views
*op
= data
;
1585 for (i
= 0; i
< op
->count
; ++i
)
1587 struct wined3d_unordered_access_view
*prev
= cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
];
1588 struct wined3d_unordered_access_view
*view
= op
->uavs
[i
].view
;
1589 unsigned int initial_count
= op
->uavs
[i
].initial_count
;
1591 cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
] = view
;
1594 InterlockedIncrement(&view
->resource
->bind_count
);
1596 InterlockedDecrement(&prev
->resource
->bind_count
);
1598 if (view
&& initial_count
!= ~0u)
1599 wined3d_unordered_access_view_set_counter(view
, initial_count
);
1602 device_invalidate_state(cs
->c
.device
, STATE_UNORDERED_ACCESS_VIEW_BINDING(op
->pipeline
));
1605 void wined3d_device_context_emit_set_unordered_access_views(struct wined3d_device_context
*context
,
1606 enum wined3d_pipeline pipeline
, unsigned int start_idx
, unsigned int count
,
1607 struct wined3d_unordered_access_view
*const *views
, const unsigned int *initial_counts
)
1609 struct wined3d_cs_set_unordered_access_views
*op
;
1612 op
= wined3d_device_context_require_space(context
,
1613 offsetof(struct wined3d_cs_set_unordered_access_views
, uavs
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1614 op
->opcode
= WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
;
1615 op
->pipeline
= pipeline
;
1616 op
->start_idx
= start_idx
;
1618 for (i
= 0; i
< count
; ++i
)
1620 op
->uavs
[i
].view
= views
[i
];
1621 op
->uavs
[i
].initial_count
= initial_counts
? initial_counts
[i
] : ~0u;
1624 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1627 static void wined3d_cs_exec_set_samplers(struct wined3d_cs
*cs
, const void *data
)
1629 const struct wined3d_cs_set_samplers
*op
= data
;
1632 for (i
= 0; i
< op
->count
; ++i
)
1633 cs
->state
.sampler
[op
->type
][op
->start_idx
+ i
] = op
->samplers
[i
];
1635 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1636 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1638 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1641 void wined3d_device_context_emit_set_samplers(struct wined3d_device_context
*context
, enum wined3d_shader_type type
,
1642 unsigned int start_idx
, unsigned int count
, struct wined3d_sampler
*const *samplers
)
1644 struct wined3d_cs_set_samplers
*op
;
1646 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_samplers
, samplers
[count
]),
1647 WINED3D_CS_QUEUE_DEFAULT
);
1648 op
->opcode
= WINED3D_CS_OP_SET_SAMPLERS
;
1650 op
->start_idx
= start_idx
;
1652 memcpy(op
->samplers
, samplers
, count
* sizeof(*samplers
));
1654 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1657 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
1659 const struct wined3d_cs_set_shader
*op
= data
;
1661 /* CB binding may have been skipped earlier if the shader wasn't set, so make it happen. */
1662 if (!cs
->state
.shader
[op
->type
] && op
->shader
)
1663 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1664 cs
->state
.shader
[op
->type
] = op
->shader
;
1665 device_invalidate_state(cs
->c
.device
, STATE_SHADER(op
->type
));
1666 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1667 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1669 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1672 void wined3d_device_context_emit_set_shader(struct wined3d_device_context
*context
,
1673 enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
1675 struct wined3d_cs_set_shader
*op
;
1677 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1678 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
1680 op
->shader
= shader
;
1682 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1685 static void wined3d_cs_exec_set_blend_state(struct wined3d_cs
*cs
, const void *data
)
1687 const struct wined3d_cs_set_blend_state
*op
= data
;
1688 struct wined3d_state
*state
= &cs
->state
;
1690 if (state
->blend_state
!= op
->state
)
1692 state
->blend_state
= op
->state
;
1693 device_invalidate_state(cs
->c
.device
, STATE_BLEND
);
1695 state
->blend_factor
= op
->factor
;
1696 device_invalidate_state(cs
->c
.device
, STATE_BLEND_FACTOR
);
1697 state
->sample_mask
= op
->sample_mask
;
1698 device_invalidate_state(cs
->c
.device
, STATE_SAMPLE_MASK
);
1701 void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context
*context
,
1702 struct wined3d_blend_state
*state
, const struct wined3d_color
*blend_factor
, unsigned int sample_mask
)
1704 struct wined3d_cs_set_blend_state
*op
;
1706 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1707 op
->opcode
= WINED3D_CS_OP_SET_BLEND_STATE
;
1709 op
->factor
= *blend_factor
;
1710 op
->sample_mask
= sample_mask
;
1712 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1715 static void wined3d_cs_exec_set_depth_stencil_state(struct wined3d_cs
*cs
, const void *data
)
1717 const struct wined3d_cs_set_depth_stencil_state
*op
= data
;
1718 struct wined3d_state
*state
= &cs
->state
;
1720 if (state
->depth_stencil_state
!= op
->state
)
1722 state
->depth_stencil_state
= op
->state
;
1723 device_invalidate_state(cs
->c
.device
, STATE_DEPTH_STENCIL
);
1725 state
->stencil_ref
= op
->stencil_ref
;
1726 device_invalidate_state(cs
->c
.device
, STATE_STENCIL_REF
);
1729 void wined3d_device_context_emit_set_depth_stencil_state(struct wined3d_device_context
*context
,
1730 struct wined3d_depth_stencil_state
*state
, unsigned int stencil_ref
)
1732 struct wined3d_cs_set_depth_stencil_state
*op
;
1734 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1735 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
;
1737 op
->stencil_ref
= stencil_ref
;
1739 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1742 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs
, const void *data
)
1744 const struct wined3d_cs_set_rasterizer_state
*op
= data
;
1746 cs
->state
.rasterizer_state
= op
->state
;
1747 device_invalidate_state(cs
->c
.device
, STATE_RASTERIZER
);
1750 void wined3d_device_context_emit_set_rasterizer_state(struct wined3d_device_context
*context
,
1751 struct wined3d_rasterizer_state
*rasterizer_state
)
1753 struct wined3d_cs_set_rasterizer_state
*op
;
1755 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1756 op
->opcode
= WINED3D_CS_OP_SET_RASTERIZER_STATE
;
1757 op
->state
= rasterizer_state
;
1759 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1762 static void wined3d_cs_exec_set_depth_bounds(struct wined3d_cs
*cs
, const void *data
)
1764 const struct wined3d_cs_set_depth_bounds
*op
= data
;
1766 cs
->state
.depth_bounds_enable
= op
->enable
;
1767 cs
->state
.depth_bounds_min
= op
->min_depth
;
1768 cs
->state
.depth_bounds_max
= op
->max_depth
;
1769 device_invalidate_state(cs
->c
.device
, STATE_DEPTH_BOUNDS
);
1772 void wined3d_device_context_set_depth_bounds(struct wined3d_device_context
*context
,
1773 bool enable
, float min_depth
, float max_depth
)
1775 struct wined3d_cs_set_depth_bounds
*op
;
1777 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1778 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_BOUNDS
;
1779 op
->enable
= enable
;
1780 op
->min_depth
= min_depth
;
1781 op
->max_depth
= max_depth
;
1783 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1786 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
1788 const struct wined3d_cs_set_render_state
*op
= data
;
1790 cs
->state
.render_states
[op
->state
] = op
->value
;
1791 device_invalidate_state(cs
->c
.device
, STATE_RENDER(op
->state
));
1794 void wined3d_device_context_emit_set_render_state(struct wined3d_device_context
*context
,
1795 enum wined3d_render_state state
, unsigned int value
)
1797 struct wined3d_cs_set_render_state
*op
;
1799 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1800 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
1804 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1807 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
1809 const struct wined3d_cs_set_texture_state
*op
= data
;
1811 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
1812 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
1815 void wined3d_device_context_emit_set_texture_state(struct wined3d_device_context
*context
, unsigned int stage
,
1816 enum wined3d_texture_stage_state state
, unsigned int value
)
1818 struct wined3d_cs_set_texture_state
*op
;
1820 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1821 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
1826 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1829 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
1831 const struct wined3d_cs_set_sampler_state
*op
= data
;
1833 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
1834 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->sampler_idx
));
1837 void wined3d_device_context_emit_set_sampler_state(struct wined3d_device_context
*context
, unsigned int sampler_idx
,
1838 enum wined3d_sampler_state state
, unsigned int value
)
1840 struct wined3d_cs_set_sampler_state
*op
;
1842 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1843 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
1844 op
->sampler_idx
= sampler_idx
;
1848 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1851 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
1853 const struct wined3d_cs_set_transform
*op
= data
;
1855 cs
->state
.transforms
[op
->state
] = op
->matrix
;
1856 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->c
.device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
1857 device_invalidate_state(cs
->c
.device
, STATE_TRANSFORM(op
->state
));
1860 void wined3d_device_context_emit_set_transform(struct wined3d_device_context
*context
,
1861 enum wined3d_transform_state state
, const struct wined3d_matrix
*matrix
)
1863 struct wined3d_cs_set_transform
*op
;
1865 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1866 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
1868 op
->matrix
= *matrix
;
1870 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1873 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
1875 const struct wined3d_cs_set_clip_plane
*op
= data
;
1877 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
1878 device_invalidate_state(cs
->c
.device
, STATE_CLIPPLANE(op
->plane_idx
));
1881 void wined3d_device_context_emit_set_clip_plane(struct wined3d_device_context
*context
,
1882 unsigned int plane_idx
, const struct wined3d_vec4
*plane
)
1884 struct wined3d_cs_set_clip_plane
*op
;
1886 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1887 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
1888 op
->plane_idx
= plane_idx
;
1891 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1894 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
1896 const struct wined3d_cs_set_color_key
*op
= data
;
1897 struct wined3d_texture
*texture
= op
->texture
;
1903 case WINED3D_CKEY_DST_BLT
:
1904 texture
->async
.dst_blt_color_key
= op
->color_key
;
1905 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
1908 case WINED3D_CKEY_DST_OVERLAY
:
1909 texture
->async
.dst_overlay_color_key
= op
->color_key
;
1910 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
1913 case WINED3D_CKEY_SRC_BLT
:
1914 if (texture
== cs
->state
.textures
[0])
1916 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1917 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
1918 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1921 texture
->async
.src_blt_color_key
= op
->color_key
;
1922 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
1925 case WINED3D_CKEY_SRC_OVERLAY
:
1926 texture
->async
.src_overlay_color_key
= op
->color_key
;
1927 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
1935 case WINED3D_CKEY_DST_BLT
:
1936 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
1939 case WINED3D_CKEY_DST_OVERLAY
:
1940 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
1943 case WINED3D_CKEY_SRC_BLT
:
1944 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1945 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1947 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
1950 case WINED3D_CKEY_SRC_OVERLAY
:
1951 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
1957 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
1958 WORD flags
, const struct wined3d_color_key
*color_key
)
1960 struct wined3d_cs_set_color_key
*op
;
1962 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1963 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
1964 op
->texture
= texture
;
1968 op
->color_key
= *color_key
;
1974 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
1977 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
1979 const struct wined3d_cs_set_material
*op
= data
;
1981 cs
->state
.material
= op
->material
;
1982 device_invalidate_state(cs
->c
.device
, STATE_MATERIAL
);
1985 void wined3d_device_context_emit_set_material(struct wined3d_device_context
*context
,
1986 const struct wined3d_material
*material
)
1988 struct wined3d_cs_set_material
*op
;
1990 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1991 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
1992 op
->material
= *material
;
1994 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1997 static void wined3d_cs_exec_set_light(struct wined3d_cs
*cs
, const void *data
)
1999 const struct wined3d_cs_set_light
*op
= data
;
2000 struct wined3d_light_info
*light_info
;
2001 unsigned int light_idx
;
2003 light_idx
= op
->light
.OriginalIndex
;
2005 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, light_idx
)))
2007 TRACE("Adding new light.\n");
2008 if (!(light_info
= heap_alloc_zero(sizeof(*light_info
))))
2010 ERR("Failed to allocate light info.\n");
2014 light_info
->glIndex
= -1;
2015 light_info
->OriginalIndex
= light_idx
;
2016 rb_put(&cs
->state
.light_state
.lights_tree
, (void *)(ULONG_PTR
)light_idx
, &light_info
->entry
);
2019 if (light_info
->glIndex
!= -1)
2021 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
2022 device_invalidate_state(cs
->c
.device
, STATE_LIGHT_TYPE
);
2023 device_invalidate_state(cs
->c
.device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
2026 light_info
->OriginalParms
= op
->light
.OriginalParms
;
2027 light_info
->position
= op
->light
.position
;
2028 light_info
->direction
= op
->light
.direction
;
2029 light_info
->exponent
= op
->light
.exponent
;
2030 light_info
->cutoff
= op
->light
.cutoff
;
2033 void wined3d_device_context_emit_set_light(struct wined3d_device_context
*context
,
2034 const struct wined3d_light_info
*light
)
2036 struct wined3d_cs_set_light
*op
;
2038 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2039 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
2042 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2045 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
2047 const struct wined3d_cs_set_light_enable
*op
= data
;
2048 struct wined3d_device
*device
= cs
->c
.device
;
2049 struct wined3d_light_info
*light_info
;
2052 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, op
->idx
)))
2054 ERR("Light doesn't exist.\n");
2058 prev_idx
= light_info
->glIndex
;
2059 if (wined3d_light_state_enable_light(&cs
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
))
2061 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
2062 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
2066 void wined3d_device_context_emit_set_light_enable(struct wined3d_device_context
*context
, unsigned int idx
, BOOL enable
)
2068 struct wined3d_cs_set_light_enable
*op
;
2070 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2071 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
2073 op
->enable
= enable
;
2075 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2078 static void wined3d_cs_exec_set_feature_level(struct wined3d_cs
*cs
, const void *data
)
2080 const struct wined3d_cs_set_feature_level
*op
= data
;
2082 cs
->state
.feature_level
= op
->level
;
2085 void wined3d_device_context_emit_set_feature_level(struct wined3d_device_context
*context
,
2086 enum wined3d_feature_level level
)
2088 struct wined3d_cs_set_feature_level
*op
;
2090 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2091 op
->opcode
= WINED3D_CS_OP_SET_FEATURE_LEVEL
;
2094 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2103 wined3d_cs_push_constant_info
[] =
2105 /* WINED3D_PUSH_CONSTANTS_VS_F */
2106 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
2107 /* WINED3D_PUSH_CONSTANTS_PS_F */
2108 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
2109 /* WINED3D_PUSH_CONSTANTS_VS_I */
2110 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
2111 /* WINED3D_PUSH_CONSTANTS_PS_I */
2112 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
2113 /* WINED3D_PUSH_CONSTANTS_VS_B */
2114 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
2115 /* WINED3D_PUSH_CONSTANTS_PS_B */
2116 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
2119 static void wined3d_cs_st_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2120 unsigned int start_idx
, unsigned int count
, const void *constants
)
2122 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2123 struct wined3d_device
*device
= cs
->c
.device
;
2124 unsigned int context_count
;
2128 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
2129 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
2130 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
2131 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
2133 offset
= wined3d_cs_push_constant_info
[p
].offset
+ start_idx
* wined3d_cs_push_constant_info
[p
].size
;
2134 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* wined3d_cs_push_constant_info
[p
].size
);
2135 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
2137 device
->contexts
[i
]->constant_update_mask
|= wined3d_cs_push_constant_info
[p
].mask
;
2141 static void wined3d_cs_exec_push_constants(struct wined3d_cs
*cs
, const void *data
)
2143 const struct wined3d_cs_push_constants
*op
= data
;
2145 wined3d_cs_st_push_constants(&cs
->c
, op
->type
, op
->start_idx
, op
->count
, op
->constants
);
2148 static void wined3d_cs_mt_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2149 unsigned int start_idx
, unsigned int count
, const void *constants
)
2151 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2152 struct wined3d_cs_push_constants
*op
;
2155 size
= count
* wined3d_cs_push_constant_info
[p
].size
;
2156 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_push_constants
, constants
[size
]),
2157 WINED3D_CS_QUEUE_DEFAULT
);
2158 op
->opcode
= WINED3D_CS_OP_PUSH_CONSTANTS
;
2160 op
->start_idx
= start_idx
;
2162 memcpy(op
->constants
, constants
, size
);
2164 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2167 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
2169 const struct wined3d_device
*device
= cs
->c
.device
;
2170 const struct wined3d_cs_reset_state
*op
= data
;
2171 const struct wined3d_state_entry
*state_table
;
2174 state_cleanup(&cs
->state
);
2175 wined3d_state_reset(&cs
->state
, &device
->adapter
->d3d_info
);
2178 state_table
= device
->state_table
;
2179 for (state
= 0; state
<= STATE_HIGHEST
; ++state
)
2181 if (state_table
[state
].representative
)
2182 device_invalidate_state(device
, state
);
2187 void wined3d_device_context_emit_reset_state(struct wined3d_device_context
*context
, bool invalidate
)
2189 struct wined3d_cs_reset_state
*op
;
2191 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2192 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
2193 op
->invalidate
= invalidate
;
2195 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2198 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
2200 const struct wined3d_cs_callback
*op
= data
;
2202 op
->callback(op
->object
);
2205 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2207 struct wined3d_cs_callback
*op
;
2209 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2210 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
2211 op
->callback
= callback
;
2212 op
->object
= object
;
2214 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2217 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2219 wined3d_cs_emit_callback(cs
, callback
, object
);
2222 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2224 wined3d_cs_emit_callback(cs
, callback
, object
);
2227 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
2229 const struct wined3d_cs_query_issue
*op
= data
;
2230 struct wined3d_query
*query
= op
->query
;
2233 poll
= query
->query_ops
->query_issue(query
, op
->flags
);
2235 if (!query
->poll_in_cs
)
2237 if (op
->flags
& WINED3DISSUE_END
)
2238 InterlockedIncrement(&query
->counter_retrieved
);
2242 if (poll
&& list_empty(&query
->poll_list_entry
))
2244 if (query
->buffer_object
)
2245 InterlockedIncrement(&query
->counter_retrieved
);
2247 list_add_tail(&cs
->query_poll_list
, &query
->poll_list_entry
);
2251 /* This can happen if occlusion queries are restarted. This discards the
2252 * old result, since polling it could result in a GL error. */
2253 if ((op
->flags
& WINED3DISSUE_BEGIN
) && !poll
&& !list_empty(&query
->poll_list_entry
))
2255 list_remove(&query
->poll_list_entry
);
2256 list_init(&query
->poll_list_entry
);
2257 InterlockedIncrement(&query
->counter_retrieved
);
2261 /* This can happen when an occlusion query is ended without being started,
2262 * in which case we don't want to poll, but still have to counter-balance
2263 * the increment of the main counter.
2265 * This can also happen if an event query is re-issued before the first
2266 * fence was reached. In this case the query is already in the list and
2267 * the poll function will check the new fence. We have to counter-balance
2268 * the discarded increment. */
2269 if (op
->flags
& WINED3DISSUE_END
)
2270 InterlockedIncrement(&query
->counter_retrieved
);
2273 static void wined3d_cs_issue_query(struct wined3d_device_context
*context
,
2274 struct wined3d_query
*query
, unsigned int flags
)
2276 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2277 struct wined3d_cs_query_issue
*op
;
2279 if (flags
& WINED3DISSUE_END
)
2280 ++query
->counter_main
;
2282 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2283 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
2287 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2288 cs
->queries_flushed
= FALSE
;
2290 if (flags
& WINED3DISSUE_BEGIN
)
2291 query
->state
= QUERY_BUILDING
;
2293 query
->state
= QUERY_SIGNALLED
;
2296 static void wined3d_cs_reference_command_list(struct wined3d_device_context
*context
, struct wined3d_command_list
*list
)
2298 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2301 if (list
->query_count
)
2303 cs
->queries_flushed
= FALSE
;
2305 for (i
= 0; i
< list
->query_count
; ++i
)
2307 if (list
->queries
[i
].flags
& WINED3DISSUE_END
)
2309 list
->queries
[i
].query
->counter_main
++;
2310 list
->queries
[i
].query
->state
= QUERY_SIGNALLED
;
2314 list
->queries
[i
].query
->state
= QUERY_BUILDING
;
2319 for (i
= 0; i
< list
->resource_count
; ++i
)
2320 wined3d_resource_reference(list
->resources
[i
]);
2322 for (i
= 0; i
< list
->command_list_count
; ++i
)
2323 wined3d_cs_reference_command_list(context
, list
->command_lists
[i
]);
2325 for (i
= 0; i
< list
->upload_count
; ++i
)
2326 invalidate_client_address(list
->uploads
[i
].resource
);
2329 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
2331 const struct wined3d_cs_preload_resource
*op
= data
;
2332 struct wined3d_resource
*resource
= op
->resource
;
2334 resource
->resource_ops
->resource_preload(resource
);
2337 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2339 struct wined3d_cs_preload_resource
*op
;
2341 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2342 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
2343 op
->resource
= resource
;
2345 wined3d_resource_reference(resource
);
2347 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2350 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
2352 const struct wined3d_cs_unload_resource
*op
= data
;
2353 struct wined3d_resource
*resource
= op
->resource
;
2355 resource
->resource_ops
->resource_unload(resource
);
2358 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2360 struct wined3d_cs_unload_resource
*op
;
2362 discard_client_address(resource
);
2364 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2365 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
2366 op
->resource
= resource
;
2368 wined3d_resource_reference(resource
);
2370 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2373 static void wined3d_device_context_upload_bo(struct wined3d_device_context
*context
,
2374 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2375 const struct upload_bo
*bo
, unsigned int row_pitch
, unsigned int slice_pitch
)
2377 struct wined3d_cs_update_sub_resource
*op
;
2379 TRACE("context %p, resource %p, sub_resource_idx %u, box %s, bo %s, flags %#x, row_pitch %u, slice_pitch %u.\n",
2380 context
, resource
, sub_resource_idx
, debug_box(box
),
2381 debug_const_bo_address(&bo
->addr
), bo
->flags
, row_pitch
, slice_pitch
);
2383 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2384 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2385 op
->resource
= resource
;
2386 op
->sub_resource_idx
= sub_resource_idx
;
2389 op
->row_pitch
= row_pitch
;
2390 op
->slice_pitch
= slice_pitch
;
2392 wined3d_device_context_reference_resource(context
, resource
);
2394 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2397 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
2399 const struct wined3d_cs_map
*op
= data
;
2400 struct wined3d_resource
*resource
= op
->resource
;
2402 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
2403 op
->sub_resource_idx
, op
->map_ptr
, op
->box
, op
->flags
);
2406 HRESULT
wined3d_device_context_emit_map(struct wined3d_device_context
*context
,
2407 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
2408 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
2410 struct wined3d_cs_map
*op
;
2413 /* Mapping resources from the worker thread isn't an issue by itself, but
2414 * increasing the map count would be visible to applications. */
2415 wined3d_not_from_cs(context
->device
->cs
);
2417 if ((flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2418 && context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, map_desc
, box
, flags
))
2420 TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n",
2421 map_desc
->data
, map_desc
->row_pitch
, map_desc
->slice_pitch
);
2425 wined3d_resource_wait_idle(resource
);
2427 /* We might end up invalidating the resource on the CS thread. */
2428 invalidate_client_address(resource
);
2430 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2431 return E_OUTOFMEMORY
;
2432 op
->opcode
= WINED3D_CS_OP_MAP
;
2433 op
->resource
= resource
;
2434 op
->sub_resource_idx
= sub_resource_idx
;
2435 op
->map_ptr
= &map_desc
->data
;
2440 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2441 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2444 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
2445 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
2449 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
2451 const struct wined3d_cs_unmap
*op
= data
;
2452 struct wined3d_resource
*resource
= op
->resource
;
2454 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
2457 HRESULT
wined3d_device_context_emit_unmap(struct wined3d_device_context
*context
,
2458 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
2460 struct wined3d_cs_unmap
*op
;
2461 struct wined3d_box box
;
2462 struct upload_bo bo
;
2465 if (context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
))
2467 unsigned int row_pitch
, slice_pitch
;
2469 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
, &row_pitch
, &slice_pitch
);
2470 if (bo
.flags
& UPLOAD_BO_UPLOAD_ON_UNMAP
)
2471 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
, row_pitch
, slice_pitch
);
2475 wined3d_not_from_cs(context
->device
->cs
);
2477 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2478 return E_OUTOFMEMORY
;
2479 op
->opcode
= WINED3D_CS_OP_UNMAP
;
2480 op
->resource
= resource
;
2481 op
->sub_resource_idx
= sub_resource_idx
;
2484 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2485 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2490 static void wined3d_cs_exec_map_bo_address(struct wined3d_cs
*cs
, const void *data
)
2492 const struct wined3d_cs_map_bo_address
*op
= data
;
2493 struct wined3d_context
*context
;
2495 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2496 wined3d_context_map_bo_address(context
, &op
->addr
, op
->size
, op
->flags
);
2497 context_release(context
);
2500 void wined3d_cs_map_bo_address(struct wined3d_cs
*cs
,
2501 struct wined3d_bo_address
*addr
, size_t size
, unsigned int flags
)
2503 struct wined3d_device_context
*context
= &cs
->c
;
2504 struct wined3d_cs_map_bo_address
*op
;
2506 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2507 op
->opcode
= WINED3D_CS_OP_MAP_BO_ADDRESS
;
2511 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2512 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2515 static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2517 const struct wined3d_cs_blt_sub_resource
*op
= data
;
2519 if (op
->dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
2521 wined3d_buffer_copy(buffer_from_resource(op
->dst_resource
), op
->dst_box
.left
,
2522 buffer_from_resource(op
->src_resource
), op
->src_box
.left
,
2523 op
->src_box
.right
- op
->src_box
.left
);
2525 else if (op
->dst_resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
2527 struct wined3d_texture
*src_texture
, *dst_texture
;
2528 unsigned int level
, update_w
, update_h
, update_d
;
2529 unsigned int row_pitch
, slice_pitch
;
2530 struct wined3d_context
*context
;
2531 struct wined3d_bo_address addr
;
2532 unsigned int location
;
2534 if (op
->flags
& ~WINED3D_BLT_RAW
)
2536 FIXME("Flags %#x not implemented for %s resources.\n",
2537 op
->flags
, debug_d3dresourcetype(op
->dst_resource
->type
));
2541 if (!(op
->flags
& WINED3D_BLT_RAW
) && op
->src_resource
->format
!= op
->dst_resource
->format
)
2543 FIXME("Format conversion not implemented for %s resources.\n",
2544 debug_d3dresourcetype(op
->dst_resource
->type
));
2548 update_w
= op
->dst_box
.right
- op
->dst_box
.left
;
2549 update_h
= op
->dst_box
.bottom
- op
->dst_box
.top
;
2550 update_d
= op
->dst_box
.back
- op
->dst_box
.front
;
2551 if (op
->src_box
.right
- op
->src_box
.left
!= update_w
2552 || op
->src_box
.bottom
- op
->src_box
.top
!= update_h
2553 || op
->src_box
.back
- op
->src_box
.front
!= update_d
)
2555 FIXME("Stretching not implemented for %s resources.\n",
2556 debug_d3dresourcetype(op
->dst_resource
->type
));
2560 dst_texture
= texture_from_resource(op
->dst_resource
);
2561 src_texture
= texture_from_resource(op
->src_resource
);
2563 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2565 location
= src_texture
->resource
.map_binding
;
2566 if (location
== WINED3D_LOCATION_SYSMEM
2567 && wined3d_texture_can_use_pbo(src_texture
, &context
->device
->adapter
->d3d_info
))
2568 location
= WINED3D_LOCATION_BUFFER
;
2570 if (!wined3d_texture_load_location(src_texture
, op
->src_sub_resource_idx
,
2573 ERR("Failed to load source sub-resource into %s.\n",
2574 wined3d_debug_location(location
));
2575 context_release(context
);
2579 level
= op
->dst_sub_resource_idx
% dst_texture
->level_count
;
2580 if (update_w
== wined3d_texture_get_level_width(dst_texture
, level
)
2581 && update_h
== wined3d_texture_get_level_height(dst_texture
, level
)
2582 && update_d
== wined3d_texture_get_level_depth(dst_texture
, level
))
2584 wined3d_texture_prepare_location(dst_texture
, op
->dst_sub_resource_idx
,
2585 context
, WINED3D_LOCATION_TEXTURE_RGB
);
2587 else if (!wined3d_texture_load_location(dst_texture
, op
->dst_sub_resource_idx
,
2588 context
, WINED3D_LOCATION_TEXTURE_RGB
))
2590 ERR("Failed to load destination sub-resource.\n");
2591 context_release(context
);
2595 wined3d_texture_get_bo_address(src_texture
, op
->src_sub_resource_idx
, &addr
, location
);
2596 wined3d_texture_get_pitch(src_texture
, op
->src_sub_resource_idx
% src_texture
->level_count
,
2597 &row_pitch
, &slice_pitch
);
2599 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&addr
),
2600 dst_texture
->resource
.format
, &op
->src_box
, row_pitch
, slice_pitch
, dst_texture
,
2601 op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
2602 op
->dst_box
.left
, op
->dst_box
.top
, op
->dst_box
.front
);
2603 wined3d_texture_validate_location(dst_texture
, op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2604 wined3d_texture_invalidate_location(dst_texture
, op
->dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2606 context_release(context
);
2610 if (FAILED(texture2d_blt(texture_from_resource(op
->dst_resource
), op
->dst_sub_resource_idx
,
2611 &op
->dst_box
, texture_from_resource(op
->src_resource
), op
->src_sub_resource_idx
,
2612 &op
->src_box
, op
->flags
, &op
->fx
, op
->filter
)))
2613 FIXME("Blit failed.\n");
2617 void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context
*context
,
2618 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
, const struct wined3d_box
*dst_box
,
2619 struct wined3d_resource
*src_resource
, unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
,
2620 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
2622 struct wined3d_cs_blt_sub_resource
*op
;
2624 /* If we are replacing the whole resource, the CS thread might discard and
2625 * rename the buffer object, in which case ours is no longer valid. */
2626 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
&& dst_box
->right
- dst_box
->left
== dst_resource
->size
)
2627 invalidate_client_address(dst_resource
);
2629 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2630 op
->opcode
= WINED3D_CS_OP_BLT_SUB_RESOURCE
;
2631 op
->dst_resource
= dst_resource
;
2632 op
->dst_sub_resource_idx
= dst_sub_resource_idx
;
2633 op
->dst_box
= *dst_box
;
2634 op
->src_resource
= src_resource
;
2635 op
->src_sub_resource_idx
= src_sub_resource_idx
;
2636 op
->src_box
= *src_box
;
2641 memset(&op
->fx
, 0, sizeof(op
->fx
));
2642 op
->filter
= filter
;
2644 wined3d_device_context_reference_resource(context
, dst_resource
);
2646 wined3d_device_context_reference_resource(context
, src_resource
);
2648 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2649 if (flags
& WINED3D_BLT_SYNCHRONOUS
)
2650 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
2653 static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2655 const struct wined3d_cs_update_sub_resource
*op
= data
;
2656 struct wined3d_resource
*resource
= op
->resource
;
2657 const struct wined3d_box
*box
= &op
->box
;
2658 struct wined3d_context
*context
;
2660 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2662 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2663 wined3d_buffer_update_sub_resource(buffer_from_resource(resource
),
2664 context
, &op
->bo
, box
->left
, box
->right
- box
->left
);
2666 wined3d_texture_update_sub_resource(texture_from_resource(resource
),
2667 op
->sub_resource_idx
, context
, &op
->bo
, box
, op
->row_pitch
, op
->slice_pitch
);
2669 context_release(context
);
2671 if (op
->bo
.flags
& UPLOAD_BO_FREE_ON_UNMAP
)
2673 if (op
->bo
.addr
.buffer_object
)
2674 FIXME("Free BO address %s.\n", debug_const_bo_address(&op
->bo
.addr
));
2676 heap_free((void *)op
->bo
.addr
.addr
);
2680 void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_context
*context
,
2681 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2682 const void *data
, unsigned int row_pitch
, unsigned int slice_pitch
)
2684 struct wined3d_cs_update_sub_resource
*op
;
2685 struct wined3d_map_desc map_desc
;
2686 struct wined3d_box dummy_box
;
2687 struct upload_bo bo
;
2689 /* If we are replacing the whole resource, the CS thread might discard and
2690 * rename the buffer object, in which case ours is no longer valid. */
2691 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& box
->right
- box
->left
== resource
->size
)
2692 invalidate_client_address(resource
);
2694 if (context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, &map_desc
, box
, WINED3D_MAP_WRITE
))
2696 wined3d_format_copy_data(resource
->format
, data
, row_pitch
, slice_pitch
, map_desc
.data
, map_desc
.row_pitch
,
2697 map_desc
.slice_pitch
, box
->right
- box
->left
, box
->bottom
- box
->top
, box
->back
- box
->front
);
2698 context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &dummy_box
, &bo
);
2699 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
,
2700 box
, &bo
, map_desc
.row_pitch
, map_desc
.slice_pitch
);
2704 wined3d_resource_wait_idle(resource
);
2706 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2707 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2708 op
->resource
= resource
;
2709 op
->sub_resource_idx
= sub_resource_idx
;
2711 op
->bo
.addr
.buffer_object
= 0;
2712 op
->bo
.addr
.addr
= data
;
2714 op
->row_pitch
= row_pitch
;
2715 op
->slice_pitch
= slice_pitch
;
2717 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2718 /* The data pointer may go away, so we need to wait until it is read.
2719 * Copying the data may be faster if it's small. */
2720 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2723 static void wined3d_cs_exec_add_dirty_texture_region(struct wined3d_cs
*cs
, const void *data
)
2725 const struct wined3d_cs_add_dirty_texture_region
*op
= data
;
2726 struct wined3d_texture
*texture
= op
->texture
;
2727 unsigned int sub_resource_idx
, i
;
2728 struct wined3d_context
*context
;
2730 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2731 sub_resource_idx
= op
->layer
* texture
->level_count
;
2732 for (i
= 0; i
< texture
->level_count
; ++i
, ++sub_resource_idx
)
2734 if (wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
))
2735 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
2737 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
2739 context_release(context
);
2742 void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs
*cs
,
2743 struct wined3d_texture
*texture
, unsigned int layer
)
2745 struct wined3d_cs_add_dirty_texture_region
*op
;
2747 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2748 op
->opcode
= WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
;
2749 op
->texture
= texture
;
2752 wined3d_resource_reference(&texture
->resource
);
2754 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2757 static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
2759 const struct wined3d_cs_clear_unordered_access_view
*op
= data
;
2760 struct wined3d_unordered_access_view
*view
= op
->view
;
2761 struct wined3d_context
*context
;
2763 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2764 cs
->c
.device
->adapter
->adapter_ops
->adapter_clear_uav(context
, view
, &op
->clear_value
, op
->fp
);
2765 context_release(context
);
2768 void wined3d_device_context_emit_clear_uav(struct wined3d_device_context
*context
,
2769 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
, bool fp
)
2771 struct wined3d_cs_clear_unordered_access_view
*op
;
2773 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2774 op
->opcode
= WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
;
2776 op
->clear_value
= *clear_value
;
2779 wined3d_device_context_reference_resource(context
, view
->resource
);
2781 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2784 static void wined3d_cs_exec_copy_uav_counter(struct wined3d_cs
*cs
, const void *data
)
2786 const struct wined3d_cs_copy_uav_counter
*op
= data
;
2787 struct wined3d_unordered_access_view
*view
= op
->view
;
2788 struct wined3d_context
*context
;
2790 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2791 wined3d_unordered_access_view_copy_counter(view
, op
->buffer
, op
->offset
, context
);
2792 context_release(context
);
2795 void wined3d_device_context_emit_copy_uav_counter(struct wined3d_device_context
*context
,
2796 struct wined3d_buffer
*dst_buffer
, unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
2798 struct wined3d_cs_copy_uav_counter
*op
;
2800 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2801 op
->opcode
= WINED3D_CS_OP_COPY_UAV_COUNTER
;
2802 op
->buffer
= dst_buffer
;
2803 op
->offset
= offset
;
2806 wined3d_device_context_reference_resource(context
, &dst_buffer
->resource
);
2808 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2811 static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs
*cs
, const void *data
)
2813 const struct wined3d_cs_generate_mipmaps
*op
= data
;
2814 struct wined3d_shader_resource_view
*view
= op
->view
;
2815 struct wined3d_context
*context
;
2817 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2818 cs
->c
.device
->adapter
->adapter_ops
->adapter_generate_mipmap(context
, view
);
2819 context_release(context
);
2822 void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context
*context
,
2823 struct wined3d_shader_resource_view
*view
)
2825 struct wined3d_cs_generate_mipmaps
*op
;
2827 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2828 op
->opcode
= WINED3D_CS_OP_GENERATE_MIPMAPS
;
2831 wined3d_device_context_reference_resource(context
, view
->resource
);
2833 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2836 static void wined3d_cs_emit_stop(struct wined3d_cs
*cs
)
2838 struct wined3d_cs_stop
*op
;
2840 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2841 op
->opcode
= WINED3D_CS_OP_STOP
;
2843 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2844 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2847 static void wined3d_cs_reference_resource(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
)
2849 wined3d_resource_reference(resource
);
2852 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
);
2854 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
2856 /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop
,
2857 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
2858 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
2859 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
2860 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
2861 /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush
,
2862 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
2863 /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports
,
2864 /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects
,
2865 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEWS */ wined3d_cs_exec_set_rendertarget_views
,
2866 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
2867 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
2868 /* WINED3D_CS_OP_SET_STREAM_SOURCES */ wined3d_cs_exec_set_stream_sources
,
2869 /* WINED3D_CS_OP_SET_STREAM_OUTPUTS */ wined3d_cs_exec_set_stream_outputs
,
2870 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
2871 /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers
,
2872 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
2873 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS */ wined3d_cs_exec_set_shader_resource_views
,
2874 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS */ wined3d_cs_exec_set_unordered_access_views
,
2875 /* WINED3D_CS_OP_SET_SAMPLERS */ wined3d_cs_exec_set_samplers
,
2876 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
2877 /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state
,
2878 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE */ wined3d_cs_exec_set_depth_stencil_state
,
2879 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
2880 /* WINED3D_CS_OP_SET_DEPTH_BOUNDS */ wined3d_cs_exec_set_depth_bounds
,
2881 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
2882 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
2883 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
2884 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
2885 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
2886 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
2887 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
2888 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
2889 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
2890 /* WINED3D_CS_OP_SET_FEATURE_LEVEL */ wined3d_cs_exec_set_feature_level
,
2891 /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants
,
2892 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
2893 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
2894 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
2895 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
2896 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
2897 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
2898 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
2899 /* WINED3D_CS_OP_MAP_BO_ADDRESS */ wined3d_cs_exec_map_bo_address
,
2900 /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource
,
2901 /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource
,
2902 /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region
,
2903 /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view
,
2904 /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter
,
2905 /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps
,
2906 /* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list
,
2909 void wined3d_device_context_emit_execute_command_list(struct wined3d_device_context
*context
,
2910 struct wined3d_command_list
*list
, bool restore_state
)
2912 struct wined3d_cs_execute_command_list
*op
;
2914 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2915 op
->opcode
= WINED3D_CS_OP_EXECUTE_COMMAND_LIST
;
2918 context
->ops
->reference_command_list(context
, list
);
2920 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2923 wined3d_device_context_set_state(context
, context
->state
);
2925 wined3d_device_context_reset_state(context
);
2928 static void *wined3d_cs_st_require_space(struct wined3d_device_context
*context
,
2929 size_t size
, enum wined3d_cs_queue_id queue_id
)
2931 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2933 if (size
> (cs
->data_size
- cs
->end
))
2938 new_size
= max(size
, cs
->data_size
* 2);
2940 new_data
= heap_realloc(cs
->data
, new_size
);
2942 new_data
= heap_alloc(new_size
);
2946 cs
->data_size
= new_size
;
2947 cs
->start
= cs
->end
= 0;
2948 cs
->data
= new_data
;
2953 return (BYTE
*)cs
->data
+ cs
->start
;
2956 static void wined3d_cs_st_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2958 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2959 enum wined3d_cs_op opcode
;
2965 cs
->start
= cs
->end
;
2967 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
2968 if (opcode
>= WINED3D_CS_OP_STOP
)
2969 ERR("Invalid opcode %#x.\n", opcode
);
2971 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
2973 if (cs
->data
== data
)
2974 cs
->start
= cs
->end
= start
;
2979 static void wined3d_cs_st_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2983 static bool wined3d_cs_map_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
2984 unsigned int sub_resource_idx
, struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
2986 struct wined3d_client_resource
*client
= &resource
->client
;
2987 const struct wined3d_format
*format
= resource
->format
;
2990 if (flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2992 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
2993 struct wined3d_device
*device
= context
->device
;
2994 struct wined3d_bo_address addr
;
2995 struct wined3d_bo
*bo
;
2998 /* We can't use persistent maps if we might need to do vertex attribute
2999 * conversion; that will cause the CS thread to invalidate the BO. */
3000 if (!d3d_info
->xyzrhw
|| !d3d_info
->vertex_bgra
|| !d3d_info
->ffp_generic_attributes
)
3002 TRACE("Not returning a persistent buffer because we might need to do vertex attribute conversion.\n");
3006 if (resource
->pin_sysmem
)
3008 TRACE("Not allocating an upload buffer because system memory is pinned for this resource.\n");
3012 if ((flags
& WINED3D_MAP_NOOVERWRITE
) && client
->addr
.buffer_object
== CLIENT_BO_DISCARDED
)
3013 flags
= (flags
& ~WINED3D_MAP_NOOVERWRITE
) | WINED3D_MAP_DISCARD
;
3015 if (flags
& WINED3D_MAP_DISCARD
)
3017 if (!device
->adapter
->adapter_ops
->adapter_alloc_bo(device
, resource
, sub_resource_idx
, &addr
))
3020 /* Limit NOOVERWRITE maps to buffers for now; there are too many
3021 * ways that a texture can be invalidated to even count. */
3022 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
3023 client
->addr
= addr
;
3027 addr
= client
->addr
;
3031 if ((bo
= addr
.buffer_object
))
3033 wined3d_device_bo_map_lock(device
);
3034 if ((map_ptr
= bo
->map_ptr
))
3035 ++bo
->client_map_count
;
3036 wined3d_device_bo_map_unlock(device
);
3040 /* adapter_alloc_bo() should have given us a mapped BO if we are
3042 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3043 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the BO is not mapped.\n");
3047 map_ptr
+= (uintptr_t)addr
.addr
;
3051 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3052 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the sub-resource has no valid address.\n");
3056 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
3057 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3059 client
->mapped_upload
.addr
= *wined3d_const_bo_address(&addr
);
3060 client
->mapped_upload
.flags
= 0;
3063 map_ptr
+= bo
->memory_offset
;
3064 /* If we are not mapping all buffers persistently, use
3065 * UPDATE_SUB_RESOURCE as a means of telling the CS thread to try
3066 * to unmap the resource, so that we can free VA space. */
3067 if (!bo
->coherent
|| !wined3d_map_persistent())
3068 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
;
3070 map_desc
->data
= resource_offset_map_pointer(resource
, sub_resource_idx
, map_ptr
, box
);
3072 if (flags
& WINED3D_MAP_DISCARD
)
3073 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_RENAME_ON_UNMAP
;
3075 client
->mapped_box
= *box
;
3077 TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client
->mapped_upload
.addr
),
3078 client
->mapped_upload
.flags
);
3082 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
3083 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3085 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
3086 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
3087 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
3089 if (!(map_desc
->data
= heap_alloc(size
)))
3091 WARN_(d3d_perf
)("Failed to allocate a heap memory buffer.\n");
3094 client
->mapped_upload
.addr
.buffer_object
= 0;
3095 client
->mapped_upload
.addr
.addr
= map_desc
->data
;
3096 client
->mapped_upload
.flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_FREE_ON_UNMAP
;
3097 client
->mapped_box
= *box
;
3101 static bool wined3d_bo_address_is_null(struct wined3d_const_bo_address
*addr
)
3103 return !addr
->buffer_object
&& !addr
->addr
;
3106 static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
3107 unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*upload_bo
)
3109 struct wined3d_client_resource
*client
= &resource
->client
;
3110 struct wined3d_device
*device
= context
->device
;
3111 struct wined3d_bo
*bo
;
3113 if (wined3d_bo_address_is_null(&client
->mapped_upload
.addr
))
3116 if ((bo
= client
->mapped_upload
.addr
.buffer_object
))
3118 wined3d_device_bo_map_lock(device
);
3119 --bo
->client_map_count
;
3120 wined3d_device_bo_map_unlock(device
);
3123 *upload_bo
= client
->mapped_upload
;
3124 *box
= client
->mapped_box
;
3125 memset(&client
->mapped_upload
, 0, sizeof(client
->mapped_upload
));
3126 memset(&client
->mapped_box
, 0, sizeof(client
->mapped_box
));
3130 static const struct wined3d_device_context_ops wined3d_cs_st_ops
=
3132 wined3d_cs_st_require_space
,
3133 wined3d_cs_st_submit
,
3134 wined3d_cs_st_finish
,
3135 wined3d_cs_st_push_constants
,
3136 wined3d_cs_map_upload_bo
,
3137 wined3d_cs_unmap_upload_bo
,
3138 wined3d_cs_issue_query
,
3140 wined3d_cs_reference_resource
,
3141 wined3d_cs_reference_command_list
,
3144 static BOOL
wined3d_cs_queue_is_empty(const struct wined3d_cs
*cs
, const struct wined3d_cs_queue
*queue
)
3146 wined3d_from_cs(cs
);
3147 return *(volatile ULONG
*)&queue
->head
== queue
->tail
;
3150 static void wined3d_cs_queue_submit(struct wined3d_cs_queue
*queue
, struct wined3d_cs
*cs
)
3152 struct wined3d_cs_packet
*packet
;
3155 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
& WINED3D_CS_QUEUE_MASK
];
3156 TRACE("Queuing op %s at %p.\n", debug_cs_op(*(const enum wined3d_cs_op
*)packet
->data
), packet
);
3157 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
3158 InterlockedExchange((LONG
*)&queue
->head
, queue
->head
+ packet_size
);
3160 if (InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3161 SetEvent(cs
->event
);
3164 static void wined3d_cs_mt_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3166 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3168 if (cs
->thread_id
== GetCurrentThreadId())
3169 return wined3d_cs_st_submit(context
, queue_id
);
3171 wined3d_cs_queue_submit(&cs
->queue
[queue_id
], cs
);
3174 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue
, size_t size
, struct wined3d_cs
*cs
)
3176 size_t queue_size
= ARRAY_SIZE(queue
->data
);
3177 size_t header_size
, packet_size
, remaining
;
3178 struct wined3d_cs_packet
*packet
;
3179 ULONG head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3181 header_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[0]);
3182 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[size
]);
3183 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
3184 size
= packet_size
- header_size
;
3185 if (packet_size
>= WINED3D_CS_QUEUE_SIZE
)
3187 ERR("Packet size %Iu >= queue size %u.\n", packet_size
, WINED3D_CS_QUEUE_SIZE
);
3191 remaining
= queue_size
- head
;
3192 if (remaining
< packet_size
)
3194 size_t nop_size
= remaining
- header_size
;
3195 struct wined3d_cs_nop
*nop
;
3197 TRACE("Inserting a nop for %Iu + %Iu bytes.\n", header_size
, nop_size
);
3199 nop
= wined3d_cs_queue_require_space(queue
, nop_size
, cs
);
3201 nop
->opcode
= WINED3D_CS_OP_NOP
;
3203 wined3d_cs_queue_submit(queue
, cs
);
3204 head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3210 ULONG tail
= (*(volatile ULONG
*)&queue
->tail
) & WINED3D_CS_QUEUE_MASK
;
3216 new_pos
= (head
+ packet_size
) & WINED3D_CS_QUEUE_MASK
;
3217 /* Head ahead of tail. We checked the remaining size above, so we only
3218 * need to make sure we don't make head equal to tail. */
3219 if (head
> tail
&& (new_pos
!= tail
))
3221 /* Tail ahead of head. Make sure the new head is before the tail as
3222 * well. Note that new_pos is 0 when it's at the end of the queue. */
3223 if (new_pos
< tail
&& new_pos
)
3226 TRACE("Waiting for free space. Head %lu, tail %lu, packet size %Iu.\n",
3227 head
, tail
, packet_size
);
3230 packet
= (struct wined3d_cs_packet
*)&queue
->data
[head
];
3231 packet
->size
= size
;
3232 return packet
->data
;
3235 static void *wined3d_cs_mt_require_space(struct wined3d_device_context
*context
,
3236 size_t size
, enum wined3d_cs_queue_id queue_id
)
3238 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3240 if (cs
->thread_id
== GetCurrentThreadId())
3241 return wined3d_cs_st_require_space(context
, size
, queue_id
);
3243 return wined3d_cs_queue_require_space(&cs
->queue
[queue_id
], size
, cs
);
3246 static void wined3d_cs_mt_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3248 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3250 if (cs
->thread_id
== GetCurrentThreadId())
3251 return wined3d_cs_st_finish(context
, queue_id
);
3253 while (cs
->queue
[queue_id
].head
!= *(volatile ULONG
*)&cs
->queue
[queue_id
].tail
)
3257 static const struct wined3d_device_context_ops wined3d_cs_mt_ops
=
3259 wined3d_cs_mt_require_space
,
3260 wined3d_cs_mt_submit
,
3261 wined3d_cs_mt_finish
,
3262 wined3d_cs_mt_push_constants
,
3263 wined3d_cs_map_upload_bo
,
3264 wined3d_cs_unmap_upload_bo
,
3265 wined3d_cs_issue_query
,
3267 wined3d_cs_reference_resource
,
3268 wined3d_cs_reference_command_list
,
3271 static void poll_queries(struct wined3d_cs
*cs
)
3273 struct wined3d_query
*query
, *cursor
;
3275 LIST_FOR_EACH_ENTRY_SAFE(query
, cursor
, &cs
->query_poll_list
, struct wined3d_query
, poll_list_entry
)
3277 if (!query
->query_ops
->query_poll(query
, 0))
3280 list_remove(&query
->poll_list_entry
);
3281 list_init(&query
->poll_list_entry
);
3282 InterlockedIncrement(&query
->counter_retrieved
);
3286 static void wined3d_cs_wait_event(struct wined3d_cs
*cs
)
3288 InterlockedExchange(&cs
->waiting_for_event
, TRUE
);
3290 /* The main thread might have enqueued a command and blocked on it after
3291 * the CS thread decided to enter wined3d_cs_wait_event(), but before
3292 * "waiting_for_event" was set.
3294 * Likewise, we can race with the main thread when resetting
3295 * "waiting_for_event", in which case we would need to call
3296 * WaitForSingleObject() because the main thread called SetEvent(). */
3297 if (!(wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
])
3298 && wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_MAP
]))
3299 && InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3302 WaitForSingleObject(cs
->event
, INFINITE
);
3305 static void wined3d_cs_command_lock(const struct wined3d_cs
*cs
)
3307 if (cs
->serialize_commands
)
3308 EnterCriticalSection(&wined3d_command_cs
);
3311 static void wined3d_cs_command_unlock(const struct wined3d_cs
*cs
)
3313 if (cs
->serialize_commands
)
3314 LeaveCriticalSection(&wined3d_command_cs
);
3317 static inline bool wined3d_cs_execute_next(struct wined3d_cs
*cs
, struct wined3d_cs_queue
*queue
)
3319 struct wined3d_cs_packet
*packet
;
3320 enum wined3d_cs_op opcode
;
3324 packet
= wined3d_next_cs_packet(queue
->data
, &tail
, WINED3D_CS_QUEUE_MASK
);
3328 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3330 TRACE("Executing %s at %p.\n", debug_cs_op(opcode
), packet
);
3331 if (opcode
>= WINED3D_CS_OP_STOP
)
3333 if (opcode
> WINED3D_CS_OP_STOP
)
3334 ERR("Invalid opcode %#x.\n", opcode
);
3338 wined3d_cs_command_lock(cs
);
3339 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3340 wined3d_cs_command_unlock(cs
);
3341 TRACE("%s at %p executed.\n", debug_cs_op(opcode
), packet
);
3344 InterlockedExchange((LONG
*)&queue
->tail
, tail
);
3348 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
)
3350 const struct wined3d_cs_execute_command_list
*op
= data
;
3351 SIZE_T start
= 0, end
= op
->list
->data_size
;
3352 const BYTE
*cs_data
= op
->list
->data
;
3353 struct wined3d_cs_queue
*queue
;
3355 TRACE("Executing command list %p.\n", op
->list
);
3357 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3360 const struct wined3d_cs_packet
*packet
;
3361 enum wined3d_cs_op opcode
;
3363 while (!wined3d_cs_queue_is_empty(cs
, queue
))
3364 wined3d_cs_execute_next(cs
, queue
);
3366 packet
= wined3d_next_cs_packet(cs_data
, &start
, WINED3D_CS_QUEUE_MASK
);
3367 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3369 if (opcode
>= WINED3D_CS_OP_STOP
)
3370 ERR("Invalid opcode %#x.\n", opcode
);
3372 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3373 TRACE("%s executed.\n", debug_cs_op(opcode
));
3377 static DWORD WINAPI
wined3d_cs_run(void *ctx
)
3379 struct wined3d_cs_queue
*queue
;
3380 unsigned int spin_count
= 0;
3381 struct wined3d_cs
*cs
= ctx
;
3382 HMODULE wined3d_module
;
3383 unsigned int poll
= 0;
3386 TRACE("Started.\n");
3387 SetThreadDescription(GetCurrentThread(), L
"wined3d_cs");
3389 /* Copy the module handle to a local variable to avoid racing with the
3390 * thread freeing "cs" before the FreeLibraryAndExitThread() call. */
3391 wined3d_module
= cs
->wined3d_module
;
3393 list_init(&cs
->query_poll_list
);
3394 cs
->thread_id
= GetCurrentThreadId();
3397 if (++poll
== WINED3D_CS_QUERY_POLL_INTERVAL
)
3399 wined3d_cs_command_lock(cs
);
3401 wined3d_cs_command_unlock(cs
);
3405 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3406 if (wined3d_cs_queue_is_empty(cs
, queue
))
3408 queue
= &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
];
3409 if (wined3d_cs_queue_is_empty(cs
, queue
))
3411 if (++spin_count
>= WINED3D_CS_SPIN_COUNT
&& list_empty(&cs
->query_poll_list
))
3412 wined3d_cs_wait_event(cs
);
3418 run
= wined3d_cs_execute_next(cs
, queue
);
3421 cs
->queue
[WINED3D_CS_QUEUE_MAP
].tail
= cs
->queue
[WINED3D_CS_QUEUE_MAP
].head
;
3422 cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].tail
= cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].head
;
3423 TRACE("Stopped.\n");
3424 FreeLibraryAndExitThread(wined3d_module
, 0);
3427 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
,
3428 const enum wined3d_feature_level
*levels
, unsigned int level_count
)
3430 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3431 struct wined3d_cs
*cs
;
3433 if (!(cs
= heap_alloc_zero(sizeof(*cs
))))
3436 if (FAILED(wined3d_state_create(device
, levels
, level_count
, &cs
->c
.state
)))
3442 cs
->c
.ops
= &wined3d_cs_st_ops
;
3443 cs
->c
.device
= device
;
3444 cs
->serialize_commands
= TRACE_ON(d3d_sync
) || wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_SERIALIZE
;
3446 if (cs
->serialize_commands
)
3447 ERR_(d3d_sync
)("Forcing serialization of all command streams.\n");
3449 state_init(&cs
->state
, d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
, cs
->c
.state
->feature_level
);
3451 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
3452 if (!(cs
->data
= heap_alloc(cs
->data_size
)))
3455 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
)
3457 if (!d3d_info
->fences
)
3459 WARN("Disabling CSMT, adapter doesn't support fences.\n");
3460 wined3d_settings
.cs_multithreaded
&= ~WINED3D_CSMT_ENABLE
;
3464 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
3465 && !RtlIsCriticalSectionLockedByThread(NtCurrentTeb()->Peb
->LoaderLock
))
3467 cs
->c
.ops
= &wined3d_cs_mt_ops
;
3469 if (!(cs
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
3471 ERR("Failed to create command stream event.\n");
3472 heap_free(cs
->data
);
3476 if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
3477 (const WCHAR
*)wined3d_cs_run
, &cs
->wined3d_module
)))
3479 ERR("Failed to get wined3d module handle.\n");
3480 CloseHandle(cs
->event
);
3481 heap_free(cs
->data
);
3485 if (!(cs
->thread
= CreateThread(NULL
, 0, wined3d_cs_run
, cs
, 0, NULL
)))
3487 ERR("Failed to create wined3d command stream thread.\n");
3488 FreeLibrary(cs
->wined3d_module
);
3489 CloseHandle(cs
->event
);
3490 heap_free(cs
->data
);
3495 TRACE("Created command stream %p.\n", cs
);
3499 wined3d_state_destroy(cs
->c
.state
);
3500 state_cleanup(&cs
->state
);
3505 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
3509 wined3d_cs_emit_stop(cs
);
3510 CloseHandle(cs
->thread
);
3511 if (!CloseHandle(cs
->event
))
3512 ERR("Closing event failed.\n");
3515 wined3d_state_destroy(cs
->c
.state
);
3516 state_cleanup(&cs
->state
);
3517 heap_free(cs
->data
);
3521 static void wined3d_cs_packet_decref_objects(const struct wined3d_cs_packet
*packet
)
3523 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3528 case WINED3D_CS_OP_SET_SAMPLERS
:
3530 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3532 for (i
= 0; i
< op
->count
; ++i
)
3534 if (op
->samplers
[i
])
3535 wined3d_sampler_decref(op
->samplers
[i
]);
3540 case WINED3D_CS_OP_SET_SHADER
:
3542 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3545 wined3d_shader_decref(op
->shader
);
3549 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3551 struct wined3d_cs_set_depth_stencil_state
*op
;
3553 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3555 wined3d_depth_stencil_state_decref(op
->state
);
3559 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3561 struct wined3d_cs_set_rasterizer_state
*op
;
3563 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3565 wined3d_rasterizer_state_decref(op
->state
);
3569 case WINED3D_CS_OP_SET_BLEND_STATE
:
3571 struct wined3d_cs_set_blend_state
*op
;
3573 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3575 wined3d_blend_state_decref(op
->state
);
3579 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3581 struct wined3d_cs_set_rendertarget_views
*op
;
3583 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3584 for (i
= 0; i
< op
->count
; ++i
)
3587 wined3d_rendertarget_view_decref(op
->views
[i
]);
3592 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3594 struct wined3d_cs_set_shader_resource_views
*op
;
3596 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3597 for (i
= 0; i
< op
->count
; ++i
)
3600 wined3d_shader_resource_view_decref(op
->views
[i
]);
3605 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3607 struct wined3d_cs_set_unordered_access_views
*op
;
3609 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3610 for (i
= 0; i
< op
->count
; ++i
)
3612 if (op
->uavs
[i
].view
)
3613 wined3d_unordered_access_view_decref(op
->uavs
[i
].view
);
3618 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3620 struct wined3d_cs_set_depth_stencil_view
*op
;
3622 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3624 wined3d_rendertarget_view_decref(op
->view
);
3628 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3630 struct wined3d_cs_set_constant_buffers
*op
;
3632 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3633 for (i
= 0; i
< op
->count
; ++i
)
3635 if (op
->buffers
[i
].buffer
)
3636 wined3d_buffer_decref(op
->buffers
[i
].buffer
);
3641 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3643 struct wined3d_cs_clear_unordered_access_view
*op
;
3645 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3646 wined3d_unordered_access_view_decref(op
->view
);
3650 case WINED3D_CS_OP_CLEAR
:
3652 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3654 for (i
= 0; i
< op
->rt_count
; ++i
)
3656 if (op
->fb
.render_targets
[i
])
3657 wined3d_rendertarget_view_decref(op
->fb
.render_targets
[i
]);
3659 if (op
->fb
.depth_stencil
)
3660 wined3d_rendertarget_view_decref(op
->fb
.depth_stencil
);
3664 case WINED3D_CS_OP_DISPATCH
:
3666 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3668 if (op
->parameters
.indirect
)
3669 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3673 case WINED3D_CS_OP_DRAW
:
3675 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3677 if (op
->parameters
.indirect
)
3678 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3682 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3684 struct wined3d_cs_set_index_buffer
*op
;
3686 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3688 wined3d_buffer_decref(op
->buffer
);
3692 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3694 struct wined3d_cs_set_stream_outputs
*op
;
3696 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3697 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3699 if (op
->outputs
[i
].buffer
)
3700 wined3d_buffer_decref(op
->outputs
[i
].buffer
);
3705 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3707 struct wined3d_cs_set_stream_sources
*op
;
3709 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3710 for (i
= 0; i
< op
->count
; ++i
)
3712 if (op
->streams
[i
].buffer
)
3713 wined3d_buffer_decref(op
->streams
[i
].buffer
);
3718 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3720 struct wined3d_cs_update_sub_resource
*op
;
3722 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3723 wined3d_resource_decref(op
->resource
);
3727 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3729 struct wined3d_cs_blt_sub_resource
*op
;
3731 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
3732 if (op
->src_resource
)
3733 wined3d_resource_decref(op
->src_resource
);
3734 wined3d_resource_decref(op
->dst_resource
);
3738 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
3740 struct wined3d_cs_copy_uav_counter
*op
;
3742 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
3743 wined3d_buffer_decref(op
->buffer
);
3744 wined3d_unordered_access_view_decref(op
->view
);
3748 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
3750 struct wined3d_cs_generate_mipmaps
*op
;
3752 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
3753 wined3d_shader_resource_view_decref(op
->view
);
3762 static void wined3d_cs_packet_incref_objects(struct wined3d_cs_packet
*packet
)
3764 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3769 case WINED3D_CS_OP_SET_SAMPLERS
:
3771 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3773 for (i
= 0; i
< op
->count
; ++i
)
3775 if (op
->samplers
[i
])
3776 wined3d_sampler_incref(op
->samplers
[i
]);
3781 case WINED3D_CS_OP_SET_SHADER
:
3783 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3786 wined3d_shader_incref(op
->shader
);
3790 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3792 struct wined3d_cs_set_depth_stencil_state
*op
;
3794 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3796 wined3d_depth_stencil_state_incref(op
->state
);
3800 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3802 struct wined3d_cs_set_rasterizer_state
*op
;
3804 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3806 wined3d_rasterizer_state_incref(op
->state
);
3810 case WINED3D_CS_OP_SET_BLEND_STATE
:
3812 struct wined3d_cs_set_blend_state
*op
;
3814 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3816 wined3d_blend_state_incref(op
->state
);
3820 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3822 struct wined3d_cs_set_rendertarget_views
*op
;
3824 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3825 for (i
= 0; i
< op
->count
; ++i
)
3828 wined3d_rendertarget_view_incref(op
->views
[i
]);
3833 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3835 struct wined3d_cs_set_shader_resource_views
*op
;
3837 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3838 for (i
= 0; i
< op
->count
; ++i
)
3841 wined3d_shader_resource_view_incref(op
->views
[i
]);
3846 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3848 struct wined3d_cs_set_unordered_access_views
*op
;
3850 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3851 for (i
= 0; i
< op
->count
; ++i
)
3853 if (op
->uavs
[i
].view
)
3854 wined3d_unordered_access_view_incref(op
->uavs
[i
].view
);
3859 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3861 struct wined3d_cs_set_depth_stencil_view
*op
;
3863 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3865 wined3d_rendertarget_view_incref(op
->view
);
3869 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3871 struct wined3d_cs_set_constant_buffers
*op
;
3873 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3874 for (i
= 0; i
< op
->count
; ++i
)
3876 if (op
->buffers
[i
].buffer
)
3877 wined3d_buffer_incref(op
->buffers
[i
].buffer
);
3882 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3884 struct wined3d_cs_clear_unordered_access_view
*op
;
3886 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3887 wined3d_unordered_access_view_incref(op
->view
);
3891 case WINED3D_CS_OP_CLEAR
:
3893 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3895 for (i
= 0; i
< op
->rt_count
; ++i
)
3897 if (op
->fb
.render_targets
[i
])
3898 wined3d_rendertarget_view_incref(op
->fb
.render_targets
[i
]);
3900 if (op
->fb
.depth_stencil
)
3901 wined3d_rendertarget_view_incref(op
->fb
.depth_stencil
);
3905 case WINED3D_CS_OP_DISPATCH
:
3907 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3909 if (op
->parameters
.indirect
)
3910 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3914 case WINED3D_CS_OP_DRAW
:
3916 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3918 if (op
->parameters
.indirect
)
3919 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3923 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3925 struct wined3d_cs_set_index_buffer
*op
;
3927 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3929 wined3d_buffer_incref(op
->buffer
);
3933 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3935 struct wined3d_cs_set_stream_outputs
*op
;
3937 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3938 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3940 if (op
->outputs
[i
].buffer
)
3941 wined3d_buffer_incref(op
->outputs
[i
].buffer
);
3946 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3948 struct wined3d_cs_set_stream_sources
*op
;
3950 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3951 for (i
= 0; i
< op
->count
; ++i
)
3953 if (op
->streams
[i
].buffer
)
3954 wined3d_buffer_incref(op
->streams
[i
].buffer
);
3959 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3961 struct wined3d_cs_update_sub_resource
*op
;
3963 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3964 wined3d_resource_incref(op
->resource
);
3968 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3970 struct wined3d_cs_blt_sub_resource
*op
;
3972 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
3973 if (op
->src_resource
)
3974 wined3d_resource_incref(op
->src_resource
);
3975 wined3d_resource_incref(op
->dst_resource
);
3979 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
3981 struct wined3d_cs_copy_uav_counter
*op
;
3983 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
3984 wined3d_buffer_incref(op
->buffer
);
3985 wined3d_unordered_access_view_incref(op
->view
);
3989 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
3991 struct wined3d_cs_generate_mipmaps
*op
;
3993 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
3994 wined3d_shader_resource_view_incref(op
->view
);
4003 struct wined3d_deferred_context
4005 struct wined3d_device_context c
;
4007 SIZE_T data_size
, data_capacity
;
4010 SIZE_T resource_count
, resources_capacity
;
4011 struct wined3d_resource
**resources
;
4013 SIZE_T upload_count
, uploads_capacity
;
4014 struct wined3d_deferred_upload
*uploads
;
4017 LONG
*upload_heap_refcount
;
4019 /* List of command lists queued for execution on this context. A command
4020 * list can be the only thing holding a pointer to another command list, so
4021 * we need to hold a reference here and in wined3d_command_list as well. */
4022 SIZE_T command_list_count
, command_lists_capacity
;
4023 struct wined3d_command_list
**command_lists
;
4025 SIZE_T query_count
, queries_capacity
;
4026 struct wined3d_deferred_query_issue
*queries
;
4029 static struct wined3d_deferred_context
*wined3d_deferred_context_from_context(struct wined3d_device_context
*context
)
4031 return CONTAINING_RECORD(context
, struct wined3d_deferred_context
, c
);
4034 static void *wined3d_deferred_context_require_space(struct wined3d_device_context
*context
,
4035 size_t size
, enum wined3d_cs_queue_id queue_id
)
4037 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4038 struct wined3d_cs_packet
*packet
;
4039 size_t header_size
, packet_size
;
4041 if (queue_id
!= WINED3D_CS_QUEUE_DEFAULT
)
4044 header_size
= offsetof(struct wined3d_cs_packet
, data
[0]);
4045 packet_size
= offsetof(struct wined3d_cs_packet
, data
[size
]);
4046 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
4048 if (!wined3d_array_reserve(&deferred
->data
, &deferred
->data_capacity
, deferred
->data_size
+ packet_size
, 1))
4051 packet
= (struct wined3d_cs_packet
*)((BYTE
*)deferred
->data
+ deferred
->data_size
);
4052 TRACE("size was %Iu, adding %Iu\n", (size_t)deferred
->data_size
, packet_size
);
4053 packet
->size
= packet_size
- header_size
;
4054 return &packet
->data
;
4057 static void wined3d_deferred_context_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4059 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4060 struct wined3d_cs_packet
*packet
;
4062 assert(queue_id
== WINED3D_CS_QUEUE_DEFAULT
);
4063 packet
= wined3d_next_cs_packet(deferred
->data
, &deferred
->data_size
, ~(SIZE_T
)0);
4064 wined3d_cs_packet_incref_objects(packet
);
4067 static void wined3d_deferred_context_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4069 /* This should not happen; we cannot meaningfully finish a deferred context. */
4070 ERR("Ignoring finish() on a deferred context.\n");
4073 static void wined3d_deferred_context_push_constants(struct wined3d_device_context
*context
,
4074 enum wined3d_push_constants p
, unsigned int start_idx
, unsigned int count
, const void *constants
)
4076 FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context
, p
, start_idx
, count
, constants
);
4079 static struct wined3d_deferred_upload
*deferred_context_get_upload(struct wined3d_deferred_context
*deferred
,
4080 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
4082 SIZE_T i
= deferred
->upload_count
;
4086 struct wined3d_deferred_upload
*upload
= &deferred
->uploads
[i
];
4088 if (upload
->resource
== resource
&& upload
->sub_resource_idx
== sub_resource_idx
)
4095 static bool wined3d_deferred_context_map_upload_bo(struct wined3d_device_context
*context
,
4096 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
4097 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
4099 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4100 const struct wined3d_format
*format
= resource
->format
;
4101 struct wined3d_deferred_upload
*upload
;
4105 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
4106 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
4108 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
4109 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
4110 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
4112 if (!(flags
& WINED3D_MAP_WRITE
))
4114 WARN("Flags %#x are not valid on a deferred context.\n", flags
);
4118 if (flags
& ~(WINED3D_MAP_WRITE
| WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
4120 FIXME("Unhandled flags %#x.\n", flags
);
4124 if (flags
& WINED3D_MAP_NOOVERWRITE
)
4126 if (!(upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4129 upload
->upload_flags
= 0;
4130 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4134 if (!wined3d_array_reserve((void **)&deferred
->uploads
, &deferred
->uploads_capacity
,
4135 deferred
->upload_count
+ 1, sizeof(*deferred
->uploads
)))
4138 if (!deferred
->upload_heap
)
4140 if (!(deferred
->upload_heap
= HeapCreate(0, 0, 0)))
4142 ERR("Failed to create upload heap.\n");
4146 if (!(deferred
->upload_heap_refcount
= heap_alloc(sizeof(*deferred
->upload_heap_refcount
))))
4148 HeapDestroy(deferred
->upload_heap
);
4149 deferred
->upload_heap
= 0;
4153 *deferred
->upload_heap_refcount
= 1;
4156 if (!(sysmem
= HeapAlloc(deferred
->upload_heap
, 0, size
+ RESOURCE_ALIGNMENT
- 1)))
4159 upload
= &deferred
->uploads
[deferred
->upload_count
++];
4160 upload
->upload_flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
;
4161 upload
->resource
= resource
;
4162 wined3d_resource_incref(resource
);
4163 upload
->sub_resource_idx
= sub_resource_idx
;
4164 upload
->sysmem
= sysmem
;
4167 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4171 static bool wined3d_deferred_context_unmap_upload_bo(struct wined3d_device_context
*context
,
4172 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*bo
)
4174 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4175 const struct wined3d_deferred_upload
*upload
;
4177 if ((upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4180 bo
->addr
.buffer_object
= 0;
4181 bo
->addr
.addr
= (uint8_t *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4182 bo
->flags
= upload
->upload_flags
;
4189 static void wined3d_deferred_context_issue_query(struct wined3d_device_context
*context
,
4190 struct wined3d_query
*query
, unsigned int flags
)
4192 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4193 struct wined3d_cs_query_issue
*op
;
4195 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
4196 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
4200 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
4202 if (!wined3d_array_reserve((void **)&deferred
->queries
, &deferred
->queries_capacity
,
4203 deferred
->query_count
+ 1, sizeof(*deferred
->queries
)))
4205 ERR("Failed to reserve memory.\n");
4209 deferred
->queries
[deferred
->query_count
].flags
= flags
;
4210 wined3d_query_incref(deferred
->queries
[deferred
->query_count
++].query
= query
);
4213 static void wined3d_deferred_context_flush(struct wined3d_device_context
*context
)
4215 FIXME("context %p, stub!\n", context
);
4218 static void wined3d_deferred_context_reference_resource(struct wined3d_device_context
*context
,
4219 struct wined3d_resource
*resource
)
4221 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4223 if (!wined3d_array_reserve((void **)&deferred
->resources
, &deferred
->resources_capacity
,
4224 deferred
->resource_count
+ 1, sizeof(*deferred
->resources
)))
4227 deferred
->resources
[deferred
->resource_count
++] = resource
;
4228 wined3d_resource_incref(resource
);
4231 static void wined3d_deferred_context_reference_command_list(struct wined3d_device_context
*context
,
4232 struct wined3d_command_list
*list
)
4234 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4236 /* Grab a reference to the command list. Note that this implicitly prevents
4237 * any dependent command lists or resources from being freed as well. */
4238 if (!wined3d_array_reserve((void **)&deferred
->command_lists
, &deferred
->command_lists_capacity
,
4239 deferred
->command_list_count
+ 1, sizeof(*deferred
->command_lists
)))
4242 wined3d_command_list_incref(deferred
->command_lists
[deferred
->command_list_count
++] = list
);
4245 static const struct wined3d_device_context_ops wined3d_deferred_context_ops
=
4247 wined3d_deferred_context_require_space
,
4248 wined3d_deferred_context_submit
,
4249 wined3d_deferred_context_finish
,
4250 wined3d_deferred_context_push_constants
,
4251 wined3d_deferred_context_map_upload_bo
,
4252 wined3d_deferred_context_unmap_upload_bo
,
4253 wined3d_deferred_context_issue_query
,
4254 wined3d_deferred_context_flush
,
4255 wined3d_deferred_context_reference_resource
,
4256 wined3d_deferred_context_reference_command_list
,
4259 HRESULT CDECL
wined3d_deferred_context_create(struct wined3d_device
*device
, struct wined3d_device_context
**context
)
4261 struct wined3d_deferred_context
*object
;
4264 TRACE("device %p, context %p.\n", device
, context
);
4266 if (!(object
= heap_alloc_zero(sizeof(*object
))))
4267 return E_OUTOFMEMORY
;
4269 if (FAILED(hr
= wined3d_state_create(device
, &device
->cs
->c
.state
->feature_level
, 1, &object
->c
.state
)))
4275 object
->c
.ops
= &wined3d_deferred_context_ops
;
4276 object
->c
.device
= device
;
4278 /* Make sure the first command list gets the state reset when executed.
4279 * Resets for subsequent command lists are encoded in wined3d_deferred_context_record_command_list(). */
4280 wined3d_device_context_emit_reset_state(&object
->c
, true);
4282 TRACE("Created deferred context %p.\n", object
);
4283 *context
= &object
->c
;
4288 void CDECL
wined3d_deferred_context_destroy(struct wined3d_device_context
*context
)
4290 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4291 const struct wined3d_cs_packet
*packet
;
4292 SIZE_T i
, offset
= 0;
4294 TRACE("context %p.\n", context
);
4296 for (i
= 0; i
< deferred
->resource_count
; ++i
)
4297 wined3d_resource_decref(deferred
->resources
[i
]);
4298 heap_free(deferred
->resources
);
4300 for (i
= 0; i
< deferred
->upload_count
; ++i
)
4302 wined3d_resource_decref(deferred
->uploads
[i
].resource
);
4303 HeapFree(deferred
->upload_heap
, 0, deferred
->uploads
[i
].resource
);
4306 if (deferred
->upload_heap
)
4308 if (!InterlockedDecrement(deferred
->upload_heap_refcount
))
4310 HeapDestroy(deferred
->upload_heap
);
4311 heap_free(deferred
->upload_heap_refcount
);
4315 heap_free(deferred
->uploads
);
4317 for (i
= 0; i
< deferred
->command_list_count
; ++i
)
4318 wined3d_command_list_decref(deferred
->command_lists
[i
]);
4319 heap_free(deferred
->command_lists
);
4321 for (i
= 0; i
< deferred
->query_count
; ++i
)
4322 wined3d_query_decref(deferred
->queries
[i
].query
);
4323 heap_free(deferred
->queries
);
4325 while (offset
< deferred
->data_size
)
4327 packet
= wined3d_next_cs_packet(deferred
->data
, &offset
, ~(SIZE_T
)0);
4328 wined3d_cs_packet_decref_objects(packet
);
4331 wined3d_state_destroy(deferred
->c
.state
);
4332 heap_free(deferred
->data
);
4333 heap_free(deferred
);
4336 HRESULT CDECL
wined3d_deferred_context_record_command_list(struct wined3d_device_context
*context
,
4337 bool restore
, struct wined3d_command_list
**list
)
4339 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4340 struct wined3d_command_list
*object
;
4343 TRACE("context %p, list %p.\n", context
, list
);
4345 wined3d_device_context_lock(context
);
4346 memory
= heap_alloc(sizeof(*object
) + deferred
->resource_count
* sizeof(*object
->resources
)
4347 + deferred
->upload_count
* sizeof(*object
->uploads
)
4348 + deferred
->command_list_count
* sizeof(*object
->command_lists
)
4349 + deferred
->query_count
* sizeof(*object
->queries
)
4350 + deferred
->data_size
);
4354 wined3d_device_context_unlock(context
);
4355 return E_OUTOFMEMORY
;
4359 memory
= &object
[1];
4360 memset(object
, 0, sizeof(*object
));
4361 object
->refcount
= 1;
4362 object
->device
= deferred
->c
.device
;
4364 object
->resources
= memory
;
4365 memory
= &object
->resources
[deferred
->resource_count
];
4366 object
->resource_count
= deferred
->resource_count
;
4367 memcpy(object
->resources
, deferred
->resources
, deferred
->resource_count
* sizeof(*object
->resources
));
4368 /* Transfer our references to the resources to the command list. */
4370 object
->uploads
= memory
;
4371 memory
= &object
->uploads
[deferred
->upload_count
];
4372 object
->upload_count
= deferred
->upload_count
;
4373 memcpy(object
->uploads
, deferred
->uploads
, deferred
->upload_count
* sizeof(*object
->uploads
));
4374 /* Transfer our references to the resources to the command list. */
4376 object
->command_lists
= memory
;
4377 memory
= &object
->command_lists
[deferred
->command_list_count
];
4378 object
->command_list_count
= deferred
->command_list_count
;
4379 memcpy(object
->command_lists
, deferred
->command_lists
,
4380 deferred
->command_list_count
* sizeof(*object
->command_lists
));
4381 /* Transfer our references to the command lists to the command list. */
4383 object
->queries
= memory
;
4384 memory
= &object
->queries
[deferred
->query_count
];
4385 object
->query_count
= deferred
->query_count
;
4386 memcpy(object
->queries
, deferred
->queries
, deferred
->query_count
* sizeof(*object
->queries
));
4387 /* Transfer our references to the queries to the command list. */
4389 object
->data
= memory
;
4390 object
->data_size
= deferred
->data_size
;
4391 memcpy(object
->data
, deferred
->data
, deferred
->data_size
);
4393 deferred
->data_size
= 0;
4394 deferred
->resource_count
= 0;
4395 deferred
->upload_count
= 0;
4396 deferred
->command_list_count
= 0;
4397 deferred
->query_count
= 0;
4399 object
->upload_heap
= deferred
->upload_heap
;
4400 if ((object
->upload_heap_refcount
= deferred
->upload_heap_refcount
))
4401 InterlockedIncrement(object
->upload_heap_refcount
);
4403 /* This is in fact recorded into a subsequent command list. */
4405 wined3d_device_context_set_state(&deferred
->c
, deferred
->c
.state
);
4407 wined3d_device_context_reset_state(&deferred
->c
);
4409 TRACE("Created command list %p.\n", object
);
4411 wined3d_device_context_unlock(context
);
4416 static void wined3d_command_list_destroy_object(void *object
)
4418 struct wined3d_command_list
*list
= object
;
4421 TRACE("list %p.\n", list
);
4423 for (i
= 0; i
< list
->upload_count
; ++i
)
4424 HeapFree(list
->upload_heap
, 0, list
->uploads
[i
].sysmem
);
4426 if (list
->upload_heap
)
4428 if (!InterlockedDecrement(list
->upload_heap_refcount
))
4430 HeapDestroy(list
->upload_heap
);
4431 heap_free(list
->upload_heap_refcount
);
4438 ULONG CDECL
wined3d_command_list_incref(struct wined3d_command_list
*list
)
4440 unsigned int refcount
= InterlockedIncrement(&list
->refcount
);
4442 TRACE("%p increasing refcount to %u.\n", list
, refcount
);
4447 ULONG CDECL
wined3d_command_list_decref(struct wined3d_command_list
*list
)
4449 unsigned int refcount
= InterlockedDecrement(&list
->refcount
);
4450 struct wined3d_device
*device
= list
->device
;
4451 const struct wined3d_cs_packet
*packet
;
4454 TRACE("%p decreasing refcount to %u.\n", list
, refcount
);
4458 for (i
= 0; i
< list
->command_list_count
; ++i
)
4459 wined3d_command_list_decref(list
->command_lists
[i
]);
4460 for (i
= 0; i
< list
->resource_count
; ++i
)
4461 wined3d_resource_decref(list
->resources
[i
]);
4462 for (i
= 0; i
< list
->upload_count
; ++i
)
4463 wined3d_resource_decref(list
->uploads
[i
].resource
);
4464 for (i
= 0; i
< list
->query_count
; ++i
)
4465 wined3d_query_decref(list
->queries
[i
].query
);
4468 while (offset
< list
->data_size
)
4470 packet
= wined3d_next_cs_packet(list
->data
, &offset
, ~(SIZE_T
)0);
4471 wined3d_cs_packet_decref_objects(packet
);
4474 wined3d_mutex_lock();
4475 wined3d_cs_destroy_object(device
->cs
, wined3d_command_list_destroy_object
, list
);
4476 wined3d_mutex_unlock();