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
, hash_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 hash_idx
= LIGHTMAP_HASHFUNC(light_idx
);
2015 list_add_head(&cs
->state
.light_state
.light_map
[hash_idx
], &light_info
->entry
);
2016 light_info
->glIndex
= -1;
2017 light_info
->OriginalIndex
= light_idx
;
2020 if (light_info
->glIndex
!= -1)
2022 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
2023 device_invalidate_state(cs
->c
.device
, STATE_LIGHT_TYPE
);
2024 device_invalidate_state(cs
->c
.device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
2027 light_info
->OriginalParms
= op
->light
.OriginalParms
;
2028 light_info
->position
= op
->light
.position
;
2029 light_info
->direction
= op
->light
.direction
;
2030 light_info
->exponent
= op
->light
.exponent
;
2031 light_info
->cutoff
= op
->light
.cutoff
;
2034 void wined3d_device_context_emit_set_light(struct wined3d_device_context
*context
,
2035 const struct wined3d_light_info
*light
)
2037 struct wined3d_cs_set_light
*op
;
2039 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2040 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
2043 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2046 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
2048 const struct wined3d_cs_set_light_enable
*op
= data
;
2049 struct wined3d_device
*device
= cs
->c
.device
;
2050 struct wined3d_light_info
*light_info
;
2053 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, op
->idx
)))
2055 ERR("Light doesn't exist.\n");
2059 prev_idx
= light_info
->glIndex
;
2060 wined3d_light_state_enable_light(&cs
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
);
2061 if (light_info
->glIndex
!= prev_idx
)
2063 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
2064 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
2068 void wined3d_device_context_emit_set_light_enable(struct wined3d_device_context
*context
, unsigned int idx
, BOOL enable
)
2070 struct wined3d_cs_set_light_enable
*op
;
2072 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2073 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
2075 op
->enable
= enable
;
2077 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2080 static void wined3d_cs_exec_set_feature_level(struct wined3d_cs
*cs
, const void *data
)
2082 const struct wined3d_cs_set_feature_level
*op
= data
;
2084 cs
->state
.feature_level
= op
->level
;
2087 void wined3d_device_context_emit_set_feature_level(struct wined3d_device_context
*context
,
2088 enum wined3d_feature_level level
)
2090 struct wined3d_cs_set_feature_level
*op
;
2092 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2093 op
->opcode
= WINED3D_CS_OP_SET_FEATURE_LEVEL
;
2096 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2105 wined3d_cs_push_constant_info
[] =
2107 /* WINED3D_PUSH_CONSTANTS_VS_F */
2108 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
2109 /* WINED3D_PUSH_CONSTANTS_PS_F */
2110 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
2111 /* WINED3D_PUSH_CONSTANTS_VS_I */
2112 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
2113 /* WINED3D_PUSH_CONSTANTS_PS_I */
2114 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
2115 /* WINED3D_PUSH_CONSTANTS_VS_B */
2116 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
2117 /* WINED3D_PUSH_CONSTANTS_PS_B */
2118 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
2121 static void wined3d_cs_st_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2122 unsigned int start_idx
, unsigned int count
, const void *constants
)
2124 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2125 struct wined3d_device
*device
= cs
->c
.device
;
2126 unsigned int context_count
;
2130 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
2131 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
2132 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
2133 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
2135 offset
= wined3d_cs_push_constant_info
[p
].offset
+ start_idx
* wined3d_cs_push_constant_info
[p
].size
;
2136 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* wined3d_cs_push_constant_info
[p
].size
);
2137 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
2139 device
->contexts
[i
]->constant_update_mask
|= wined3d_cs_push_constant_info
[p
].mask
;
2143 static void wined3d_cs_exec_push_constants(struct wined3d_cs
*cs
, const void *data
)
2145 const struct wined3d_cs_push_constants
*op
= data
;
2147 wined3d_cs_st_push_constants(&cs
->c
, op
->type
, op
->start_idx
, op
->count
, op
->constants
);
2150 static void wined3d_cs_mt_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2151 unsigned int start_idx
, unsigned int count
, const void *constants
)
2153 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2154 struct wined3d_cs_push_constants
*op
;
2157 size
= count
* wined3d_cs_push_constant_info
[p
].size
;
2158 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_push_constants
, constants
[size
]),
2159 WINED3D_CS_QUEUE_DEFAULT
);
2160 op
->opcode
= WINED3D_CS_OP_PUSH_CONSTANTS
;
2162 op
->start_idx
= start_idx
;
2164 memcpy(op
->constants
, constants
, size
);
2166 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2169 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
2171 const struct wined3d_device
*device
= cs
->c
.device
;
2172 const struct wined3d_cs_reset_state
*op
= data
;
2173 const struct wined3d_state_entry
*state_table
;
2176 state_cleanup(&cs
->state
);
2177 wined3d_state_reset(&cs
->state
, &device
->adapter
->d3d_info
);
2180 state_table
= device
->state_table
;
2181 for (state
= 0; state
<= STATE_HIGHEST
; ++state
)
2183 if (state_table
[state
].representative
)
2184 device_invalidate_state(device
, state
);
2189 void wined3d_device_context_emit_reset_state(struct wined3d_device_context
*context
, bool invalidate
)
2191 struct wined3d_cs_reset_state
*op
;
2193 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2194 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
2195 op
->invalidate
= invalidate
;
2197 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2200 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
2202 const struct wined3d_cs_callback
*op
= data
;
2204 op
->callback(op
->object
);
2207 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2209 struct wined3d_cs_callback
*op
;
2211 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2212 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
2213 op
->callback
= callback
;
2214 op
->object
= object
;
2216 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2219 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2221 wined3d_cs_emit_callback(cs
, callback
, object
);
2224 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2226 wined3d_cs_emit_callback(cs
, callback
, object
);
2229 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
2231 const struct wined3d_cs_query_issue
*op
= data
;
2232 struct wined3d_query
*query
= op
->query
;
2235 poll
= query
->query_ops
->query_issue(query
, op
->flags
);
2237 if (!query
->poll_in_cs
)
2239 if (op
->flags
& WINED3DISSUE_END
)
2240 InterlockedIncrement(&query
->counter_retrieved
);
2244 if (poll
&& list_empty(&query
->poll_list_entry
))
2246 if (query
->buffer_object
)
2247 InterlockedIncrement(&query
->counter_retrieved
);
2249 list_add_tail(&cs
->query_poll_list
, &query
->poll_list_entry
);
2253 /* This can happen if occlusion queries are restarted. This discards the
2254 * old result, since polling it could result in a GL error. */
2255 if ((op
->flags
& WINED3DISSUE_BEGIN
) && !poll
&& !list_empty(&query
->poll_list_entry
))
2257 list_remove(&query
->poll_list_entry
);
2258 list_init(&query
->poll_list_entry
);
2259 InterlockedIncrement(&query
->counter_retrieved
);
2263 /* This can happen when an occlusion query is ended without being started,
2264 * in which case we don't want to poll, but still have to counter-balance
2265 * the increment of the main counter.
2267 * This can also happen if an event query is re-issued before the first
2268 * fence was reached. In this case the query is already in the list and
2269 * the poll function will check the new fence. We have to counter-balance
2270 * the discarded increment. */
2271 if (op
->flags
& WINED3DISSUE_END
)
2272 InterlockedIncrement(&query
->counter_retrieved
);
2275 static void wined3d_cs_issue_query(struct wined3d_device_context
*context
,
2276 struct wined3d_query
*query
, unsigned int flags
)
2278 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2279 struct wined3d_cs_query_issue
*op
;
2281 if (flags
& WINED3DISSUE_END
)
2282 ++query
->counter_main
;
2284 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2285 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
2289 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2290 cs
->queries_flushed
= FALSE
;
2292 if (flags
& WINED3DISSUE_BEGIN
)
2293 query
->state
= QUERY_BUILDING
;
2295 query
->state
= QUERY_SIGNALLED
;
2298 static void wined3d_cs_reference_command_list(struct wined3d_device_context
*context
, struct wined3d_command_list
*list
)
2300 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2303 if (list
->query_count
)
2305 cs
->queries_flushed
= FALSE
;
2307 for (i
= 0; i
< list
->query_count
; ++i
)
2309 if (list
->queries
[i
].flags
& WINED3DISSUE_END
)
2311 list
->queries
[i
].query
->counter_main
++;
2312 list
->queries
[i
].query
->state
= QUERY_SIGNALLED
;
2316 list
->queries
[i
].query
->state
= QUERY_BUILDING
;
2321 for (i
= 0; i
< list
->resource_count
; ++i
)
2322 wined3d_resource_reference(list
->resources
[i
]);
2324 for (i
= 0; i
< list
->command_list_count
; ++i
)
2325 wined3d_cs_reference_command_list(context
, list
->command_lists
[i
]);
2327 for (i
= 0; i
< list
->upload_count
; ++i
)
2328 invalidate_client_address(list
->uploads
[i
].resource
);
2331 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
2333 const struct wined3d_cs_preload_resource
*op
= data
;
2334 struct wined3d_resource
*resource
= op
->resource
;
2336 resource
->resource_ops
->resource_preload(resource
);
2339 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2341 struct wined3d_cs_preload_resource
*op
;
2343 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2344 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
2345 op
->resource
= resource
;
2347 wined3d_resource_reference(resource
);
2349 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2352 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
2354 const struct wined3d_cs_unload_resource
*op
= data
;
2355 struct wined3d_resource
*resource
= op
->resource
;
2357 resource
->resource_ops
->resource_unload(resource
);
2360 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2362 struct wined3d_cs_unload_resource
*op
;
2364 discard_client_address(resource
);
2366 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2367 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
2368 op
->resource
= resource
;
2370 wined3d_resource_reference(resource
);
2372 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2375 static void wined3d_device_context_upload_bo(struct wined3d_device_context
*context
,
2376 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2377 const struct upload_bo
*bo
, unsigned int row_pitch
, unsigned int slice_pitch
)
2379 struct wined3d_cs_update_sub_resource
*op
;
2381 TRACE("context %p, resource %p, sub_resource_idx %u, box %s, bo %s, flags %#x, row_pitch %u, slice_pitch %u.\n",
2382 context
, resource
, sub_resource_idx
, debug_box(box
),
2383 debug_const_bo_address(&bo
->addr
), bo
->flags
, row_pitch
, slice_pitch
);
2385 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2386 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2387 op
->resource
= resource
;
2388 op
->sub_resource_idx
= sub_resource_idx
;
2391 op
->row_pitch
= row_pitch
;
2392 op
->slice_pitch
= slice_pitch
;
2394 wined3d_device_context_reference_resource(context
, resource
);
2396 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2399 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
2401 const struct wined3d_cs_map
*op
= data
;
2402 struct wined3d_resource
*resource
= op
->resource
;
2404 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
2405 op
->sub_resource_idx
, op
->map_ptr
, op
->box
, op
->flags
);
2408 HRESULT
wined3d_device_context_emit_map(struct wined3d_device_context
*context
,
2409 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
2410 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
2412 struct wined3d_cs_map
*op
;
2415 /* Mapping resources from the worker thread isn't an issue by itself, but
2416 * increasing the map count would be visible to applications. */
2417 wined3d_not_from_cs(context
->device
->cs
);
2419 if ((flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2420 && context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, map_desc
, box
, flags
))
2422 TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n",
2423 map_desc
->data
, map_desc
->row_pitch
, map_desc
->slice_pitch
);
2427 wined3d_resource_wait_idle(resource
);
2429 /* We might end up invalidating the resource on the CS thread. */
2430 invalidate_client_address(resource
);
2432 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2433 return E_OUTOFMEMORY
;
2434 op
->opcode
= WINED3D_CS_OP_MAP
;
2435 op
->resource
= resource
;
2436 op
->sub_resource_idx
= sub_resource_idx
;
2437 op
->map_ptr
= &map_desc
->data
;
2442 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2443 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2446 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
2447 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
2451 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
2453 const struct wined3d_cs_unmap
*op
= data
;
2454 struct wined3d_resource
*resource
= op
->resource
;
2456 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
2459 HRESULT
wined3d_device_context_emit_unmap(struct wined3d_device_context
*context
,
2460 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
2462 struct wined3d_cs_unmap
*op
;
2463 struct wined3d_box box
;
2464 struct upload_bo bo
;
2467 if (context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
))
2469 unsigned int row_pitch
, slice_pitch
;
2471 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
, &row_pitch
, &slice_pitch
);
2472 if (bo
.flags
& UPLOAD_BO_UPLOAD_ON_UNMAP
)
2473 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
, row_pitch
, slice_pitch
);
2477 wined3d_not_from_cs(context
->device
->cs
);
2479 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2480 return E_OUTOFMEMORY
;
2481 op
->opcode
= WINED3D_CS_OP_UNMAP
;
2482 op
->resource
= resource
;
2483 op
->sub_resource_idx
= sub_resource_idx
;
2486 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2487 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2492 static void wined3d_cs_exec_map_bo_address(struct wined3d_cs
*cs
, const void *data
)
2494 const struct wined3d_cs_map_bo_address
*op
= data
;
2495 struct wined3d_context
*context
;
2497 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2498 wined3d_context_map_bo_address(context
, &op
->addr
, op
->size
, op
->flags
);
2499 context_release(context
);
2502 void wined3d_cs_map_bo_address(struct wined3d_cs
*cs
,
2503 struct wined3d_bo_address
*addr
, size_t size
, unsigned int flags
)
2505 struct wined3d_device_context
*context
= &cs
->c
;
2506 struct wined3d_cs_map_bo_address
*op
;
2508 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2509 op
->opcode
= WINED3D_CS_OP_MAP_BO_ADDRESS
;
2513 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2514 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2517 static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2519 const struct wined3d_cs_blt_sub_resource
*op
= data
;
2521 if (op
->dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
2523 wined3d_buffer_copy(buffer_from_resource(op
->dst_resource
), op
->dst_box
.left
,
2524 buffer_from_resource(op
->src_resource
), op
->src_box
.left
,
2525 op
->src_box
.right
- op
->src_box
.left
);
2527 else if (op
->dst_resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
2529 struct wined3d_texture
*src_texture
, *dst_texture
;
2530 unsigned int level
, update_w
, update_h
, update_d
;
2531 unsigned int row_pitch
, slice_pitch
;
2532 struct wined3d_context
*context
;
2533 struct wined3d_bo_address addr
;
2534 unsigned int location
;
2536 if (op
->flags
& ~WINED3D_BLT_RAW
)
2538 FIXME("Flags %#x not implemented for %s resources.\n",
2539 op
->flags
, debug_d3dresourcetype(op
->dst_resource
->type
));
2543 if (!(op
->flags
& WINED3D_BLT_RAW
) && op
->src_resource
->format
!= op
->dst_resource
->format
)
2545 FIXME("Format conversion not implemented for %s resources.\n",
2546 debug_d3dresourcetype(op
->dst_resource
->type
));
2550 update_w
= op
->dst_box
.right
- op
->dst_box
.left
;
2551 update_h
= op
->dst_box
.bottom
- op
->dst_box
.top
;
2552 update_d
= op
->dst_box
.back
- op
->dst_box
.front
;
2553 if (op
->src_box
.right
- op
->src_box
.left
!= update_w
2554 || op
->src_box
.bottom
- op
->src_box
.top
!= update_h
2555 || op
->src_box
.back
- op
->src_box
.front
!= update_d
)
2557 FIXME("Stretching not implemented for %s resources.\n",
2558 debug_d3dresourcetype(op
->dst_resource
->type
));
2562 dst_texture
= texture_from_resource(op
->dst_resource
);
2563 src_texture
= texture_from_resource(op
->src_resource
);
2565 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2567 location
= src_texture
->resource
.map_binding
;
2568 if (location
== WINED3D_LOCATION_SYSMEM
2569 && wined3d_texture_can_use_pbo(src_texture
, &context
->device
->adapter
->d3d_info
))
2570 location
= WINED3D_LOCATION_BUFFER
;
2572 if (!wined3d_texture_load_location(src_texture
, op
->src_sub_resource_idx
,
2575 ERR("Failed to load source sub-resource into %s.\n",
2576 wined3d_debug_location(location
));
2577 context_release(context
);
2581 level
= op
->dst_sub_resource_idx
% dst_texture
->level_count
;
2582 if (update_w
== wined3d_texture_get_level_width(dst_texture
, level
)
2583 && update_h
== wined3d_texture_get_level_height(dst_texture
, level
)
2584 && update_d
== wined3d_texture_get_level_depth(dst_texture
, level
))
2586 wined3d_texture_prepare_location(dst_texture
, op
->dst_sub_resource_idx
,
2587 context
, WINED3D_LOCATION_TEXTURE_RGB
);
2589 else if (!wined3d_texture_load_location(dst_texture
, op
->dst_sub_resource_idx
,
2590 context
, WINED3D_LOCATION_TEXTURE_RGB
))
2592 ERR("Failed to load destination sub-resource.\n");
2593 context_release(context
);
2597 wined3d_texture_get_bo_address(src_texture
, op
->src_sub_resource_idx
, &addr
, location
);
2598 wined3d_texture_get_pitch(src_texture
, op
->src_sub_resource_idx
% src_texture
->level_count
,
2599 &row_pitch
, &slice_pitch
);
2601 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&addr
),
2602 dst_texture
->resource
.format
, &op
->src_box
, row_pitch
, slice_pitch
, dst_texture
,
2603 op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
2604 op
->dst_box
.left
, op
->dst_box
.top
, op
->dst_box
.front
);
2605 wined3d_texture_validate_location(dst_texture
, op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2606 wined3d_texture_invalidate_location(dst_texture
, op
->dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2608 context_release(context
);
2612 if (FAILED(texture2d_blt(texture_from_resource(op
->dst_resource
), op
->dst_sub_resource_idx
,
2613 &op
->dst_box
, texture_from_resource(op
->src_resource
), op
->src_sub_resource_idx
,
2614 &op
->src_box
, op
->flags
, &op
->fx
, op
->filter
)))
2615 FIXME("Blit failed.\n");
2619 void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context
*context
,
2620 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
, const struct wined3d_box
*dst_box
,
2621 struct wined3d_resource
*src_resource
, unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
,
2622 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
2624 struct wined3d_cs_blt_sub_resource
*op
;
2626 /* If we are replacing the whole resource, the CS thread might discard and
2627 * rename the buffer object, in which case ours is no longer valid. */
2628 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
&& dst_box
->right
- dst_box
->left
== dst_resource
->size
)
2629 invalidate_client_address(dst_resource
);
2631 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2632 op
->opcode
= WINED3D_CS_OP_BLT_SUB_RESOURCE
;
2633 op
->dst_resource
= dst_resource
;
2634 op
->dst_sub_resource_idx
= dst_sub_resource_idx
;
2635 op
->dst_box
= *dst_box
;
2636 op
->src_resource
= src_resource
;
2637 op
->src_sub_resource_idx
= src_sub_resource_idx
;
2638 op
->src_box
= *src_box
;
2643 memset(&op
->fx
, 0, sizeof(op
->fx
));
2644 op
->filter
= filter
;
2646 wined3d_device_context_reference_resource(context
, dst_resource
);
2648 wined3d_device_context_reference_resource(context
, src_resource
);
2650 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2651 if (flags
& WINED3D_BLT_SYNCHRONOUS
)
2652 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
2655 static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2657 const struct wined3d_cs_update_sub_resource
*op
= data
;
2658 struct wined3d_resource
*resource
= op
->resource
;
2659 const struct wined3d_box
*box
= &op
->box
;
2660 struct wined3d_context
*context
;
2662 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2664 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2665 wined3d_buffer_update_sub_resource(buffer_from_resource(resource
),
2666 context
, &op
->bo
, box
->left
, box
->right
- box
->left
);
2668 wined3d_texture_update_sub_resource(texture_from_resource(resource
),
2669 op
->sub_resource_idx
, context
, &op
->bo
, box
, op
->row_pitch
, op
->slice_pitch
);
2671 context_release(context
);
2673 if (op
->bo
.flags
& UPLOAD_BO_FREE_ON_UNMAP
)
2675 if (op
->bo
.addr
.buffer_object
)
2676 FIXME("Free BO address %s.\n", debug_const_bo_address(&op
->bo
.addr
));
2678 heap_free((void *)op
->bo
.addr
.addr
);
2682 void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_context
*context
,
2683 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2684 const void *data
, unsigned int row_pitch
, unsigned int slice_pitch
)
2686 struct wined3d_cs_update_sub_resource
*op
;
2687 struct wined3d_map_desc map_desc
;
2688 struct wined3d_box dummy_box
;
2689 struct upload_bo bo
;
2691 /* If we are replacing the whole resource, the CS thread might discard and
2692 * rename the buffer object, in which case ours is no longer valid. */
2693 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& box
->right
- box
->left
== resource
->size
)
2694 invalidate_client_address(resource
);
2696 if (context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, &map_desc
, box
, WINED3D_MAP_WRITE
))
2698 wined3d_format_copy_data(resource
->format
, data
, row_pitch
, slice_pitch
, map_desc
.data
, map_desc
.row_pitch
,
2699 map_desc
.slice_pitch
, box
->right
- box
->left
, box
->bottom
- box
->top
, box
->back
- box
->front
);
2700 context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &dummy_box
, &bo
);
2701 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
,
2702 box
, &bo
, map_desc
.row_pitch
, map_desc
.slice_pitch
);
2706 wined3d_resource_wait_idle(resource
);
2708 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2709 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2710 op
->resource
= resource
;
2711 op
->sub_resource_idx
= sub_resource_idx
;
2713 op
->bo
.addr
.buffer_object
= 0;
2714 op
->bo
.addr
.addr
= data
;
2716 op
->row_pitch
= row_pitch
;
2717 op
->slice_pitch
= slice_pitch
;
2719 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2720 /* The data pointer may go away, so we need to wait until it is read.
2721 * Copying the data may be faster if it's small. */
2722 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2725 static void wined3d_cs_exec_add_dirty_texture_region(struct wined3d_cs
*cs
, const void *data
)
2727 const struct wined3d_cs_add_dirty_texture_region
*op
= data
;
2728 struct wined3d_texture
*texture
= op
->texture
;
2729 unsigned int sub_resource_idx
, i
;
2730 struct wined3d_context
*context
;
2732 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2733 sub_resource_idx
= op
->layer
* texture
->level_count
;
2734 for (i
= 0; i
< texture
->level_count
; ++i
, ++sub_resource_idx
)
2736 if (wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
))
2737 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
2739 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
2741 context_release(context
);
2744 void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs
*cs
,
2745 struct wined3d_texture
*texture
, unsigned int layer
)
2747 struct wined3d_cs_add_dirty_texture_region
*op
;
2749 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2750 op
->opcode
= WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
;
2751 op
->texture
= texture
;
2754 wined3d_resource_reference(&texture
->resource
);
2756 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2759 static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
2761 const struct wined3d_cs_clear_unordered_access_view
*op
= data
;
2762 struct wined3d_unordered_access_view
*view
= op
->view
;
2763 struct wined3d_context
*context
;
2765 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2766 cs
->c
.device
->adapter
->adapter_ops
->adapter_clear_uav(context
, view
, &op
->clear_value
, op
->fp
);
2767 context_release(context
);
2770 void wined3d_device_context_emit_clear_uav(struct wined3d_device_context
*context
,
2771 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
, bool fp
)
2773 struct wined3d_cs_clear_unordered_access_view
*op
;
2775 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2776 op
->opcode
= WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
;
2778 op
->clear_value
= *clear_value
;
2781 wined3d_device_context_reference_resource(context
, view
->resource
);
2783 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2786 static void wined3d_cs_exec_copy_uav_counter(struct wined3d_cs
*cs
, const void *data
)
2788 const struct wined3d_cs_copy_uav_counter
*op
= data
;
2789 struct wined3d_unordered_access_view
*view
= op
->view
;
2790 struct wined3d_context
*context
;
2792 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2793 wined3d_unordered_access_view_copy_counter(view
, op
->buffer
, op
->offset
, context
);
2794 context_release(context
);
2797 void wined3d_device_context_emit_copy_uav_counter(struct wined3d_device_context
*context
,
2798 struct wined3d_buffer
*dst_buffer
, unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
2800 struct wined3d_cs_copy_uav_counter
*op
;
2802 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2803 op
->opcode
= WINED3D_CS_OP_COPY_UAV_COUNTER
;
2804 op
->buffer
= dst_buffer
;
2805 op
->offset
= offset
;
2808 wined3d_device_context_reference_resource(context
, &dst_buffer
->resource
);
2810 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2813 static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs
*cs
, const void *data
)
2815 const struct wined3d_cs_generate_mipmaps
*op
= data
;
2816 struct wined3d_shader_resource_view
*view
= op
->view
;
2817 struct wined3d_context
*context
;
2819 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2820 cs
->c
.device
->adapter
->adapter_ops
->adapter_generate_mipmap(context
, view
);
2821 context_release(context
);
2824 void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context
*context
,
2825 struct wined3d_shader_resource_view
*view
)
2827 struct wined3d_cs_generate_mipmaps
*op
;
2829 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2830 op
->opcode
= WINED3D_CS_OP_GENERATE_MIPMAPS
;
2833 wined3d_device_context_reference_resource(context
, view
->resource
);
2835 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2838 static void wined3d_cs_emit_stop(struct wined3d_cs
*cs
)
2840 struct wined3d_cs_stop
*op
;
2842 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2843 op
->opcode
= WINED3D_CS_OP_STOP
;
2845 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2846 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2849 static void wined3d_cs_reference_resource(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
)
2851 wined3d_resource_reference(resource
);
2854 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
);
2856 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
2858 /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop
,
2859 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
2860 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
2861 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
2862 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
2863 /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush
,
2864 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
2865 /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports
,
2866 /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects
,
2867 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEWS */ wined3d_cs_exec_set_rendertarget_views
,
2868 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
2869 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
2870 /* WINED3D_CS_OP_SET_STREAM_SOURCES */ wined3d_cs_exec_set_stream_sources
,
2871 /* WINED3D_CS_OP_SET_STREAM_OUTPUTS */ wined3d_cs_exec_set_stream_outputs
,
2872 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
2873 /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers
,
2874 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
2875 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS */ wined3d_cs_exec_set_shader_resource_views
,
2876 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS */ wined3d_cs_exec_set_unordered_access_views
,
2877 /* WINED3D_CS_OP_SET_SAMPLERS */ wined3d_cs_exec_set_samplers
,
2878 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
2879 /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state
,
2880 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE */ wined3d_cs_exec_set_depth_stencil_state
,
2881 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
2882 /* WINED3D_CS_OP_SET_DEPTH_BOUNDS */ wined3d_cs_exec_set_depth_bounds
,
2883 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
2884 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
2885 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
2886 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
2887 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
2888 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
2889 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
2890 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
2891 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
2892 /* WINED3D_CS_OP_SET_FEATURE_LEVEL */ wined3d_cs_exec_set_feature_level
,
2893 /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants
,
2894 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
2895 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
2896 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
2897 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
2898 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
2899 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
2900 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
2901 /* WINED3D_CS_OP_MAP_BO_ADDRESS */ wined3d_cs_exec_map_bo_address
,
2902 /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource
,
2903 /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource
,
2904 /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region
,
2905 /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view
,
2906 /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter
,
2907 /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps
,
2908 /* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list
,
2911 void wined3d_device_context_emit_execute_command_list(struct wined3d_device_context
*context
,
2912 struct wined3d_command_list
*list
, bool restore_state
)
2914 struct wined3d_cs_execute_command_list
*op
;
2916 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2917 op
->opcode
= WINED3D_CS_OP_EXECUTE_COMMAND_LIST
;
2920 context
->ops
->reference_command_list(context
, list
);
2922 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2925 wined3d_device_context_set_state(context
, context
->state
);
2927 wined3d_device_context_reset_state(context
);
2930 static void *wined3d_cs_st_require_space(struct wined3d_device_context
*context
,
2931 size_t size
, enum wined3d_cs_queue_id queue_id
)
2933 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2935 if (size
> (cs
->data_size
- cs
->end
))
2940 new_size
= max(size
, cs
->data_size
* 2);
2942 new_data
= heap_realloc(cs
->data
, new_size
);
2944 new_data
= heap_alloc(new_size
);
2948 cs
->data_size
= new_size
;
2949 cs
->start
= cs
->end
= 0;
2950 cs
->data
= new_data
;
2955 return (BYTE
*)cs
->data
+ cs
->start
;
2958 static void wined3d_cs_st_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2960 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2961 enum wined3d_cs_op opcode
;
2967 cs
->start
= cs
->end
;
2969 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
2970 if (opcode
>= WINED3D_CS_OP_STOP
)
2971 ERR("Invalid opcode %#x.\n", opcode
);
2973 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
2975 if (cs
->data
== data
)
2976 cs
->start
= cs
->end
= start
;
2981 static void wined3d_cs_st_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2985 static bool wined3d_cs_map_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
2986 unsigned int sub_resource_idx
, struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
2988 struct wined3d_client_resource
*client
= &resource
->client
;
2989 const struct wined3d_format
*format
= resource
->format
;
2992 if (flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2994 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
2995 struct wined3d_device
*device
= context
->device
;
2996 struct wined3d_bo_address addr
;
2997 struct wined3d_bo
*bo
;
3000 /* We can't use persistent maps if we might need to do vertex attribute
3001 * conversion; that will cause the CS thread to invalidate the BO. */
3002 if (!d3d_info
->xyzrhw
|| !d3d_info
->vertex_bgra
|| !d3d_info
->ffp_generic_attributes
)
3004 TRACE("Not returning a persistent buffer because we might need to do vertex attribute conversion.\n");
3008 if (resource
->pin_sysmem
)
3010 TRACE("Not allocating an upload buffer because system memory is pinned for this resource.\n");
3014 if ((flags
& WINED3D_MAP_NOOVERWRITE
) && client
->addr
.buffer_object
== CLIENT_BO_DISCARDED
)
3015 flags
= (flags
& ~WINED3D_MAP_NOOVERWRITE
) | WINED3D_MAP_DISCARD
;
3017 if (flags
& WINED3D_MAP_DISCARD
)
3019 if (!device
->adapter
->adapter_ops
->adapter_alloc_bo(device
, resource
, sub_resource_idx
, &addr
))
3022 /* Limit NOOVERWRITE maps to buffers for now; there are too many
3023 * ways that a texture can be invalidated to even count. */
3024 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
3025 client
->addr
= addr
;
3029 addr
= client
->addr
;
3033 if ((bo
= addr
.buffer_object
))
3035 wined3d_device_bo_map_lock(device
);
3036 if ((map_ptr
= bo
->map_ptr
))
3037 ++bo
->client_map_count
;
3038 wined3d_device_bo_map_unlock(device
);
3042 /* adapter_alloc_bo() should have given us a mapped BO if we are
3044 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3045 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the BO is not mapped.\n");
3049 map_ptr
+= (uintptr_t)addr
.addr
;
3053 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3054 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the sub-resource has no valid address.\n");
3058 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
3059 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3061 client
->mapped_upload
.addr
= *wined3d_const_bo_address(&addr
);
3062 client
->mapped_upload
.flags
= 0;
3065 map_ptr
+= bo
->memory_offset
;
3066 /* If we are not mapping all buffers persistently, use
3067 * UPDATE_SUB_RESOURCE as a means of telling the CS thread to try
3068 * to unmap the resource, so that we can free VA space. */
3069 if (!bo
->coherent
|| !wined3d_map_persistent())
3070 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
;
3072 map_desc
->data
= resource_offset_map_pointer(resource
, sub_resource_idx
, map_ptr
, box
);
3074 if (flags
& WINED3D_MAP_DISCARD
)
3075 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_RENAME_ON_UNMAP
;
3077 client
->mapped_box
= *box
;
3079 TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client
->mapped_upload
.addr
),
3080 client
->mapped_upload
.flags
);
3084 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
3085 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3087 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
3088 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
3089 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
3091 if (!(map_desc
->data
= heap_alloc(size
)))
3093 WARN_(d3d_perf
)("Failed to allocate a heap memory buffer.\n");
3096 client
->mapped_upload
.addr
.buffer_object
= 0;
3097 client
->mapped_upload
.addr
.addr
= map_desc
->data
;
3098 client
->mapped_upload
.flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_FREE_ON_UNMAP
;
3099 client
->mapped_box
= *box
;
3103 static bool wined3d_bo_address_is_null(struct wined3d_const_bo_address
*addr
)
3105 return !addr
->buffer_object
&& !addr
->addr
;
3108 static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
3109 unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*upload_bo
)
3111 struct wined3d_client_resource
*client
= &resource
->client
;
3112 struct wined3d_device
*device
= context
->device
;
3113 struct wined3d_bo
*bo
;
3115 if (wined3d_bo_address_is_null(&client
->mapped_upload
.addr
))
3118 if ((bo
= client
->mapped_upload
.addr
.buffer_object
))
3120 wined3d_device_bo_map_lock(device
);
3121 --bo
->client_map_count
;
3122 wined3d_device_bo_map_unlock(device
);
3125 *upload_bo
= client
->mapped_upload
;
3126 *box
= client
->mapped_box
;
3127 memset(&client
->mapped_upload
, 0, sizeof(client
->mapped_upload
));
3128 memset(&client
->mapped_box
, 0, sizeof(client
->mapped_box
));
3132 static const struct wined3d_device_context_ops wined3d_cs_st_ops
=
3134 wined3d_cs_st_require_space
,
3135 wined3d_cs_st_submit
,
3136 wined3d_cs_st_finish
,
3137 wined3d_cs_st_push_constants
,
3138 wined3d_cs_map_upload_bo
,
3139 wined3d_cs_unmap_upload_bo
,
3140 wined3d_cs_issue_query
,
3142 wined3d_cs_reference_resource
,
3143 wined3d_cs_reference_command_list
,
3146 static BOOL
wined3d_cs_queue_is_empty(const struct wined3d_cs
*cs
, const struct wined3d_cs_queue
*queue
)
3148 wined3d_from_cs(cs
);
3149 return *(volatile ULONG
*)&queue
->head
== queue
->tail
;
3152 static void wined3d_cs_queue_submit(struct wined3d_cs_queue
*queue
, struct wined3d_cs
*cs
)
3154 struct wined3d_cs_packet
*packet
;
3157 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
& WINED3D_CS_QUEUE_MASK
];
3158 TRACE("Queuing op %s at %p.\n", debug_cs_op(*(const enum wined3d_cs_op
*)packet
->data
), packet
);
3159 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
3160 InterlockedExchange((LONG
*)&queue
->head
, queue
->head
+ packet_size
);
3162 if (InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3163 SetEvent(cs
->event
);
3166 static void wined3d_cs_mt_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3168 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3170 if (cs
->thread_id
== GetCurrentThreadId())
3171 return wined3d_cs_st_submit(context
, queue_id
);
3173 wined3d_cs_queue_submit(&cs
->queue
[queue_id
], cs
);
3176 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue
, size_t size
, struct wined3d_cs
*cs
)
3178 size_t queue_size
= ARRAY_SIZE(queue
->data
);
3179 size_t header_size
, packet_size
, remaining
;
3180 struct wined3d_cs_packet
*packet
;
3181 ULONG head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3183 header_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[0]);
3184 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[size
]);
3185 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
3186 size
= packet_size
- header_size
;
3187 if (packet_size
>= WINED3D_CS_QUEUE_SIZE
)
3189 ERR("Packet size %Iu >= queue size %u.\n", packet_size
, WINED3D_CS_QUEUE_SIZE
);
3193 remaining
= queue_size
- head
;
3194 if (remaining
< packet_size
)
3196 size_t nop_size
= remaining
- header_size
;
3197 struct wined3d_cs_nop
*nop
;
3199 TRACE("Inserting a nop for %Iu + %Iu bytes.\n", header_size
, nop_size
);
3201 nop
= wined3d_cs_queue_require_space(queue
, nop_size
, cs
);
3203 nop
->opcode
= WINED3D_CS_OP_NOP
;
3205 wined3d_cs_queue_submit(queue
, cs
);
3206 head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3212 ULONG tail
= (*(volatile ULONG
*)&queue
->tail
) & WINED3D_CS_QUEUE_MASK
;
3218 new_pos
= (head
+ packet_size
) & WINED3D_CS_QUEUE_MASK
;
3219 /* Head ahead of tail. We checked the remaining size above, so we only
3220 * need to make sure we don't make head equal to tail. */
3221 if (head
> tail
&& (new_pos
!= tail
))
3223 /* Tail ahead of head. Make sure the new head is before the tail as
3224 * well. Note that new_pos is 0 when it's at the end of the queue. */
3225 if (new_pos
< tail
&& new_pos
)
3228 TRACE("Waiting for free space. Head %lu, tail %lu, packet size %Iu.\n",
3229 head
, tail
, packet_size
);
3232 packet
= (struct wined3d_cs_packet
*)&queue
->data
[head
];
3233 packet
->size
= size
;
3234 return packet
->data
;
3237 static void *wined3d_cs_mt_require_space(struct wined3d_device_context
*context
,
3238 size_t size
, enum wined3d_cs_queue_id queue_id
)
3240 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3242 if (cs
->thread_id
== GetCurrentThreadId())
3243 return wined3d_cs_st_require_space(context
, size
, queue_id
);
3245 return wined3d_cs_queue_require_space(&cs
->queue
[queue_id
], size
, cs
);
3248 static void wined3d_cs_mt_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3250 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3252 if (cs
->thread_id
== GetCurrentThreadId())
3253 return wined3d_cs_st_finish(context
, queue_id
);
3255 while (cs
->queue
[queue_id
].head
!= *(volatile ULONG
*)&cs
->queue
[queue_id
].tail
)
3259 static const struct wined3d_device_context_ops wined3d_cs_mt_ops
=
3261 wined3d_cs_mt_require_space
,
3262 wined3d_cs_mt_submit
,
3263 wined3d_cs_mt_finish
,
3264 wined3d_cs_mt_push_constants
,
3265 wined3d_cs_map_upload_bo
,
3266 wined3d_cs_unmap_upload_bo
,
3267 wined3d_cs_issue_query
,
3269 wined3d_cs_reference_resource
,
3270 wined3d_cs_reference_command_list
,
3273 static void poll_queries(struct wined3d_cs
*cs
)
3275 struct wined3d_query
*query
, *cursor
;
3277 LIST_FOR_EACH_ENTRY_SAFE(query
, cursor
, &cs
->query_poll_list
, struct wined3d_query
, poll_list_entry
)
3279 if (!query
->query_ops
->query_poll(query
, 0))
3282 list_remove(&query
->poll_list_entry
);
3283 list_init(&query
->poll_list_entry
);
3284 InterlockedIncrement(&query
->counter_retrieved
);
3288 static void wined3d_cs_wait_event(struct wined3d_cs
*cs
)
3290 InterlockedExchange(&cs
->waiting_for_event
, TRUE
);
3292 /* The main thread might have enqueued a command and blocked on it after
3293 * the CS thread decided to enter wined3d_cs_wait_event(), but before
3294 * "waiting_for_event" was set.
3296 * Likewise, we can race with the main thread when resetting
3297 * "waiting_for_event", in which case we would need to call
3298 * WaitForSingleObject() because the main thread called SetEvent(). */
3299 if (!(wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
])
3300 && wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_MAP
]))
3301 && InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3304 WaitForSingleObject(cs
->event
, INFINITE
);
3307 static void wined3d_cs_command_lock(const struct wined3d_cs
*cs
)
3309 if (cs
->serialize_commands
)
3310 EnterCriticalSection(&wined3d_command_cs
);
3313 static void wined3d_cs_command_unlock(const struct wined3d_cs
*cs
)
3315 if (cs
->serialize_commands
)
3316 LeaveCriticalSection(&wined3d_command_cs
);
3319 static inline bool wined3d_cs_execute_next(struct wined3d_cs
*cs
, struct wined3d_cs_queue
*queue
)
3321 struct wined3d_cs_packet
*packet
;
3322 enum wined3d_cs_op opcode
;
3326 packet
= wined3d_next_cs_packet(queue
->data
, &tail
, WINED3D_CS_QUEUE_MASK
);
3330 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3332 TRACE("Executing %s at %p.\n", debug_cs_op(opcode
), packet
);
3333 if (opcode
>= WINED3D_CS_OP_STOP
)
3335 if (opcode
> WINED3D_CS_OP_STOP
)
3336 ERR("Invalid opcode %#x.\n", opcode
);
3340 wined3d_cs_command_lock(cs
);
3341 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3342 wined3d_cs_command_unlock(cs
);
3343 TRACE("%s at %p executed.\n", debug_cs_op(opcode
), packet
);
3346 InterlockedExchange((LONG
*)&queue
->tail
, tail
);
3350 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
)
3352 const struct wined3d_cs_execute_command_list
*op
= data
;
3353 SIZE_T start
= 0, end
= op
->list
->data_size
;
3354 const BYTE
*cs_data
= op
->list
->data
;
3355 struct wined3d_cs_queue
*queue
;
3357 TRACE("Executing command list %p.\n", op
->list
);
3359 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3362 const struct wined3d_cs_packet
*packet
;
3363 enum wined3d_cs_op opcode
;
3365 while (!wined3d_cs_queue_is_empty(cs
, queue
))
3366 wined3d_cs_execute_next(cs
, queue
);
3368 packet
= wined3d_next_cs_packet(cs_data
, &start
, WINED3D_CS_QUEUE_MASK
);
3369 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3371 if (opcode
>= WINED3D_CS_OP_STOP
)
3372 ERR("Invalid opcode %#x.\n", opcode
);
3374 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3375 TRACE("%s executed.\n", debug_cs_op(opcode
));
3379 static DWORD WINAPI
wined3d_cs_run(void *ctx
)
3381 struct wined3d_cs_queue
*queue
;
3382 unsigned int spin_count
= 0;
3383 struct wined3d_cs
*cs
= ctx
;
3384 HMODULE wined3d_module
;
3385 unsigned int poll
= 0;
3388 TRACE("Started.\n");
3389 SetThreadDescription(GetCurrentThread(), L
"wined3d_cs");
3391 /* Copy the module handle to a local variable to avoid racing with the
3392 * thread freeing "cs" before the FreeLibraryAndExitThread() call. */
3393 wined3d_module
= cs
->wined3d_module
;
3395 list_init(&cs
->query_poll_list
);
3396 cs
->thread_id
= GetCurrentThreadId();
3399 if (++poll
== WINED3D_CS_QUERY_POLL_INTERVAL
)
3401 wined3d_cs_command_lock(cs
);
3403 wined3d_cs_command_unlock(cs
);
3407 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3408 if (wined3d_cs_queue_is_empty(cs
, queue
))
3410 queue
= &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
];
3411 if (wined3d_cs_queue_is_empty(cs
, queue
))
3413 if (++spin_count
>= WINED3D_CS_SPIN_COUNT
&& list_empty(&cs
->query_poll_list
))
3414 wined3d_cs_wait_event(cs
);
3420 run
= wined3d_cs_execute_next(cs
, queue
);
3423 cs
->queue
[WINED3D_CS_QUEUE_MAP
].tail
= cs
->queue
[WINED3D_CS_QUEUE_MAP
].head
;
3424 cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].tail
= cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].head
;
3425 TRACE("Stopped.\n");
3426 FreeLibraryAndExitThread(wined3d_module
, 0);
3429 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
,
3430 const enum wined3d_feature_level
*levels
, unsigned int level_count
)
3432 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3433 struct wined3d_cs
*cs
;
3435 if (!(cs
= heap_alloc_zero(sizeof(*cs
))))
3438 if (FAILED(wined3d_state_create(device
, levels
, level_count
, &cs
->c
.state
)))
3444 cs
->c
.ops
= &wined3d_cs_st_ops
;
3445 cs
->c
.device
= device
;
3446 cs
->serialize_commands
= TRACE_ON(d3d_sync
) || wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_SERIALIZE
;
3448 if (cs
->serialize_commands
)
3449 ERR_(d3d_sync
)("Forcing serialization of all command streams.\n");
3451 state_init(&cs
->state
, d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
, cs
->c
.state
->feature_level
);
3453 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
3454 if (!(cs
->data
= heap_alloc(cs
->data_size
)))
3457 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
)
3459 if (!d3d_info
->fences
)
3461 WARN("Disabling CSMT, adapter doesn't support fences.\n");
3462 wined3d_settings
.cs_multithreaded
&= ~WINED3D_CSMT_ENABLE
;
3466 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
3467 && !RtlIsCriticalSectionLockedByThread(NtCurrentTeb()->Peb
->LoaderLock
))
3469 cs
->c
.ops
= &wined3d_cs_mt_ops
;
3471 if (!(cs
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
3473 ERR("Failed to create command stream event.\n");
3474 heap_free(cs
->data
);
3478 if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
3479 (const WCHAR
*)wined3d_cs_run
, &cs
->wined3d_module
)))
3481 ERR("Failed to get wined3d module handle.\n");
3482 CloseHandle(cs
->event
);
3483 heap_free(cs
->data
);
3487 if (!(cs
->thread
= CreateThread(NULL
, 0, wined3d_cs_run
, cs
, 0, NULL
)))
3489 ERR("Failed to create wined3d command stream thread.\n");
3490 FreeLibrary(cs
->wined3d_module
);
3491 CloseHandle(cs
->event
);
3492 heap_free(cs
->data
);
3497 TRACE("Created command stream %p.\n", cs
);
3501 wined3d_state_destroy(cs
->c
.state
);
3502 state_cleanup(&cs
->state
);
3507 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
3511 wined3d_cs_emit_stop(cs
);
3512 CloseHandle(cs
->thread
);
3513 if (!CloseHandle(cs
->event
))
3514 ERR("Closing event failed.\n");
3517 wined3d_state_destroy(cs
->c
.state
);
3518 state_cleanup(&cs
->state
);
3519 heap_free(cs
->data
);
3523 static void wined3d_cs_packet_decref_objects(const struct wined3d_cs_packet
*packet
)
3525 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3530 case WINED3D_CS_OP_SET_SAMPLERS
:
3532 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3534 for (i
= 0; i
< op
->count
; ++i
)
3536 if (op
->samplers
[i
])
3537 wined3d_sampler_decref(op
->samplers
[i
]);
3542 case WINED3D_CS_OP_SET_SHADER
:
3544 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3547 wined3d_shader_decref(op
->shader
);
3551 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3553 struct wined3d_cs_set_depth_stencil_state
*op
;
3555 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3557 wined3d_depth_stencil_state_decref(op
->state
);
3561 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3563 struct wined3d_cs_set_rasterizer_state
*op
;
3565 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3567 wined3d_rasterizer_state_decref(op
->state
);
3571 case WINED3D_CS_OP_SET_BLEND_STATE
:
3573 struct wined3d_cs_set_blend_state
*op
;
3575 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3577 wined3d_blend_state_decref(op
->state
);
3581 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3583 struct wined3d_cs_set_rendertarget_views
*op
;
3585 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3586 for (i
= 0; i
< op
->count
; ++i
)
3589 wined3d_rendertarget_view_decref(op
->views
[i
]);
3594 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3596 struct wined3d_cs_set_shader_resource_views
*op
;
3598 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3599 for (i
= 0; i
< op
->count
; ++i
)
3602 wined3d_shader_resource_view_decref(op
->views
[i
]);
3607 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3609 struct wined3d_cs_set_unordered_access_views
*op
;
3611 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3612 for (i
= 0; i
< op
->count
; ++i
)
3614 if (op
->uavs
[i
].view
)
3615 wined3d_unordered_access_view_decref(op
->uavs
[i
].view
);
3620 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3622 struct wined3d_cs_set_depth_stencil_view
*op
;
3624 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3626 wined3d_rendertarget_view_decref(op
->view
);
3630 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3632 struct wined3d_cs_set_constant_buffers
*op
;
3634 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3635 for (i
= 0; i
< op
->count
; ++i
)
3637 if (op
->buffers
[i
].buffer
)
3638 wined3d_buffer_decref(op
->buffers
[i
].buffer
);
3643 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3645 struct wined3d_cs_clear_unordered_access_view
*op
;
3647 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3648 wined3d_unordered_access_view_decref(op
->view
);
3652 case WINED3D_CS_OP_CLEAR
:
3654 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3656 for (i
= 0; i
< op
->rt_count
; ++i
)
3658 if (op
->fb
.render_targets
[i
])
3659 wined3d_rendertarget_view_decref(op
->fb
.render_targets
[i
]);
3661 if (op
->fb
.depth_stencil
)
3662 wined3d_rendertarget_view_decref(op
->fb
.depth_stencil
);
3666 case WINED3D_CS_OP_DISPATCH
:
3668 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3670 if (op
->parameters
.indirect
)
3671 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3675 case WINED3D_CS_OP_DRAW
:
3677 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3679 if (op
->parameters
.indirect
)
3680 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3684 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3686 struct wined3d_cs_set_index_buffer
*op
;
3688 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3690 wined3d_buffer_decref(op
->buffer
);
3694 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3696 struct wined3d_cs_set_stream_outputs
*op
;
3698 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3699 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3701 if (op
->outputs
[i
].buffer
)
3702 wined3d_buffer_decref(op
->outputs
[i
].buffer
);
3707 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3709 struct wined3d_cs_set_stream_sources
*op
;
3711 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3712 for (i
= 0; i
< op
->count
; ++i
)
3714 if (op
->streams
[i
].buffer
)
3715 wined3d_buffer_decref(op
->streams
[i
].buffer
);
3720 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3722 struct wined3d_cs_update_sub_resource
*op
;
3724 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3725 wined3d_resource_decref(op
->resource
);
3729 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3731 struct wined3d_cs_blt_sub_resource
*op
;
3733 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
3734 if (op
->src_resource
)
3735 wined3d_resource_decref(op
->src_resource
);
3736 wined3d_resource_decref(op
->dst_resource
);
3740 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
3742 struct wined3d_cs_copy_uav_counter
*op
;
3744 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
3745 wined3d_buffer_decref(op
->buffer
);
3746 wined3d_unordered_access_view_decref(op
->view
);
3750 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
3752 struct wined3d_cs_generate_mipmaps
*op
;
3754 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
3755 wined3d_shader_resource_view_decref(op
->view
);
3764 static void wined3d_cs_packet_incref_objects(struct wined3d_cs_packet
*packet
)
3766 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3771 case WINED3D_CS_OP_SET_SAMPLERS
:
3773 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3775 for (i
= 0; i
< op
->count
; ++i
)
3777 if (op
->samplers
[i
])
3778 wined3d_sampler_incref(op
->samplers
[i
]);
3783 case WINED3D_CS_OP_SET_SHADER
:
3785 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3788 wined3d_shader_incref(op
->shader
);
3792 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3794 struct wined3d_cs_set_depth_stencil_state
*op
;
3796 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3798 wined3d_depth_stencil_state_incref(op
->state
);
3802 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3804 struct wined3d_cs_set_rasterizer_state
*op
;
3806 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3808 wined3d_rasterizer_state_incref(op
->state
);
3812 case WINED3D_CS_OP_SET_BLEND_STATE
:
3814 struct wined3d_cs_set_blend_state
*op
;
3816 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3818 wined3d_blend_state_incref(op
->state
);
3822 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3824 struct wined3d_cs_set_rendertarget_views
*op
;
3826 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3827 for (i
= 0; i
< op
->count
; ++i
)
3830 wined3d_rendertarget_view_incref(op
->views
[i
]);
3835 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3837 struct wined3d_cs_set_shader_resource_views
*op
;
3839 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3840 for (i
= 0; i
< op
->count
; ++i
)
3843 wined3d_shader_resource_view_incref(op
->views
[i
]);
3848 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3850 struct wined3d_cs_set_unordered_access_views
*op
;
3852 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3853 for (i
= 0; i
< op
->count
; ++i
)
3855 if (op
->uavs
[i
].view
)
3856 wined3d_unordered_access_view_incref(op
->uavs
[i
].view
);
3861 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3863 struct wined3d_cs_set_depth_stencil_view
*op
;
3865 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3867 wined3d_rendertarget_view_incref(op
->view
);
3871 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3873 struct wined3d_cs_set_constant_buffers
*op
;
3875 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3876 for (i
= 0; i
< op
->count
; ++i
)
3878 if (op
->buffers
[i
].buffer
)
3879 wined3d_buffer_incref(op
->buffers
[i
].buffer
);
3884 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3886 struct wined3d_cs_clear_unordered_access_view
*op
;
3888 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3889 wined3d_unordered_access_view_incref(op
->view
);
3893 case WINED3D_CS_OP_CLEAR
:
3895 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3897 for (i
= 0; i
< op
->rt_count
; ++i
)
3899 if (op
->fb
.render_targets
[i
])
3900 wined3d_rendertarget_view_incref(op
->fb
.render_targets
[i
]);
3902 if (op
->fb
.depth_stencil
)
3903 wined3d_rendertarget_view_incref(op
->fb
.depth_stencil
);
3907 case WINED3D_CS_OP_DISPATCH
:
3909 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3911 if (op
->parameters
.indirect
)
3912 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3916 case WINED3D_CS_OP_DRAW
:
3918 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3920 if (op
->parameters
.indirect
)
3921 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3925 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3927 struct wined3d_cs_set_index_buffer
*op
;
3929 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3931 wined3d_buffer_incref(op
->buffer
);
3935 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3937 struct wined3d_cs_set_stream_outputs
*op
;
3939 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3940 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3942 if (op
->outputs
[i
].buffer
)
3943 wined3d_buffer_incref(op
->outputs
[i
].buffer
);
3948 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3950 struct wined3d_cs_set_stream_sources
*op
;
3952 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3953 for (i
= 0; i
< op
->count
; ++i
)
3955 if (op
->streams
[i
].buffer
)
3956 wined3d_buffer_incref(op
->streams
[i
].buffer
);
3961 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3963 struct wined3d_cs_update_sub_resource
*op
;
3965 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3966 wined3d_resource_incref(op
->resource
);
3970 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3972 struct wined3d_cs_blt_sub_resource
*op
;
3974 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
3975 if (op
->src_resource
)
3976 wined3d_resource_incref(op
->src_resource
);
3977 wined3d_resource_incref(op
->dst_resource
);
3981 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
3983 struct wined3d_cs_copy_uav_counter
*op
;
3985 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
3986 wined3d_buffer_incref(op
->buffer
);
3987 wined3d_unordered_access_view_incref(op
->view
);
3991 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
3993 struct wined3d_cs_generate_mipmaps
*op
;
3995 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
3996 wined3d_shader_resource_view_incref(op
->view
);
4005 struct wined3d_deferred_context
4007 struct wined3d_device_context c
;
4009 SIZE_T data_size
, data_capacity
;
4012 SIZE_T resource_count
, resources_capacity
;
4013 struct wined3d_resource
**resources
;
4015 SIZE_T upload_count
, uploads_capacity
;
4016 struct wined3d_deferred_upload
*uploads
;
4019 LONG
*upload_heap_refcount
;
4021 /* List of command lists queued for execution on this context. A command
4022 * list can be the only thing holding a pointer to another command list, so
4023 * we need to hold a reference here and in wined3d_command_list as well. */
4024 SIZE_T command_list_count
, command_lists_capacity
;
4025 struct wined3d_command_list
**command_lists
;
4027 SIZE_T query_count
, queries_capacity
;
4028 struct wined3d_deferred_query_issue
*queries
;
4031 static struct wined3d_deferred_context
*wined3d_deferred_context_from_context(struct wined3d_device_context
*context
)
4033 return CONTAINING_RECORD(context
, struct wined3d_deferred_context
, c
);
4036 static void *wined3d_deferred_context_require_space(struct wined3d_device_context
*context
,
4037 size_t size
, enum wined3d_cs_queue_id queue_id
)
4039 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4040 struct wined3d_cs_packet
*packet
;
4041 size_t header_size
, packet_size
;
4043 if (queue_id
!= WINED3D_CS_QUEUE_DEFAULT
)
4046 header_size
= offsetof(struct wined3d_cs_packet
, data
[0]);
4047 packet_size
= offsetof(struct wined3d_cs_packet
, data
[size
]);
4048 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
4050 if (!wined3d_array_reserve(&deferred
->data
, &deferred
->data_capacity
, deferred
->data_size
+ packet_size
, 1))
4053 packet
= (struct wined3d_cs_packet
*)((BYTE
*)deferred
->data
+ deferred
->data_size
);
4054 TRACE("size was %Iu, adding %Iu\n", (size_t)deferred
->data_size
, packet_size
);
4055 packet
->size
= packet_size
- header_size
;
4056 return &packet
->data
;
4059 static void wined3d_deferred_context_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4061 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4062 struct wined3d_cs_packet
*packet
;
4064 assert(queue_id
== WINED3D_CS_QUEUE_DEFAULT
);
4065 packet
= wined3d_next_cs_packet(deferred
->data
, &deferred
->data_size
, ~(SIZE_T
)0);
4066 wined3d_cs_packet_incref_objects(packet
);
4069 static void wined3d_deferred_context_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4071 /* This should not happen; we cannot meaningfully finish a deferred context. */
4072 ERR("Ignoring finish() on a deferred context.\n");
4075 static void wined3d_deferred_context_push_constants(struct wined3d_device_context
*context
,
4076 enum wined3d_push_constants p
, unsigned int start_idx
, unsigned int count
, const void *constants
)
4078 FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context
, p
, start_idx
, count
, constants
);
4081 static struct wined3d_deferred_upload
*deferred_context_get_upload(struct wined3d_deferred_context
*deferred
,
4082 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
4084 SIZE_T i
= deferred
->upload_count
;
4088 struct wined3d_deferred_upload
*upload
= &deferred
->uploads
[i
];
4090 if (upload
->resource
== resource
&& upload
->sub_resource_idx
== sub_resource_idx
)
4097 static bool wined3d_deferred_context_map_upload_bo(struct wined3d_device_context
*context
,
4098 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
4099 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
4101 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4102 const struct wined3d_format
*format
= resource
->format
;
4103 struct wined3d_deferred_upload
*upload
;
4107 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
4108 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
4110 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
4111 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
4112 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
4114 if (!(flags
& WINED3D_MAP_WRITE
))
4116 WARN("Flags %#x are not valid on a deferred context.\n", flags
);
4120 if (flags
& ~(WINED3D_MAP_WRITE
| WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
4122 FIXME("Unhandled flags %#x.\n", flags
);
4126 if (flags
& WINED3D_MAP_NOOVERWRITE
)
4128 if (!(upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4131 upload
->upload_flags
= 0;
4132 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4136 if (!wined3d_array_reserve((void **)&deferred
->uploads
, &deferred
->uploads_capacity
,
4137 deferred
->upload_count
+ 1, sizeof(*deferred
->uploads
)))
4140 if (!deferred
->upload_heap
)
4142 if (!(deferred
->upload_heap
= HeapCreate(0, 0, 0)))
4144 ERR("Failed to create upload heap.\n");
4148 if (!(deferred
->upload_heap_refcount
= heap_alloc(sizeof(*deferred
->upload_heap_refcount
))))
4150 HeapDestroy(deferred
->upload_heap
);
4151 deferred
->upload_heap
= 0;
4155 *deferred
->upload_heap_refcount
= 1;
4158 if (!(sysmem
= HeapAlloc(deferred
->upload_heap
, 0, size
+ RESOURCE_ALIGNMENT
- 1)))
4161 upload
= &deferred
->uploads
[deferred
->upload_count
++];
4162 upload
->upload_flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
;
4163 upload
->resource
= resource
;
4164 wined3d_resource_incref(resource
);
4165 upload
->sub_resource_idx
= sub_resource_idx
;
4166 upload
->sysmem
= sysmem
;
4169 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4173 static bool wined3d_deferred_context_unmap_upload_bo(struct wined3d_device_context
*context
,
4174 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*bo
)
4176 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4177 const struct wined3d_deferred_upload
*upload
;
4179 if ((upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4182 bo
->addr
.buffer_object
= 0;
4183 bo
->addr
.addr
= (uint8_t *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4184 bo
->flags
= upload
->upload_flags
;
4191 static void wined3d_deferred_context_issue_query(struct wined3d_device_context
*context
,
4192 struct wined3d_query
*query
, unsigned int flags
)
4194 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4195 struct wined3d_cs_query_issue
*op
;
4197 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
4198 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
4202 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
4204 if (!wined3d_array_reserve((void **)&deferred
->queries
, &deferred
->queries_capacity
,
4205 deferred
->query_count
+ 1, sizeof(*deferred
->queries
)))
4207 ERR("Failed to reserve memory.\n");
4211 deferred
->queries
[deferred
->query_count
].flags
= flags
;
4212 wined3d_query_incref(deferred
->queries
[deferred
->query_count
++].query
= query
);
4215 static void wined3d_deferred_context_flush(struct wined3d_device_context
*context
)
4217 FIXME("context %p, stub!\n", context
);
4220 static void wined3d_deferred_context_reference_resource(struct wined3d_device_context
*context
,
4221 struct wined3d_resource
*resource
)
4223 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4225 if (!wined3d_array_reserve((void **)&deferred
->resources
, &deferred
->resources_capacity
,
4226 deferred
->resource_count
+ 1, sizeof(*deferred
->resources
)))
4229 deferred
->resources
[deferred
->resource_count
++] = resource
;
4230 wined3d_resource_incref(resource
);
4233 static void wined3d_deferred_context_reference_command_list(struct wined3d_device_context
*context
,
4234 struct wined3d_command_list
*list
)
4236 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4238 /* Grab a reference to the command list. Note that this implicitly prevents
4239 * any dependent command lists or resources from being freed as well. */
4240 if (!wined3d_array_reserve((void **)&deferred
->command_lists
, &deferred
->command_lists_capacity
,
4241 deferred
->command_list_count
+ 1, sizeof(*deferred
->command_lists
)))
4244 wined3d_command_list_incref(deferred
->command_lists
[deferred
->command_list_count
++] = list
);
4247 static const struct wined3d_device_context_ops wined3d_deferred_context_ops
=
4249 wined3d_deferred_context_require_space
,
4250 wined3d_deferred_context_submit
,
4251 wined3d_deferred_context_finish
,
4252 wined3d_deferred_context_push_constants
,
4253 wined3d_deferred_context_map_upload_bo
,
4254 wined3d_deferred_context_unmap_upload_bo
,
4255 wined3d_deferred_context_issue_query
,
4256 wined3d_deferred_context_flush
,
4257 wined3d_deferred_context_reference_resource
,
4258 wined3d_deferred_context_reference_command_list
,
4261 HRESULT CDECL
wined3d_deferred_context_create(struct wined3d_device
*device
, struct wined3d_device_context
**context
)
4263 struct wined3d_deferred_context
*object
;
4266 TRACE("device %p, context %p.\n", device
, context
);
4268 if (!(object
= heap_alloc_zero(sizeof(*object
))))
4269 return E_OUTOFMEMORY
;
4271 if (FAILED(hr
= wined3d_state_create(device
, &device
->cs
->c
.state
->feature_level
, 1, &object
->c
.state
)))
4277 object
->c
.ops
= &wined3d_deferred_context_ops
;
4278 object
->c
.device
= device
;
4280 /* Make sure the first command list gets the state reset when executed.
4281 * Resets for subsequent command lists are encoded in wined3d_deferred_context_record_command_list(). */
4282 wined3d_device_context_emit_reset_state(&object
->c
, true);
4284 TRACE("Created deferred context %p.\n", object
);
4285 *context
= &object
->c
;
4290 void CDECL
wined3d_deferred_context_destroy(struct wined3d_device_context
*context
)
4292 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4293 const struct wined3d_cs_packet
*packet
;
4294 SIZE_T i
, offset
= 0;
4296 TRACE("context %p.\n", context
);
4298 for (i
= 0; i
< deferred
->resource_count
; ++i
)
4299 wined3d_resource_decref(deferred
->resources
[i
]);
4300 heap_free(deferred
->resources
);
4302 for (i
= 0; i
< deferred
->upload_count
; ++i
)
4304 wined3d_resource_decref(deferred
->uploads
[i
].resource
);
4305 HeapFree(deferred
->upload_heap
, 0, deferred
->uploads
[i
].resource
);
4308 if (deferred
->upload_heap
)
4310 if (!InterlockedDecrement(deferred
->upload_heap_refcount
))
4312 HeapDestroy(deferred
->upload_heap
);
4313 heap_free(deferred
->upload_heap_refcount
);
4317 heap_free(deferred
->uploads
);
4319 for (i
= 0; i
< deferred
->command_list_count
; ++i
)
4320 wined3d_command_list_decref(deferred
->command_lists
[i
]);
4321 heap_free(deferred
->command_lists
);
4323 for (i
= 0; i
< deferred
->query_count
; ++i
)
4324 wined3d_query_decref(deferred
->queries
[i
].query
);
4325 heap_free(deferred
->queries
);
4327 while (offset
< deferred
->data_size
)
4329 packet
= wined3d_next_cs_packet(deferred
->data
, &offset
, ~(SIZE_T
)0);
4330 wined3d_cs_packet_decref_objects(packet
);
4333 wined3d_state_destroy(deferred
->c
.state
);
4334 heap_free(deferred
->data
);
4335 heap_free(deferred
);
4338 HRESULT CDECL
wined3d_deferred_context_record_command_list(struct wined3d_device_context
*context
,
4339 bool restore
, struct wined3d_command_list
**list
)
4341 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4342 struct wined3d_command_list
*object
;
4345 TRACE("context %p, list %p.\n", context
, list
);
4347 wined3d_device_context_lock(context
);
4348 memory
= heap_alloc(sizeof(*object
) + deferred
->resource_count
* sizeof(*object
->resources
)
4349 + deferred
->upload_count
* sizeof(*object
->uploads
)
4350 + deferred
->command_list_count
* sizeof(*object
->command_lists
)
4351 + deferred
->query_count
* sizeof(*object
->queries
)
4352 + deferred
->data_size
);
4356 wined3d_device_context_unlock(context
);
4357 return E_OUTOFMEMORY
;
4361 memory
= &object
[1];
4362 memset(object
, 0, sizeof(*object
));
4363 object
->refcount
= 1;
4364 object
->device
= deferred
->c
.device
;
4366 object
->resources
= memory
;
4367 memory
= &object
->resources
[deferred
->resource_count
];
4368 object
->resource_count
= deferred
->resource_count
;
4369 memcpy(object
->resources
, deferred
->resources
, deferred
->resource_count
* sizeof(*object
->resources
));
4370 /* Transfer our references to the resources to the command list. */
4372 object
->uploads
= memory
;
4373 memory
= &object
->uploads
[deferred
->upload_count
];
4374 object
->upload_count
= deferred
->upload_count
;
4375 memcpy(object
->uploads
, deferred
->uploads
, deferred
->upload_count
* sizeof(*object
->uploads
));
4376 /* Transfer our references to the resources to the command list. */
4378 object
->command_lists
= memory
;
4379 memory
= &object
->command_lists
[deferred
->command_list_count
];
4380 object
->command_list_count
= deferred
->command_list_count
;
4381 memcpy(object
->command_lists
, deferred
->command_lists
,
4382 deferred
->command_list_count
* sizeof(*object
->command_lists
));
4383 /* Transfer our references to the command lists to the command list. */
4385 object
->queries
= memory
;
4386 memory
= &object
->queries
[deferred
->query_count
];
4387 object
->query_count
= deferred
->query_count
;
4388 memcpy(object
->queries
, deferred
->queries
, deferred
->query_count
* sizeof(*object
->queries
));
4389 /* Transfer our references to the queries to the command list. */
4391 object
->data
= memory
;
4392 object
->data_size
= deferred
->data_size
;
4393 memcpy(object
->data
, deferred
->data
, deferred
->data_size
);
4395 deferred
->data_size
= 0;
4396 deferred
->resource_count
= 0;
4397 deferred
->upload_count
= 0;
4398 deferred
->command_list_count
= 0;
4399 deferred
->query_count
= 0;
4401 object
->upload_heap
= deferred
->upload_heap
;
4402 if ((object
->upload_heap_refcount
= deferred
->upload_heap_refcount
))
4403 InterlockedIncrement(object
->upload_heap_refcount
);
4405 /* This is in fact recorded into a subsequent command list. */
4407 wined3d_device_context_set_state(&deferred
->c
, deferred
->c
.state
);
4409 wined3d_device_context_reset_state(&deferred
->c
);
4411 TRACE("Created command list %p.\n", object
);
4413 wined3d_device_context_unlock(context
);
4418 static void wined3d_command_list_destroy_object(void *object
)
4420 struct wined3d_command_list
*list
= object
;
4423 TRACE("list %p.\n", list
);
4425 for (i
= 0; i
< list
->upload_count
; ++i
)
4426 HeapFree(list
->upload_heap
, 0, list
->uploads
[i
].sysmem
);
4428 if (list
->upload_heap
)
4430 if (!InterlockedDecrement(list
->upload_heap_refcount
))
4432 HeapDestroy(list
->upload_heap
);
4433 heap_free(list
->upload_heap_refcount
);
4440 ULONG CDECL
wined3d_command_list_incref(struct wined3d_command_list
*list
)
4442 unsigned int refcount
= InterlockedIncrement(&list
->refcount
);
4444 TRACE("%p increasing refcount to %u.\n", list
, refcount
);
4449 ULONG CDECL
wined3d_command_list_decref(struct wined3d_command_list
*list
)
4451 unsigned int refcount
= InterlockedDecrement(&list
->refcount
);
4452 struct wined3d_device
*device
= list
->device
;
4453 const struct wined3d_cs_packet
*packet
;
4456 TRACE("%p decreasing refcount to %u.\n", list
, refcount
);
4460 for (i
= 0; i
< list
->command_list_count
; ++i
)
4461 wined3d_command_list_decref(list
->command_lists
[i
]);
4462 for (i
= 0; i
< list
->resource_count
; ++i
)
4463 wined3d_resource_decref(list
->resources
[i
]);
4464 for (i
= 0; i
< list
->upload_count
; ++i
)
4465 wined3d_resource_decref(list
->uploads
[i
].resource
);
4466 for (i
= 0; i
< list
->query_count
; ++i
)
4467 wined3d_query_decref(list
->queries
[i
].query
);
4470 while (offset
< list
->data_size
)
4472 packet
= wined3d_next_cs_packet(list
->data
, &offset
, ~(SIZE_T
)0);
4473 wined3d_cs_packet_decref_objects(packet
);
4476 wined3d_mutex_lock();
4477 wined3d_cs_destroy_object(device
->cs
, wined3d_command_list_destroy_object
, list
);
4478 wined3d_mutex_unlock();