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
);
727 if (InterlockedCompareExchange(&cs
->waiting_for_present
, FALSE
, TRUE
))
728 SetEvent(cs
->present_event
);
731 void wined3d_cs_emit_present(struct wined3d_cs
*cs
, struct wined3d_swapchain
*swapchain
,
732 const RECT
*src_rect
, const RECT
*dst_rect
, HWND dst_window_override
,
733 unsigned int swap_interval
, uint32_t flags
)
735 struct wined3d_cs_present
*op
;
739 wined3d_not_from_cs(cs
);
741 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
742 op
->opcode
= WINED3D_CS_OP_PRESENT
;
743 op
->dst_window_override
= dst_window_override
;
744 op
->swapchain
= swapchain
;
745 op
->src_rect
= *src_rect
;
746 op
->dst_rect
= *dst_rect
;
747 op
->swap_interval
= swap_interval
;
750 pending
= InterlockedIncrement(&cs
->pending_presents
);
752 wined3d_resource_reference(&swapchain
->front_buffer
->resource
);
753 for (i
= 0; i
< swapchain
->state
.desc
.backbuffer_count
; ++i
)
755 wined3d_resource_reference(&swapchain
->back_buffers
[i
]->resource
);
758 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
760 /* Limit input latency by limiting the number of presents that we can get
761 * ahead of the worker thread. */
762 while (pending
>= swapchain
->max_frame_latency
)
764 InterlockedExchange(&cs
->waiting_for_present
, TRUE
);
766 pending
= InterlockedCompareExchange(&cs
->pending_presents
, 0, 0);
767 if (pending
>= swapchain
->max_frame_latency
|| !InterlockedCompareExchange(&cs
->waiting_for_present
, FALSE
, TRUE
))
769 TRACE_(d3d_perf
)("Reached latency limit (%u frames), blocking to wait.\n", swapchain
->max_frame_latency
);
770 wined3d_mutex_unlock();
771 WaitForSingleObject(cs
->present_event
, INFINITE
);
772 wined3d_mutex_lock();
773 TRACE_(d3d_perf
)("Woken up from the wait.\n");
778 static void wined3d_cs_exec_clear(struct wined3d_cs
*cs
, const void *data
)
780 struct wined3d_device
*device
= cs
->c
.device
;
781 const struct wined3d_cs_clear
*op
= data
;
783 device
->blitter
->ops
->blitter_clear(device
->blitter
, device
, op
->rt_count
, &op
->fb
,
784 op
->rect_count
, op
->rects
, &op
->draw_rect
, op
->flags
, &op
->color
, op
->depth
, op
->stencil
);
787 void wined3d_cs_emit_clear(struct wined3d_cs
*cs
, DWORD rect_count
, const RECT
*rects
,
788 uint32_t flags
, const struct wined3d_color
*color
, float depth
, DWORD stencil
)
790 const struct wined3d_state
*state
= cs
->c
.state
;
791 const struct wined3d_viewport
*vp
= &state
->viewports
[0];
792 struct wined3d_rendertarget_view
*view
;
793 struct wined3d_cs_clear
*op
;
794 unsigned int rt_count
, i
;
796 rt_count
= flags
& WINED3DCLEAR_TARGET
? cs
->c
.device
->adapter
->d3d_info
.limits
.max_rt_count
: 0;
798 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_clear
, rects
[rect_count
]),
799 WINED3D_CS_QUEUE_DEFAULT
);
800 op
->opcode
= WINED3D_CS_OP_CLEAR
;
801 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
802 op
->rt_count
= rt_count
;
804 SetRect(&op
->draw_rect
, vp
->x
, vp
->y
, vp
->x
+ vp
->width
, vp
->y
+ vp
->height
);
805 if (state
->rasterizer_state
&& state
->rasterizer_state
->desc
.scissor
)
806 IntersectRect(&op
->draw_rect
, &op
->draw_rect
, &state
->scissor_rects
[0]);
809 op
->stencil
= stencil
;
810 op
->rect_count
= rect_count
;
811 memcpy(op
->rects
, rects
, sizeof(*rects
) * rect_count
);
813 for (i
= 0; i
< rt_count
; ++i
)
815 if ((view
= state
->fb
.render_targets
[i
]))
816 wined3d_resource_reference(view
->resource
);
818 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
820 view
= state
->fb
.depth_stencil
;
821 wined3d_resource_reference(view
->resource
);
824 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
827 void wined3d_device_context_emit_clear_rendertarget_view(struct wined3d_device_context
*context
,
828 struct wined3d_rendertarget_view
*view
, const RECT
*rect
, unsigned int flags
,
829 const struct wined3d_color
*color
, float depth
, unsigned int stencil
)
831 struct wined3d_cs_clear
*op
;
834 size
= FIELD_OFFSET(struct wined3d_cs_clear
, rects
[1]);
835 op
= wined3d_device_context_require_space(context
, size
, WINED3D_CS_QUEUE_DEFAULT
);
837 op
->opcode
= WINED3D_CS_OP_CLEAR
;
838 op
->flags
= flags
& (WINED3DCLEAR_TARGET
| WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
839 if (flags
& WINED3DCLEAR_TARGET
)
842 op
->fb
.render_targets
[0] = view
;
843 op
->fb
.depth_stencil
= NULL
;
849 op
->fb
.render_targets
[0] = NULL
;
850 op
->fb
.depth_stencil
= view
;
852 op
->stencil
= stencil
;
854 SetRect(&op
->draw_rect
, 0, 0, view
->width
, view
->height
);
856 op
->rects
[0] = *rect
;
858 wined3d_device_context_reference_resource(context
, view
->resource
);
860 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
861 if (flags
& WINED3DCLEAR_SYNCHRONOUS
)
862 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
865 static void reference_shader_resources(struct wined3d_device_context
*context
, unsigned int shader_mask
)
867 const struct wined3d_state
*state
= context
->state
;
868 struct wined3d_shader_sampler_map_entry
*entry
;
869 struct wined3d_shader_resource_view
*view
;
870 struct wined3d_shader
*shader
;
873 for (i
= 0; i
< WINED3D_SHADER_TYPE_COUNT
; ++i
)
875 if (!(shader_mask
& (1u << i
)))
878 if (!(shader
= state
->shader
[i
]))
881 for (j
= 0; j
< WINED3D_MAX_CBS
; ++j
)
883 if (state
->cb
[i
][j
].buffer
)
884 wined3d_device_context_reference_resource(context
, &state
->cb
[i
][j
].buffer
->resource
);
887 for (j
= 0; j
< shader
->reg_maps
.sampler_map
.count
; ++j
)
889 entry
= &shader
->reg_maps
.sampler_map
.entries
[j
];
891 if (!(view
= state
->shader_resource_view
[i
][entry
->resource_idx
]))
894 wined3d_device_context_reference_resource(context
, view
->resource
);
899 static void reference_unordered_access_resources(struct wined3d_device_context
*context
,
900 const struct wined3d_shader
*shader
, struct wined3d_unordered_access_view
* const *views
)
907 for (i
= 0; i
< MAX_UNORDERED_ACCESS_VIEWS
; ++i
)
909 if (!shader
->reg_maps
.uav_resource_info
[i
].type
)
915 wined3d_device_context_reference_resource(context
, views
[i
]->resource
);
919 static void wined3d_cs_exec_dispatch(struct wined3d_cs
*cs
, const void *data
)
921 const struct wined3d_cs_dispatch
*op
= data
;
922 struct wined3d_state
*state
= &cs
->state
;
924 if (!state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
])
925 WARN("No compute shader bound, skipping dispatch.\n");
927 cs
->c
.device
->adapter
->adapter_ops
->adapter_dispatch_compute(cs
->c
.device
, state
, &op
->parameters
);
930 static void reference_compute_pipeline_resources(struct wined3d_device_context
*context
)
932 const struct wined3d_state
*state
= context
->state
;
934 reference_shader_resources(context
, 1u << WINED3D_SHADER_TYPE_COMPUTE
);
935 reference_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_COMPUTE
],
936 state
->unordered_access_view
[WINED3D_PIPELINE_COMPUTE
]);
939 void CDECL
wined3d_device_context_dispatch(struct wined3d_device_context
*context
,
940 unsigned int group_count_x
, unsigned int group_count_y
, unsigned int group_count_z
)
942 struct wined3d_cs_dispatch
*op
;
944 wined3d_device_context_lock(context
);
945 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
946 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
947 op
->parameters
.indirect
= FALSE
;
948 op
->parameters
.u
.direct
.group_count_x
= group_count_x
;
949 op
->parameters
.u
.direct
.group_count_y
= group_count_y
;
950 op
->parameters
.u
.direct
.group_count_z
= group_count_z
;
952 reference_compute_pipeline_resources(context
);
954 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
955 wined3d_device_context_unlock(context
);
958 void CDECL
wined3d_device_context_dispatch_indirect(struct wined3d_device_context
*context
,
959 struct wined3d_buffer
*buffer
, unsigned int offset
)
961 struct wined3d_cs_dispatch
*op
;
963 wined3d_device_context_lock(context
);
964 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
965 op
->opcode
= WINED3D_CS_OP_DISPATCH
;
966 op
->parameters
.indirect
= TRUE
;
967 op
->parameters
.u
.indirect
.buffer
= buffer
;
968 op
->parameters
.u
.indirect
.offset
= offset
;
970 reference_compute_pipeline_resources(context
);
971 wined3d_device_context_reference_resource(context
, &buffer
->resource
);
973 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
974 wined3d_device_context_unlock(context
);
977 static void wined3d_cs_exec_draw(struct wined3d_cs
*cs
, const void *data
)
979 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
980 const struct wined3d_shader
*geometry_shader
;
981 struct wined3d_device
*device
= cs
->c
.device
;
982 int base_vertex_idx
, load_base_vertex_idx
;
983 struct wined3d_state
*state
= &cs
->state
;
984 const struct wined3d_cs_draw
*op
= data
;
988 if (!op
->parameters
.indirect
)
990 const struct wined3d_direct_draw_parameters
*direct
= &op
->parameters
.u
.direct
;
992 if (op
->parameters
.indexed
&& d3d_info
->draw_base_vertex_offset
)
993 base_vertex_idx
= direct
->base_vertex_idx
;
994 else if (!op
->parameters
.indexed
)
995 base_vertex_idx
= direct
->start_idx
;
998 /* ARB_draw_indirect always supports a base vertex offset. */
999 if (!op
->parameters
.indirect
&& !d3d_info
->draw_base_vertex_offset
)
1000 load_base_vertex_idx
= op
->parameters
.u
.direct
.base_vertex_idx
;
1002 load_base_vertex_idx
= 0;
1004 if (state
->base_vertex_index
!= base_vertex_idx
)
1006 state
->base_vertex_index
= base_vertex_idx
;
1007 for (i
= 0; i
< device
->context_count
; ++i
)
1008 device
->contexts
[i
]->constant_update_mask
|= WINED3D_SHADER_CONST_BASE_VERTEX_ID
;
1011 if (state
->load_base_vertex_index
!= load_base_vertex_idx
)
1013 state
->load_base_vertex_index
= load_base_vertex_idx
;
1014 device_invalidate_state(cs
->c
.device
, STATE_BASEVERTEXINDEX
);
1017 if (state
->primitive_type
!= op
->primitive_type
)
1019 if ((geometry_shader
= state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]) && !geometry_shader
->function
)
1020 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
));
1021 if (state
->primitive_type
== WINED3D_PT_POINTLIST
|| op
->primitive_type
== WINED3D_PT_POINTLIST
)
1022 device_invalidate_state(cs
->c
.device
, STATE_POINT_ENABLE
);
1023 state
->primitive_type
= op
->primitive_type
;
1025 state
->patch_vertex_count
= op
->patch_vertex_count
;
1027 cs
->c
.device
->adapter
->adapter_ops
->adapter_draw_primitive(cs
->c
.device
, state
, &op
->parameters
);
1030 static void reference_graphics_pipeline_resources(struct wined3d_device_context
*context
,
1031 BOOL indexed
, const struct wined3d_d3d_info
*d3d_info
)
1033 const struct wined3d_state
*state
= context
->state
;
1037 wined3d_device_context_reference_resource(context
, &state
->index_buffer
->resource
);
1038 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
1040 if (state
->streams
[i
].buffer
)
1041 wined3d_device_context_reference_resource(context
, &state
->streams
[i
].buffer
->resource
);
1043 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
1045 if (state
->stream_output
[i
].buffer
)
1046 wined3d_device_context_reference_resource(context
, &state
->stream_output
[i
].buffer
->resource
);
1048 for (i
= 0; i
< ARRAY_SIZE(state
->textures
); ++i
)
1050 if (state
->textures
[i
])
1051 wined3d_device_context_reference_resource(context
, &state
->textures
[i
]->resource
);
1053 for (i
= 0; i
< d3d_info
->limits
.max_rt_count
; ++i
)
1055 if (state
->fb
.render_targets
[i
])
1056 wined3d_device_context_reference_resource(context
, state
->fb
.render_targets
[i
]->resource
);
1058 if (state
->fb
.depth_stencil
)
1059 wined3d_device_context_reference_resource(context
, state
->fb
.depth_stencil
->resource
);
1060 reference_shader_resources(context
, ~(1u << WINED3D_SHADER_TYPE_COMPUTE
));
1061 reference_unordered_access_resources(context
, state
->shader
[WINED3D_SHADER_TYPE_PIXEL
],
1062 state
->unordered_access_view
[WINED3D_PIPELINE_GRAPHICS
]);
1065 void wined3d_device_context_emit_draw(struct wined3d_device_context
*context
,
1066 enum wined3d_primitive_type primitive_type
, unsigned int patch_vertex_count
, int base_vertex_idx
,
1067 unsigned int start_idx
, unsigned int index_count
, unsigned int start_instance
, unsigned int instance_count
,
1070 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1071 struct wined3d_cs_draw
*op
;
1073 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1074 op
->opcode
= WINED3D_CS_OP_DRAW
;
1075 op
->primitive_type
= primitive_type
;
1076 op
->patch_vertex_count
= patch_vertex_count
;
1077 op
->parameters
.indirect
= FALSE
;
1078 op
->parameters
.u
.direct
.base_vertex_idx
= base_vertex_idx
;
1079 op
->parameters
.u
.direct
.start_idx
= start_idx
;
1080 op
->parameters
.u
.direct
.index_count
= index_count
;
1081 op
->parameters
.u
.direct
.start_instance
= start_instance
;
1082 op
->parameters
.u
.direct
.instance_count
= instance_count
;
1083 op
->parameters
.indexed
= indexed
;
1085 reference_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1087 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1090 void CDECL
wined3d_device_context_draw_indirect(struct wined3d_device_context
*context
,
1091 struct wined3d_buffer
*buffer
, unsigned int offset
, bool indexed
)
1093 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
1094 const struct wined3d_state
*state
= context
->state
;
1095 struct wined3d_cs_draw
*op
;
1097 wined3d_device_context_lock(context
);
1098 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1099 op
->opcode
= WINED3D_CS_OP_DRAW
;
1100 op
->primitive_type
= state
->primitive_type
;
1101 op
->patch_vertex_count
= state
->patch_vertex_count
;
1102 op
->parameters
.indirect
= TRUE
;
1103 op
->parameters
.u
.indirect
.buffer
= buffer
;
1104 op
->parameters
.u
.indirect
.offset
= offset
;
1105 op
->parameters
.indexed
= indexed
;
1107 reference_graphics_pipeline_resources(context
, indexed
, d3d_info
);
1108 wined3d_device_context_reference_resource(context
, &buffer
->resource
);
1110 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1111 wined3d_device_context_unlock(context
);
1114 static void wined3d_cs_exec_flush(struct wined3d_cs
*cs
, const void *data
)
1116 struct wined3d_context
*context
;
1118 context
= context_acquire(cs
->c
.device
, NULL
, 0);
1119 cs
->c
.device
->adapter
->adapter_ops
->adapter_flush_context(context
);
1120 context_release(context
);
1123 static void wined3d_cs_flush(struct wined3d_device_context
*context
)
1125 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
1126 struct wined3d_cs_flush
*op
;
1128 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1129 op
->opcode
= WINED3D_CS_OP_FLUSH
;
1131 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1132 cs
->queries_flushed
= TRUE
;
1135 static void wined3d_cs_exec_set_predication(struct wined3d_cs
*cs
, const void *data
)
1137 const struct wined3d_cs_set_predication
*op
= data
;
1139 cs
->state
.predicate
= op
->predicate
;
1140 cs
->state
.predicate_value
= op
->value
;
1143 void wined3d_device_context_emit_set_predication(struct wined3d_device_context
*context
,
1144 struct wined3d_query
*predicate
, BOOL value
)
1146 struct wined3d_cs_set_predication
*op
;
1148 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1149 op
->opcode
= WINED3D_CS_OP_SET_PREDICATION
;
1150 op
->predicate
= predicate
;
1153 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1156 static void wined3d_cs_exec_set_viewports(struct wined3d_cs
*cs
, const void *data
)
1158 const struct wined3d_cs_set_viewports
*op
= data
;
1160 if (op
->viewport_count
)
1161 memcpy(cs
->state
.viewports
, op
->viewports
, op
->viewport_count
* sizeof(*op
->viewports
));
1163 memset(cs
->state
.viewports
, 0, sizeof(*cs
->state
.viewports
));
1164 cs
->state
.viewport_count
= op
->viewport_count
;
1165 device_invalidate_state(cs
->c
.device
, STATE_VIEWPORT
);
1168 void wined3d_device_context_emit_set_viewports(struct wined3d_device_context
*context
, unsigned int viewport_count
,
1169 const struct wined3d_viewport
*viewports
)
1171 struct wined3d_cs_set_viewports
*op
;
1173 op
= wined3d_device_context_require_space(context
,
1174 FIELD_OFFSET(struct wined3d_cs_set_viewports
,viewports
[viewport_count
]), WINED3D_CS_QUEUE_DEFAULT
);
1175 op
->opcode
= WINED3D_CS_OP_SET_VIEWPORTS
;
1176 memcpy(op
->viewports
, viewports
, viewport_count
* sizeof(*viewports
));
1177 op
->viewport_count
= viewport_count
;
1179 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1182 static void wined3d_cs_exec_set_scissor_rects(struct wined3d_cs
*cs
, const void *data
)
1184 const struct wined3d_cs_set_scissor_rects
*op
= data
;
1187 memcpy(cs
->state
.scissor_rects
, op
->rects
, op
->rect_count
* sizeof(*op
->rects
));
1189 SetRectEmpty(cs
->state
.scissor_rects
);
1190 cs
->state
.scissor_rect_count
= op
->rect_count
;
1191 device_invalidate_state(cs
->c
.device
, STATE_SCISSORRECT
);
1194 void wined3d_device_context_emit_set_scissor_rects(struct wined3d_device_context
*context
,
1195 unsigned int rect_count
, const RECT
*rects
)
1197 struct wined3d_cs_set_scissor_rects
*op
;
1199 op
= wined3d_device_context_require_space(context
, FIELD_OFFSET(struct wined3d_cs_set_scissor_rects
, rects
[rect_count
]),
1200 WINED3D_CS_QUEUE_DEFAULT
);
1201 op
->opcode
= WINED3D_CS_OP_SET_SCISSOR_RECTS
;
1202 memcpy(op
->rects
, rects
, rect_count
* sizeof(*rects
));
1203 op
->rect_count
= rect_count
;
1205 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1208 static void wined3d_cs_exec_set_rendertarget_views(struct wined3d_cs
*cs
, const void *data
)
1210 const struct wined3d_cs_set_rendertarget_views
*op
= data
;
1211 struct wined3d_device
*device
= cs
->c
.device
;
1214 for (i
= 0; i
< op
->count
; ++i
)
1216 struct wined3d_rendertarget_view
*prev
= cs
->state
.fb
.render_targets
[op
->start_idx
+ i
];
1217 struct wined3d_rendertarget_view
*view
= op
->views
[i
];
1218 bool prev_alpha_swizzle
, curr_alpha_swizzle
;
1219 bool prev_srgb_write
, curr_srgb_write
;
1221 cs
->state
.fb
.render_targets
[op
->start_idx
+ i
] = view
;
1223 prev_alpha_swizzle
= prev
&& prev
->format
->id
== WINED3DFMT_A8_UNORM
;
1224 curr_alpha_swizzle
= view
&& view
->format
->id
== WINED3DFMT_A8_UNORM
;
1225 if (prev_alpha_swizzle
!= curr_alpha_swizzle
)
1226 device_invalidate_state(device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1228 if (!(device
->adapter
->d3d_info
.wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
1229 || cs
->state
.render_states
[WINED3D_RS_SRGBWRITEENABLE
])
1231 prev_srgb_write
= prev
&& prev
->format_caps
& WINED3D_FORMAT_CAP_SRGB_WRITE
;
1232 curr_srgb_write
= view
&& view
->format_caps
& WINED3D_FORMAT_CAP_SRGB_WRITE
;
1233 if (prev_srgb_write
!= curr_srgb_write
)
1234 device_invalidate_state(device
, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE
));
1238 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1241 void wined3d_device_context_emit_set_rendertarget_views(struct wined3d_device_context
*context
,
1242 unsigned int start_idx
, unsigned int count
, struct wined3d_rendertarget_view
*const *views
)
1244 struct wined3d_cs_set_rendertarget_views
*op
;
1246 op
= wined3d_device_context_require_space(context
,
1247 offsetof(struct wined3d_cs_set_rendertarget_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1248 op
->opcode
= WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
;
1249 op
->start_idx
= start_idx
;
1251 memcpy(op
->views
, views
, count
* sizeof(*views
));
1253 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1256 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs
*cs
, const void *data
)
1258 const struct wined3d_cs_set_depth_stencil_view
*op
= data
;
1259 struct wined3d_device
*device
= cs
->c
.device
;
1260 struct wined3d_rendertarget_view
*prev
;
1262 if ((prev
= cs
->state
.fb
.depth_stencil
) && prev
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
1264 struct wined3d_texture
*prev_texture
= texture_from_resource(prev
->resource
);
1266 if (device
->swapchains
[0]->state
.desc
.flags
& WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
1267 || prev_texture
->flags
& WINED3D_TEXTURE_DISCARD
)
1268 wined3d_texture_validate_location(prev_texture
,
1269 prev
->sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
1272 cs
->state
.fb
.depth_stencil
= op
->view
;
1274 if (!prev
!= !op
->view
)
1276 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
1277 device_invalidate_state(device
, STATE_DEPTH_STENCIL
);
1278 device_invalidate_state(device
, STATE_STENCIL_REF
);
1279 device_invalidate_state(device
, STATE_RASTERIZER
);
1283 if (prev
->format
->depth_bias_scale
!= op
->view
->format
->depth_bias_scale
)
1284 device_invalidate_state(device
, STATE_RASTERIZER
);
1285 if (prev
->format
->stencil_size
!= op
->view
->format
->stencil_size
)
1286 device_invalidate_state(device
, STATE_STENCIL_REF
);
1289 device_invalidate_state(device
, STATE_FRAMEBUFFER
);
1292 void wined3d_device_context_emit_set_depth_stencil_view(struct wined3d_device_context
*context
,
1293 struct wined3d_rendertarget_view
*view
)
1295 struct wined3d_cs_set_depth_stencil_view
*op
;
1297 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1298 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
;
1301 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1304 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs
*cs
, const void *data
)
1306 const struct wined3d_cs_set_vertex_declaration
*op
= data
;
1308 cs
->state
.vertex_declaration
= op
->declaration
;
1309 device_invalidate_state(cs
->c
.device
, STATE_VDECL
);
1312 void wined3d_device_context_emit_set_vertex_declaration(struct wined3d_device_context
*context
,
1313 struct wined3d_vertex_declaration
*declaration
)
1315 struct wined3d_cs_set_vertex_declaration
*op
;
1317 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1318 op
->opcode
= WINED3D_CS_OP_SET_VERTEX_DECLARATION
;
1319 op
->declaration
= declaration
;
1321 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1324 static void wined3d_cs_exec_set_stream_sources(struct wined3d_cs
*cs
, const void *data
)
1326 const struct wined3d_cs_set_stream_sources
*op
= data
;
1329 for (i
= 0; i
< op
->count
; ++i
)
1331 struct wined3d_buffer
*prev
= cs
->state
.streams
[op
->start_idx
+ i
].buffer
;
1332 struct wined3d_buffer
*buffer
= op
->streams
[i
].buffer
;
1335 InterlockedIncrement(&buffer
->resource
.bind_count
);
1337 InterlockedDecrement(&prev
->resource
.bind_count
);
1340 memcpy(&cs
->state
.streams
[op
->start_idx
], op
->streams
, op
->count
* sizeof(*op
->streams
));
1341 device_invalidate_state(cs
->c
.device
, STATE_STREAMSRC
);
1344 void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context
*context
,
1345 unsigned int start_idx
, unsigned int count
, const struct wined3d_stream_state
*streams
)
1347 struct wined3d_cs_set_stream_sources
*op
;
1349 op
= wined3d_device_context_require_space(context
,
1350 offsetof(struct wined3d_cs_set_stream_sources
, streams
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1351 op
->opcode
= WINED3D_CS_OP_SET_STREAM_SOURCES
;
1352 op
->start_idx
= start_idx
;
1354 memcpy(op
->streams
, streams
, count
* sizeof(*streams
));
1356 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1359 static void wined3d_cs_exec_set_stream_outputs(struct wined3d_cs
*cs
, const void *data
)
1361 const struct wined3d_cs_set_stream_outputs
*op
= data
;
1364 for (i
= 0; i
< WINED3D_MAX_STREAM_OUTPUT_BUFFERS
; ++i
)
1366 struct wined3d_buffer
*prev
= cs
->state
.stream_output
[i
].buffer
;
1367 struct wined3d_buffer
*buffer
= op
->outputs
[i
].buffer
;
1370 InterlockedIncrement(&buffer
->resource
.bind_count
);
1372 InterlockedDecrement(&prev
->resource
.bind_count
);
1375 memcpy(cs
->state
.stream_output
, op
->outputs
, sizeof(op
->outputs
));
1376 device_invalidate_state(cs
->c
.device
, STATE_STREAM_OUTPUT
);
1379 void wined3d_device_context_emit_set_stream_outputs(struct wined3d_device_context
*context
,
1380 const struct wined3d_stream_output outputs
[WINED3D_MAX_STREAM_OUTPUT_BUFFERS
])
1382 struct wined3d_cs_set_stream_outputs
*op
;
1384 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1385 op
->opcode
= WINED3D_CS_OP_SET_STREAM_OUTPUTS
;
1386 memcpy(op
->outputs
, outputs
, sizeof(op
->outputs
));
1388 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1391 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs
*cs
, const void *data
)
1393 const struct wined3d_cs_set_index_buffer
*op
= data
;
1394 struct wined3d_buffer
*prev
;
1396 prev
= cs
->state
.index_buffer
;
1397 cs
->state
.index_buffer
= op
->buffer
;
1398 cs
->state
.index_format
= op
->format_id
;
1399 cs
->state
.index_offset
= op
->offset
;
1402 InterlockedIncrement(&op
->buffer
->resource
.bind_count
);
1404 InterlockedDecrement(&prev
->resource
.bind_count
);
1406 device_invalidate_state(cs
->c
.device
, STATE_INDEXBUFFER
);
1409 void wined3d_device_context_emit_set_index_buffer(struct wined3d_device_context
*context
, struct wined3d_buffer
*buffer
,
1410 enum wined3d_format_id format_id
, unsigned int offset
)
1412 struct wined3d_cs_set_index_buffer
*op
;
1414 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1415 op
->opcode
= WINED3D_CS_OP_SET_INDEX_BUFFER
;
1416 op
->buffer
= buffer
;
1417 op
->format_id
= format_id
;
1418 op
->offset
= offset
;
1420 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1423 static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs
*cs
, const void *data
)
1425 const struct wined3d_cs_set_constant_buffers
*op
= data
;
1428 for (i
= 0; i
< op
->count
; ++i
)
1430 struct wined3d_buffer
*prev
= cs
->state
.cb
[op
->type
][op
->start_idx
+ i
].buffer
;
1431 struct wined3d_buffer
*buffer
= op
->buffers
[i
].buffer
;
1433 cs
->state
.cb
[op
->type
][op
->start_idx
+ i
] = op
->buffers
[i
];
1436 InterlockedIncrement(&buffer
->resource
.bind_count
);
1438 InterlockedDecrement(&prev
->resource
.bind_count
);
1441 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1444 void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context
*context
,
1445 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1446 const struct wined3d_constant_buffer_state
*buffers
)
1448 struct wined3d_cs_set_constant_buffers
*op
;
1450 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_constant_buffers
, buffers
[count
]),
1451 WINED3D_CS_QUEUE_DEFAULT
);
1452 op
->opcode
= WINED3D_CS_OP_SET_CONSTANT_BUFFERS
;
1454 op
->start_idx
= start_idx
;
1456 memcpy(op
->buffers
, buffers
, count
* sizeof(*buffers
));
1458 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1461 static void wined3d_cs_exec_set_texture(struct wined3d_cs
*cs
, const void *data
)
1463 const struct wined3d_d3d_info
*d3d_info
= &cs
->c
.device
->adapter
->d3d_info
;
1464 const struct wined3d_cs_set_texture
*op
= data
;
1465 struct wined3d_texture
*prev
;
1466 BOOL old_use_color_key
= FALSE
, new_use_color_key
= FALSE
;
1468 prev
= cs
->state
.textures
[op
->stage
];
1469 cs
->state
.textures
[op
->stage
] = op
->texture
;
1473 const struct wined3d_format
*new_format
= op
->texture
->resource
.format
;
1474 const struct wined3d_format
*old_format
= prev
? prev
->resource
.format
: NULL
;
1475 unsigned int old_fmt_caps
= prev
? prev
->resource
.format_caps
: 0;
1476 unsigned int new_fmt_caps
= op
->texture
->resource
.format_caps
;
1478 if (InterlockedIncrement(&op
->texture
->resource
.bind_count
) == 1)
1479 op
->texture
->sampler
= op
->stage
;
1481 if (!prev
|| wined3d_texture_gl(op
->texture
)->target
!= wined3d_texture_gl(prev
)->target
1482 || (!is_same_fixup(new_format
->color_fixup
, old_format
->color_fixup
)
1483 && !(can_use_texture_swizzle(d3d_info
, new_format
) && can_use_texture_swizzle(d3d_info
, old_format
)))
1484 || (new_fmt_caps
& WINED3D_FORMAT_CAP_SHADOW
) != (old_fmt_caps
& WINED3D_FORMAT_CAP_SHADOW
))
1485 device_invalidate_state(cs
->c
.device
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
));
1487 if (!prev
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1489 /* The source arguments for color and alpha ops have different
1490 * meanings when a NULL texture is bound, so the COLOR_OP and
1491 * ALPHA_OP have to be dirtified. */
1492 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1493 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1496 if (!op
->stage
&& op
->texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1497 new_use_color_key
= TRUE
;
1502 if (InterlockedDecrement(&prev
->resource
.bind_count
) && prev
->sampler
== op
->stage
)
1506 /* Search for other stages the texture is bound to. Shouldn't
1507 * happen if applications bind textures to a single stage only. */
1508 TRACE("Searching for other stages the texture is bound to.\n");
1509 for (i
= 0; i
< WINED3D_MAX_COMBINED_SAMPLERS
; ++i
)
1511 if (cs
->state
.textures
[i
] == prev
)
1513 TRACE("Texture is also bound to stage %u.\n", i
);
1520 if (!op
->texture
&& op
->stage
< d3d_info
->limits
.ffp_blend_stages
)
1522 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_COLOR_OP
));
1523 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, WINED3D_TSS_ALPHA_OP
));
1526 if (!op
->stage
&& prev
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1527 old_use_color_key
= TRUE
;
1530 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->stage
));
1532 if (new_use_color_key
!= old_use_color_key
)
1533 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1535 if (new_use_color_key
)
1536 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1539 void wined3d_device_context_emit_set_texture(struct wined3d_device_context
*context
, unsigned int stage
,
1540 struct wined3d_texture
*texture
)
1542 struct wined3d_cs_set_texture
*op
;
1544 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1545 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE
;
1547 op
->texture
= texture
;
1549 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1552 static void wined3d_cs_exec_set_shader_resource_views(struct wined3d_cs
*cs
, const void *data
)
1554 const struct wined3d_cs_set_shader_resource_views
*op
= data
;
1557 for (i
= 0; i
< op
->count
; ++i
)
1559 struct wined3d_shader_resource_view
*prev
= cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
];
1560 struct wined3d_shader_resource_view
*view
= op
->views
[i
];
1562 cs
->state
.shader_resource_view
[op
->type
][op
->start_idx
+ i
] = view
;
1565 InterlockedIncrement(&view
->resource
->bind_count
);
1567 InterlockedDecrement(&prev
->resource
->bind_count
);
1570 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1571 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1573 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1576 void wined3d_device_context_emit_set_shader_resource_views(struct wined3d_device_context
*context
,
1577 enum wined3d_shader_type type
, unsigned int start_idx
, unsigned int count
,
1578 struct wined3d_shader_resource_view
*const *views
)
1580 struct wined3d_cs_set_shader_resource_views
*op
;
1582 op
= wined3d_device_context_require_space(context
,
1583 offsetof(struct wined3d_cs_set_shader_resource_views
, views
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1584 op
->opcode
= WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
;
1586 op
->start_idx
= start_idx
;
1588 memcpy(op
->views
, views
, count
* sizeof(*views
));
1590 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1593 static void wined3d_cs_exec_set_unordered_access_views(struct wined3d_cs
*cs
, const void *data
)
1595 const struct wined3d_cs_set_unordered_access_views
*op
= data
;
1598 for (i
= 0; i
< op
->count
; ++i
)
1600 struct wined3d_unordered_access_view
*prev
= cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
];
1601 struct wined3d_unordered_access_view
*view
= op
->uavs
[i
].view
;
1602 unsigned int initial_count
= op
->uavs
[i
].initial_count
;
1604 cs
->state
.unordered_access_view
[op
->pipeline
][op
->start_idx
+ i
] = view
;
1607 InterlockedIncrement(&view
->resource
->bind_count
);
1609 InterlockedDecrement(&prev
->resource
->bind_count
);
1611 if (view
&& initial_count
!= ~0u)
1612 wined3d_unordered_access_view_set_counter(view
, initial_count
);
1615 device_invalidate_state(cs
->c
.device
, STATE_UNORDERED_ACCESS_VIEW_BINDING(op
->pipeline
));
1618 void wined3d_device_context_emit_set_unordered_access_views(struct wined3d_device_context
*context
,
1619 enum wined3d_pipeline pipeline
, unsigned int start_idx
, unsigned int count
,
1620 struct wined3d_unordered_access_view
*const *views
, const unsigned int *initial_counts
)
1622 struct wined3d_cs_set_unordered_access_views
*op
;
1625 op
= wined3d_device_context_require_space(context
,
1626 offsetof(struct wined3d_cs_set_unordered_access_views
, uavs
[count
]), WINED3D_CS_QUEUE_DEFAULT
);
1627 op
->opcode
= WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
;
1628 op
->pipeline
= pipeline
;
1629 op
->start_idx
= start_idx
;
1631 for (i
= 0; i
< count
; ++i
)
1633 op
->uavs
[i
].view
= views
[i
];
1634 op
->uavs
[i
].initial_count
= initial_counts
? initial_counts
[i
] : ~0u;
1637 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1640 static void wined3d_cs_exec_set_samplers(struct wined3d_cs
*cs
, const void *data
)
1642 const struct wined3d_cs_set_samplers
*op
= data
;
1645 for (i
= 0; i
< op
->count
; ++i
)
1646 cs
->state
.sampler
[op
->type
][op
->start_idx
+ i
] = op
->samplers
[i
];
1648 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1649 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1651 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1654 void wined3d_device_context_emit_set_samplers(struct wined3d_device_context
*context
, enum wined3d_shader_type type
,
1655 unsigned int start_idx
, unsigned int count
, struct wined3d_sampler
*const *samplers
)
1657 struct wined3d_cs_set_samplers
*op
;
1659 op
= wined3d_device_context_require_space(context
, offsetof(struct wined3d_cs_set_samplers
, samplers
[count
]),
1660 WINED3D_CS_QUEUE_DEFAULT
);
1661 op
->opcode
= WINED3D_CS_OP_SET_SAMPLERS
;
1663 op
->start_idx
= start_idx
;
1665 memcpy(op
->samplers
, samplers
, count
* sizeof(*samplers
));
1667 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1670 static void wined3d_cs_exec_set_shader(struct wined3d_cs
*cs
, const void *data
)
1672 const struct wined3d_cs_set_shader
*op
= data
;
1674 /* CB binding may have been skipped earlier if the shader wasn't set, so make it happen. */
1675 if (!cs
->state
.shader
[op
->type
] && op
->shader
)
1676 device_invalidate_state(cs
->c
.device
, STATE_CONSTANT_BUFFER(op
->type
));
1677 cs
->state
.shader
[op
->type
] = op
->shader
;
1678 device_invalidate_state(cs
->c
.device
, STATE_SHADER(op
->type
));
1679 if (op
->type
!= WINED3D_SHADER_TYPE_COMPUTE
)
1680 device_invalidate_state(cs
->c
.device
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1682 device_invalidate_state(cs
->c
.device
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1685 void wined3d_device_context_emit_set_shader(struct wined3d_device_context
*context
,
1686 enum wined3d_shader_type type
, struct wined3d_shader
*shader
)
1688 struct wined3d_cs_set_shader
*op
;
1690 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1691 op
->opcode
= WINED3D_CS_OP_SET_SHADER
;
1693 op
->shader
= shader
;
1695 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1698 static void wined3d_cs_exec_set_blend_state(struct wined3d_cs
*cs
, const void *data
)
1700 const struct wined3d_cs_set_blend_state
*op
= data
;
1701 struct wined3d_state
*state
= &cs
->state
;
1703 if (state
->blend_state
!= op
->state
)
1705 state
->blend_state
= op
->state
;
1706 device_invalidate_state(cs
->c
.device
, STATE_BLEND
);
1708 state
->blend_factor
= op
->factor
;
1709 device_invalidate_state(cs
->c
.device
, STATE_BLEND_FACTOR
);
1710 state
->sample_mask
= op
->sample_mask
;
1711 device_invalidate_state(cs
->c
.device
, STATE_SAMPLE_MASK
);
1714 void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context
*context
,
1715 struct wined3d_blend_state
*state
, const struct wined3d_color
*blend_factor
, unsigned int sample_mask
)
1717 struct wined3d_cs_set_blend_state
*op
;
1719 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1720 op
->opcode
= WINED3D_CS_OP_SET_BLEND_STATE
;
1722 op
->factor
= *blend_factor
;
1723 op
->sample_mask
= sample_mask
;
1725 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1728 static void wined3d_cs_exec_set_depth_stencil_state(struct wined3d_cs
*cs
, const void *data
)
1730 const struct wined3d_cs_set_depth_stencil_state
*op
= data
;
1731 struct wined3d_state
*state
= &cs
->state
;
1733 if (state
->depth_stencil_state
!= op
->state
)
1735 state
->depth_stencil_state
= op
->state
;
1736 device_invalidate_state(cs
->c
.device
, STATE_DEPTH_STENCIL
);
1738 state
->stencil_ref
= op
->stencil_ref
;
1739 device_invalidate_state(cs
->c
.device
, STATE_STENCIL_REF
);
1742 void wined3d_device_context_emit_set_depth_stencil_state(struct wined3d_device_context
*context
,
1743 struct wined3d_depth_stencil_state
*state
, unsigned int stencil_ref
)
1745 struct wined3d_cs_set_depth_stencil_state
*op
;
1747 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1748 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
;
1750 op
->stencil_ref
= stencil_ref
;
1752 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1755 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs
*cs
, const void *data
)
1757 const struct wined3d_cs_set_rasterizer_state
*op
= data
;
1759 cs
->state
.rasterizer_state
= op
->state
;
1760 device_invalidate_state(cs
->c
.device
, STATE_RASTERIZER
);
1763 void wined3d_device_context_emit_set_rasterizer_state(struct wined3d_device_context
*context
,
1764 struct wined3d_rasterizer_state
*rasterizer_state
)
1766 struct wined3d_cs_set_rasterizer_state
*op
;
1768 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1769 op
->opcode
= WINED3D_CS_OP_SET_RASTERIZER_STATE
;
1770 op
->state
= rasterizer_state
;
1772 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1775 static void wined3d_cs_exec_set_depth_bounds(struct wined3d_cs
*cs
, const void *data
)
1777 const struct wined3d_cs_set_depth_bounds
*op
= data
;
1779 cs
->state
.depth_bounds_enable
= op
->enable
;
1780 cs
->state
.depth_bounds_min
= op
->min_depth
;
1781 cs
->state
.depth_bounds_max
= op
->max_depth
;
1782 device_invalidate_state(cs
->c
.device
, STATE_DEPTH_BOUNDS
);
1785 void wined3d_device_context_set_depth_bounds(struct wined3d_device_context
*context
,
1786 bool enable
, float min_depth
, float max_depth
)
1788 struct wined3d_cs_set_depth_bounds
*op
;
1790 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1791 op
->opcode
= WINED3D_CS_OP_SET_DEPTH_BOUNDS
;
1792 op
->enable
= enable
;
1793 op
->min_depth
= min_depth
;
1794 op
->max_depth
= max_depth
;
1796 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1799 static void wined3d_cs_exec_set_render_state(struct wined3d_cs
*cs
, const void *data
)
1801 const struct wined3d_cs_set_render_state
*op
= data
;
1803 cs
->state
.render_states
[op
->state
] = op
->value
;
1804 device_invalidate_state(cs
->c
.device
, STATE_RENDER(op
->state
));
1807 void wined3d_device_context_emit_set_render_state(struct wined3d_device_context
*context
,
1808 enum wined3d_render_state state
, unsigned int value
)
1810 struct wined3d_cs_set_render_state
*op
;
1812 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1813 op
->opcode
= WINED3D_CS_OP_SET_RENDER_STATE
;
1817 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1820 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs
*cs
, const void *data
)
1822 const struct wined3d_cs_set_texture_state
*op
= data
;
1824 cs
->state
.texture_states
[op
->stage
][op
->state
] = op
->value
;
1825 device_invalidate_state(cs
->c
.device
, STATE_TEXTURESTAGE(op
->stage
, op
->state
));
1828 void wined3d_device_context_emit_set_texture_state(struct wined3d_device_context
*context
, unsigned int stage
,
1829 enum wined3d_texture_stage_state state
, unsigned int value
)
1831 struct wined3d_cs_set_texture_state
*op
;
1833 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1834 op
->opcode
= WINED3D_CS_OP_SET_TEXTURE_STATE
;
1839 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1842 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs
*cs
, const void *data
)
1844 const struct wined3d_cs_set_sampler_state
*op
= data
;
1846 cs
->state
.sampler_states
[op
->sampler_idx
][op
->state
] = op
->value
;
1847 device_invalidate_state(cs
->c
.device
, STATE_SAMPLER(op
->sampler_idx
));
1850 void wined3d_device_context_emit_set_sampler_state(struct wined3d_device_context
*context
, unsigned int sampler_idx
,
1851 enum wined3d_sampler_state state
, unsigned int value
)
1853 struct wined3d_cs_set_sampler_state
*op
;
1855 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1856 op
->opcode
= WINED3D_CS_OP_SET_SAMPLER_STATE
;
1857 op
->sampler_idx
= sampler_idx
;
1861 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1864 static void wined3d_cs_exec_set_transform(struct wined3d_cs
*cs
, const void *data
)
1866 const struct wined3d_cs_set_transform
*op
= data
;
1868 cs
->state
.transforms
[op
->state
] = op
->matrix
;
1869 if (op
->state
< WINED3D_TS_WORLD_MATRIX(cs
->c
.device
->adapter
->d3d_info
.limits
.ffp_vertex_blend_matrices
))
1870 device_invalidate_state(cs
->c
.device
, STATE_TRANSFORM(op
->state
));
1873 void wined3d_device_context_emit_set_transform(struct wined3d_device_context
*context
,
1874 enum wined3d_transform_state state
, const struct wined3d_matrix
*matrix
)
1876 struct wined3d_cs_set_transform
*op
;
1878 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1879 op
->opcode
= WINED3D_CS_OP_SET_TRANSFORM
;
1881 op
->matrix
= *matrix
;
1883 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1886 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs
*cs
, const void *data
)
1888 const struct wined3d_cs_set_clip_plane
*op
= data
;
1890 cs
->state
.clip_planes
[op
->plane_idx
] = op
->plane
;
1891 device_invalidate_state(cs
->c
.device
, STATE_CLIPPLANE(op
->plane_idx
));
1894 void wined3d_device_context_emit_set_clip_plane(struct wined3d_device_context
*context
,
1895 unsigned int plane_idx
, const struct wined3d_vec4
*plane
)
1897 struct wined3d_cs_set_clip_plane
*op
;
1899 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1900 op
->opcode
= WINED3D_CS_OP_SET_CLIP_PLANE
;
1901 op
->plane_idx
= plane_idx
;
1904 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
1907 static void wined3d_cs_exec_set_color_key(struct wined3d_cs
*cs
, const void *data
)
1909 const struct wined3d_cs_set_color_key
*op
= data
;
1910 struct wined3d_texture
*texture
= op
->texture
;
1916 case WINED3D_CKEY_DST_BLT
:
1917 texture
->async
.dst_blt_color_key
= op
->color_key
;
1918 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_BLT
;
1921 case WINED3D_CKEY_DST_OVERLAY
:
1922 texture
->async
.dst_overlay_color_key
= op
->color_key
;
1923 texture
->async
.color_key_flags
|= WINED3D_CKEY_DST_OVERLAY
;
1926 case WINED3D_CKEY_SRC_BLT
:
1927 if (texture
== cs
->state
.textures
[0])
1929 device_invalidate_state(cs
->c
.device
, STATE_COLOR_KEY
);
1930 if (!(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
1931 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1934 texture
->async
.src_blt_color_key
= op
->color_key
;
1935 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_BLT
;
1938 case WINED3D_CKEY_SRC_OVERLAY
:
1939 texture
->async
.src_overlay_color_key
= op
->color_key
;
1940 texture
->async
.color_key_flags
|= WINED3D_CKEY_SRC_OVERLAY
;
1948 case WINED3D_CKEY_DST_BLT
:
1949 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_BLT
;
1952 case WINED3D_CKEY_DST_OVERLAY
:
1953 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_DST_OVERLAY
;
1956 case WINED3D_CKEY_SRC_BLT
:
1957 if (texture
== cs
->state
.textures
[0] && texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1958 device_invalidate_state(cs
->c
.device
, STATE_RENDER(WINED3D_RS_COLORKEYENABLE
));
1960 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_BLT
;
1963 case WINED3D_CKEY_SRC_OVERLAY
:
1964 texture
->async
.color_key_flags
&= ~WINED3D_CKEY_SRC_OVERLAY
;
1970 void wined3d_cs_emit_set_color_key(struct wined3d_cs
*cs
, struct wined3d_texture
*texture
,
1971 WORD flags
, const struct wined3d_color_key
*color_key
)
1973 struct wined3d_cs_set_color_key
*op
;
1975 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
1976 op
->opcode
= WINED3D_CS_OP_SET_COLOR_KEY
;
1977 op
->texture
= texture
;
1981 op
->color_key
= *color_key
;
1987 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
1990 static void wined3d_cs_exec_set_material(struct wined3d_cs
*cs
, const void *data
)
1992 const struct wined3d_cs_set_material
*op
= data
;
1994 cs
->state
.material
= op
->material
;
1995 device_invalidate_state(cs
->c
.device
, STATE_MATERIAL
);
1998 void wined3d_device_context_emit_set_material(struct wined3d_device_context
*context
,
1999 const struct wined3d_material
*material
)
2001 struct wined3d_cs_set_material
*op
;
2003 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2004 op
->opcode
= WINED3D_CS_OP_SET_MATERIAL
;
2005 op
->material
= *material
;
2007 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2010 static void wined3d_cs_exec_set_light(struct wined3d_cs
*cs
, const void *data
)
2012 const struct wined3d_cs_set_light
*op
= data
;
2013 struct wined3d_light_info
*light_info
;
2014 unsigned int light_idx
;
2016 light_idx
= op
->light
.OriginalIndex
;
2018 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, light_idx
)))
2020 TRACE("Adding new light.\n");
2021 if (!(light_info
= heap_alloc_zero(sizeof(*light_info
))))
2023 ERR("Failed to allocate light info.\n");
2027 light_info
->glIndex
= -1;
2028 light_info
->OriginalIndex
= light_idx
;
2029 rb_put(&cs
->state
.light_state
.lights_tree
, (void *)(ULONG_PTR
)light_idx
, &light_info
->entry
);
2032 if (light_info
->glIndex
!= -1)
2034 if (light_info
->OriginalParms
.type
!= op
->light
.OriginalParms
.type
)
2035 device_invalidate_state(cs
->c
.device
, STATE_LIGHT_TYPE
);
2036 device_invalidate_state(cs
->c
.device
, STATE_ACTIVELIGHT(light_info
->glIndex
));
2039 light_info
->OriginalParms
= op
->light
.OriginalParms
;
2040 light_info
->position
= op
->light
.position
;
2041 light_info
->direction
= op
->light
.direction
;
2042 light_info
->exponent
= op
->light
.exponent
;
2043 light_info
->cutoff
= op
->light
.cutoff
;
2046 void wined3d_device_context_emit_set_light(struct wined3d_device_context
*context
,
2047 const struct wined3d_light_info
*light
)
2049 struct wined3d_cs_set_light
*op
;
2051 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2052 op
->opcode
= WINED3D_CS_OP_SET_LIGHT
;
2055 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2058 static void wined3d_cs_exec_set_light_enable(struct wined3d_cs
*cs
, const void *data
)
2060 const struct wined3d_cs_set_light_enable
*op
= data
;
2061 struct wined3d_device
*device
= cs
->c
.device
;
2062 struct wined3d_light_info
*light_info
;
2065 if (!(light_info
= wined3d_light_state_get_light(&cs
->state
.light_state
, op
->idx
)))
2067 ERR("Light doesn't exist.\n");
2071 prev_idx
= light_info
->glIndex
;
2072 if (wined3d_light_state_enable_light(&cs
->state
.light_state
, &device
->adapter
->d3d_info
, light_info
, op
->enable
))
2074 device_invalidate_state(device
, STATE_LIGHT_TYPE
);
2075 device_invalidate_state(device
, STATE_ACTIVELIGHT(op
->enable
? light_info
->glIndex
: prev_idx
));
2079 void wined3d_device_context_emit_set_light_enable(struct wined3d_device_context
*context
, unsigned int idx
, BOOL enable
)
2081 struct wined3d_cs_set_light_enable
*op
;
2083 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2084 op
->opcode
= WINED3D_CS_OP_SET_LIGHT_ENABLE
;
2086 op
->enable
= enable
;
2088 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2091 static void wined3d_cs_exec_set_feature_level(struct wined3d_cs
*cs
, const void *data
)
2093 const struct wined3d_cs_set_feature_level
*op
= data
;
2095 cs
->state
.feature_level
= op
->level
;
2098 void wined3d_device_context_emit_set_feature_level(struct wined3d_device_context
*context
,
2099 enum wined3d_feature_level level
)
2101 struct wined3d_cs_set_feature_level
*op
;
2103 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2104 op
->opcode
= WINED3D_CS_OP_SET_FEATURE_LEVEL
;
2107 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2116 wined3d_cs_push_constant_info
[] =
2118 /* WINED3D_PUSH_CONSTANTS_VS_F */
2119 {FIELD_OFFSET(struct wined3d_state
, vs_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_VS_F
},
2120 /* WINED3D_PUSH_CONSTANTS_PS_F */
2121 {FIELD_OFFSET(struct wined3d_state
, ps_consts_f
), sizeof(struct wined3d_vec4
), WINED3D_SHADER_CONST_PS_F
},
2122 /* WINED3D_PUSH_CONSTANTS_VS_I */
2123 {FIELD_OFFSET(struct wined3d_state
, vs_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_VS_I
},
2124 /* WINED3D_PUSH_CONSTANTS_PS_I */
2125 {FIELD_OFFSET(struct wined3d_state
, ps_consts_i
), sizeof(struct wined3d_ivec4
), WINED3D_SHADER_CONST_PS_I
},
2126 /* WINED3D_PUSH_CONSTANTS_VS_B */
2127 {FIELD_OFFSET(struct wined3d_state
, vs_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_VS_B
},
2128 /* WINED3D_PUSH_CONSTANTS_PS_B */
2129 {FIELD_OFFSET(struct wined3d_state
, ps_consts_b
), sizeof(BOOL
), WINED3D_SHADER_CONST_PS_B
},
2132 static void wined3d_cs_st_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2133 unsigned int start_idx
, unsigned int count
, const void *constants
)
2135 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2136 struct wined3d_device
*device
= cs
->c
.device
;
2137 unsigned int context_count
;
2141 if (p
== WINED3D_PUSH_CONSTANTS_VS_F
)
2142 device
->shader_backend
->shader_update_float_vertex_constants(device
, start_idx
, count
);
2143 else if (p
== WINED3D_PUSH_CONSTANTS_PS_F
)
2144 device
->shader_backend
->shader_update_float_pixel_constants(device
, start_idx
, count
);
2146 offset
= wined3d_cs_push_constant_info
[p
].offset
+ start_idx
* wined3d_cs_push_constant_info
[p
].size
;
2147 memcpy((BYTE
*)&cs
->state
+ offset
, constants
, count
* wined3d_cs_push_constant_info
[p
].size
);
2148 for (i
= 0, context_count
= device
->context_count
; i
< context_count
; ++i
)
2150 device
->contexts
[i
]->constant_update_mask
|= wined3d_cs_push_constant_info
[p
].mask
;
2154 static void wined3d_cs_exec_push_constants(struct wined3d_cs
*cs
, const void *data
)
2156 const struct wined3d_cs_push_constants
*op
= data
;
2158 wined3d_cs_st_push_constants(&cs
->c
, op
->type
, op
->start_idx
, op
->count
, op
->constants
);
2161 static void wined3d_cs_mt_push_constants(struct wined3d_device_context
*context
, enum wined3d_push_constants p
,
2162 unsigned int start_idx
, unsigned int count
, const void *constants
)
2164 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2165 struct wined3d_cs_push_constants
*op
;
2168 size
= count
* wined3d_cs_push_constant_info
[p
].size
;
2169 op
= wined3d_device_context_require_space(&cs
->c
, FIELD_OFFSET(struct wined3d_cs_push_constants
, constants
[size
]),
2170 WINED3D_CS_QUEUE_DEFAULT
);
2171 op
->opcode
= WINED3D_CS_OP_PUSH_CONSTANTS
;
2173 op
->start_idx
= start_idx
;
2175 memcpy(op
->constants
, constants
, size
);
2177 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2180 static void wined3d_cs_exec_reset_state(struct wined3d_cs
*cs
, const void *data
)
2182 const struct wined3d_device
*device
= cs
->c
.device
;
2183 const struct wined3d_cs_reset_state
*op
= data
;
2184 const struct wined3d_state_entry
*state_table
;
2187 state_cleanup(&cs
->state
);
2188 wined3d_state_reset(&cs
->state
, &device
->adapter
->d3d_info
);
2191 state_table
= device
->state_table
;
2192 for (state
= 0; state
<= STATE_HIGHEST
; ++state
)
2194 if (state_table
[state
].representative
)
2195 device_invalidate_state(device
, state
);
2200 void wined3d_device_context_emit_reset_state(struct wined3d_device_context
*context
, bool invalidate
)
2202 struct wined3d_cs_reset_state
*op
;
2204 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2205 op
->opcode
= WINED3D_CS_OP_RESET_STATE
;
2206 op
->invalidate
= invalidate
;
2208 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2211 static void wined3d_cs_exec_callback(struct wined3d_cs
*cs
, const void *data
)
2213 const struct wined3d_cs_callback
*op
= data
;
2215 op
->callback(op
->object
);
2218 static void wined3d_cs_emit_callback(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2220 struct wined3d_cs_callback
*op
;
2222 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2223 op
->opcode
= WINED3D_CS_OP_CALLBACK
;
2224 op
->callback
= callback
;
2225 op
->object
= object
;
2227 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2230 void wined3d_cs_destroy_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2232 wined3d_cs_emit_callback(cs
, callback
, object
);
2235 void wined3d_cs_init_object(struct wined3d_cs
*cs
, void (*callback
)(void *object
), void *object
)
2237 wined3d_cs_emit_callback(cs
, callback
, object
);
2240 static void wined3d_cs_exec_query_issue(struct wined3d_cs
*cs
, const void *data
)
2242 const struct wined3d_cs_query_issue
*op
= data
;
2243 struct wined3d_query
*query
= op
->query
;
2246 poll
= query
->query_ops
->query_issue(query
, op
->flags
);
2248 if (!query
->poll_in_cs
)
2250 if (op
->flags
& WINED3DISSUE_END
)
2251 InterlockedIncrement(&query
->counter_retrieved
);
2255 if (poll
&& list_empty(&query
->poll_list_entry
))
2257 if (query
->buffer_object
)
2258 InterlockedIncrement(&query
->counter_retrieved
);
2260 list_add_tail(&cs
->query_poll_list
, &query
->poll_list_entry
);
2264 /* This can happen if occlusion queries are restarted. This discards the
2265 * old result, since polling it could result in a GL error. */
2266 if ((op
->flags
& WINED3DISSUE_BEGIN
) && !poll
&& !list_empty(&query
->poll_list_entry
))
2268 list_remove(&query
->poll_list_entry
);
2269 list_init(&query
->poll_list_entry
);
2270 InterlockedIncrement(&query
->counter_retrieved
);
2274 /* This can happen when an occlusion query is ended without being started,
2275 * in which case we don't want to poll, but still have to counter-balance
2276 * the increment of the main counter.
2278 * This can also happen if an event query is re-issued before the first
2279 * fence was reached. In this case the query is already in the list and
2280 * the poll function will check the new fence. We have to counter-balance
2281 * the discarded increment. */
2282 if (op
->flags
& WINED3DISSUE_END
)
2283 InterlockedIncrement(&query
->counter_retrieved
);
2286 static void wined3d_cs_issue_query(struct wined3d_device_context
*context
,
2287 struct wined3d_query
*query
, unsigned int flags
)
2289 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2290 struct wined3d_cs_query_issue
*op
;
2292 if (flags
& WINED3DISSUE_END
)
2293 ++query
->counter_main
;
2295 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2296 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
2300 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2301 cs
->queries_flushed
= FALSE
;
2303 if (flags
& WINED3DISSUE_BEGIN
)
2304 query
->state
= QUERY_BUILDING
;
2306 query
->state
= QUERY_SIGNALLED
;
2309 static void wined3d_cs_reference_command_list(struct wined3d_device_context
*context
, struct wined3d_command_list
*list
)
2311 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2314 if (list
->query_count
)
2316 cs
->queries_flushed
= FALSE
;
2318 for (i
= 0; i
< list
->query_count
; ++i
)
2320 if (list
->queries
[i
].flags
& WINED3DISSUE_END
)
2322 list
->queries
[i
].query
->counter_main
++;
2323 list
->queries
[i
].query
->state
= QUERY_SIGNALLED
;
2327 list
->queries
[i
].query
->state
= QUERY_BUILDING
;
2332 for (i
= 0; i
< list
->resource_count
; ++i
)
2333 wined3d_resource_reference(list
->resources
[i
]);
2335 for (i
= 0; i
< list
->command_list_count
; ++i
)
2336 wined3d_cs_reference_command_list(context
, list
->command_lists
[i
]);
2338 for (i
= 0; i
< list
->upload_count
; ++i
)
2339 invalidate_client_address(list
->uploads
[i
].resource
);
2342 static void wined3d_cs_exec_preload_resource(struct wined3d_cs
*cs
, const void *data
)
2344 const struct wined3d_cs_preload_resource
*op
= data
;
2345 struct wined3d_resource
*resource
= op
->resource
;
2347 resource
->resource_ops
->resource_preload(resource
);
2350 void wined3d_cs_emit_preload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2352 struct wined3d_cs_preload_resource
*op
;
2354 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2355 op
->opcode
= WINED3D_CS_OP_PRELOAD_RESOURCE
;
2356 op
->resource
= resource
;
2358 wined3d_resource_reference(resource
);
2360 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2363 static void wined3d_cs_exec_unload_resource(struct wined3d_cs
*cs
, const void *data
)
2365 const struct wined3d_cs_unload_resource
*op
= data
;
2366 struct wined3d_resource
*resource
= op
->resource
;
2368 resource
->resource_ops
->resource_unload(resource
);
2371 void wined3d_cs_emit_unload_resource(struct wined3d_cs
*cs
, struct wined3d_resource
*resource
)
2373 struct wined3d_cs_unload_resource
*op
;
2375 discard_client_address(resource
);
2377 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2378 op
->opcode
= WINED3D_CS_OP_UNLOAD_RESOURCE
;
2379 op
->resource
= resource
;
2381 wined3d_resource_reference(resource
);
2383 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2386 static void wined3d_device_context_upload_bo(struct wined3d_device_context
*context
,
2387 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2388 const struct upload_bo
*bo
, unsigned int row_pitch
, unsigned int slice_pitch
)
2390 struct wined3d_cs_update_sub_resource
*op
;
2392 TRACE("context %p, resource %p, sub_resource_idx %u, box %s, bo %s, flags %#x, row_pitch %u, slice_pitch %u.\n",
2393 context
, resource
, sub_resource_idx
, debug_box(box
),
2394 debug_const_bo_address(&bo
->addr
), bo
->flags
, row_pitch
, slice_pitch
);
2396 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2397 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2398 op
->resource
= resource
;
2399 op
->sub_resource_idx
= sub_resource_idx
;
2402 op
->row_pitch
= row_pitch
;
2403 op
->slice_pitch
= slice_pitch
;
2405 wined3d_device_context_reference_resource(context
, resource
);
2407 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2410 static void wined3d_cs_exec_map(struct wined3d_cs
*cs
, const void *data
)
2412 const struct wined3d_cs_map
*op
= data
;
2413 struct wined3d_resource
*resource
= op
->resource
;
2415 *op
->hr
= resource
->resource_ops
->resource_sub_resource_map(resource
,
2416 op
->sub_resource_idx
, op
->map_ptr
, op
->box
, op
->flags
);
2419 HRESULT
wined3d_device_context_emit_map(struct wined3d_device_context
*context
,
2420 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
2421 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, unsigned int flags
)
2423 struct wined3d_cs_map
*op
;
2426 /* Mapping resources from the worker thread isn't an issue by itself, but
2427 * increasing the map count would be visible to applications. */
2428 wined3d_not_from_cs(context
->device
->cs
);
2430 if ((flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
2431 && context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, map_desc
, box
, flags
))
2433 TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n",
2434 map_desc
->data
, map_desc
->row_pitch
, map_desc
->slice_pitch
);
2438 wined3d_resource_wait_idle(resource
);
2440 /* We might end up invalidating the resource on the CS thread. */
2441 invalidate_client_address(resource
);
2443 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2444 return E_OUTOFMEMORY
;
2445 op
->opcode
= WINED3D_CS_OP_MAP
;
2446 op
->resource
= resource
;
2447 op
->sub_resource_idx
= sub_resource_idx
;
2448 op
->map_ptr
= &map_desc
->data
;
2453 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2454 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2457 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
2458 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
2462 static void wined3d_cs_exec_unmap(struct wined3d_cs
*cs
, const void *data
)
2464 const struct wined3d_cs_unmap
*op
= data
;
2465 struct wined3d_resource
*resource
= op
->resource
;
2467 *op
->hr
= resource
->resource_ops
->resource_sub_resource_unmap(resource
, op
->sub_resource_idx
);
2470 HRESULT
wined3d_device_context_emit_unmap(struct wined3d_device_context
*context
,
2471 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
2473 struct wined3d_cs_unmap
*op
;
2474 struct wined3d_box box
;
2475 struct upload_bo bo
;
2478 if (context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
))
2480 unsigned int row_pitch
, slice_pitch
;
2482 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
, &row_pitch
, &slice_pitch
);
2483 if (bo
.flags
& UPLOAD_BO_UPLOAD_ON_UNMAP
)
2484 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
, &box
, &bo
, row_pitch
, slice_pitch
);
2488 wined3d_not_from_cs(context
->device
->cs
);
2490 if (!(op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
)))
2491 return E_OUTOFMEMORY
;
2492 op
->opcode
= WINED3D_CS_OP_UNMAP
;
2493 op
->resource
= resource
;
2494 op
->sub_resource_idx
= sub_resource_idx
;
2497 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2498 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2503 static void wined3d_cs_exec_map_bo_address(struct wined3d_cs
*cs
, const void *data
)
2505 const struct wined3d_cs_map_bo_address
*op
= data
;
2506 struct wined3d_context
*context
;
2508 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2509 wined3d_context_map_bo_address(context
, &op
->addr
, op
->size
, op
->flags
);
2510 context_release(context
);
2513 void wined3d_cs_map_bo_address(struct wined3d_cs
*cs
,
2514 struct wined3d_bo_address
*addr
, size_t size
, unsigned int flags
)
2516 struct wined3d_device_context
*context
= &cs
->c
;
2517 struct wined3d_cs_map_bo_address
*op
;
2519 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2520 op
->opcode
= WINED3D_CS_OP_MAP_BO_ADDRESS
;
2524 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2525 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2528 static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2530 const struct wined3d_cs_blt_sub_resource
*op
= data
;
2532 if (op
->dst_resource
->type
== WINED3D_RTYPE_BUFFER
)
2534 wined3d_buffer_copy(buffer_from_resource(op
->dst_resource
), op
->dst_box
.left
,
2535 buffer_from_resource(op
->src_resource
), op
->src_box
.left
,
2536 op
->src_box
.right
- op
->src_box
.left
);
2538 else if (op
->dst_resource
->type
== WINED3D_RTYPE_TEXTURE_3D
)
2540 struct wined3d_texture
*src_texture
, *dst_texture
;
2541 unsigned int level
, update_w
, update_h
, update_d
;
2542 unsigned int row_pitch
, slice_pitch
;
2543 struct wined3d_context
*context
;
2544 struct wined3d_bo_address addr
;
2545 unsigned int location
;
2547 if (op
->flags
& ~WINED3D_BLT_RAW
)
2549 FIXME("Flags %#x not implemented for %s resources.\n",
2550 op
->flags
, debug_d3dresourcetype(op
->dst_resource
->type
));
2554 if (!(op
->flags
& WINED3D_BLT_RAW
) && op
->src_resource
->format
!= op
->dst_resource
->format
)
2556 FIXME("Format conversion not implemented for %s resources.\n",
2557 debug_d3dresourcetype(op
->dst_resource
->type
));
2561 update_w
= op
->dst_box
.right
- op
->dst_box
.left
;
2562 update_h
= op
->dst_box
.bottom
- op
->dst_box
.top
;
2563 update_d
= op
->dst_box
.back
- op
->dst_box
.front
;
2564 if (op
->src_box
.right
- op
->src_box
.left
!= update_w
2565 || op
->src_box
.bottom
- op
->src_box
.top
!= update_h
2566 || op
->src_box
.back
- op
->src_box
.front
!= update_d
)
2568 FIXME("Stretching not implemented for %s resources.\n",
2569 debug_d3dresourcetype(op
->dst_resource
->type
));
2573 dst_texture
= texture_from_resource(op
->dst_resource
);
2574 src_texture
= texture_from_resource(op
->src_resource
);
2576 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2578 location
= src_texture
->resource
.map_binding
;
2579 if (location
== WINED3D_LOCATION_SYSMEM
2580 && wined3d_texture_can_use_pbo(src_texture
, &context
->device
->adapter
->d3d_info
))
2581 location
= WINED3D_LOCATION_BUFFER
;
2583 if (!wined3d_texture_load_location(src_texture
, op
->src_sub_resource_idx
,
2586 ERR("Failed to load source sub-resource into %s.\n",
2587 wined3d_debug_location(location
));
2588 context_release(context
);
2592 level
= op
->dst_sub_resource_idx
% dst_texture
->level_count
;
2593 if (update_w
== wined3d_texture_get_level_width(dst_texture
, level
)
2594 && update_h
== wined3d_texture_get_level_height(dst_texture
, level
)
2595 && update_d
== wined3d_texture_get_level_depth(dst_texture
, level
))
2597 wined3d_texture_prepare_location(dst_texture
, op
->dst_sub_resource_idx
,
2598 context
, WINED3D_LOCATION_TEXTURE_RGB
);
2600 else if (!wined3d_texture_load_location(dst_texture
, op
->dst_sub_resource_idx
,
2601 context
, WINED3D_LOCATION_TEXTURE_RGB
))
2603 ERR("Failed to load destination sub-resource.\n");
2604 context_release(context
);
2608 wined3d_texture_get_bo_address(src_texture
, op
->src_sub_resource_idx
, &addr
, location
);
2609 wined3d_texture_get_pitch(src_texture
, op
->src_sub_resource_idx
% src_texture
->level_count
,
2610 &row_pitch
, &slice_pitch
);
2612 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&addr
),
2613 dst_texture
->resource
.format
, &op
->src_box
, row_pitch
, slice_pitch
, dst_texture
,
2614 op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
2615 op
->dst_box
.left
, op
->dst_box
.top
, op
->dst_box
.front
);
2616 wined3d_texture_validate_location(dst_texture
, op
->dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
2617 wined3d_texture_invalidate_location(dst_texture
, op
->dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
2619 context_release(context
);
2623 if (FAILED(texture2d_blt(texture_from_resource(op
->dst_resource
), op
->dst_sub_resource_idx
,
2624 &op
->dst_box
, texture_from_resource(op
->src_resource
), op
->src_sub_resource_idx
,
2625 &op
->src_box
, op
->flags
, &op
->fx
, op
->filter
)))
2626 FIXME("Blit failed.\n");
2630 void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context
*context
,
2631 struct wined3d_resource
*dst_resource
, unsigned int dst_sub_resource_idx
, const struct wined3d_box
*dst_box
,
2632 struct wined3d_resource
*src_resource
, unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
,
2633 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
2635 struct wined3d_cs_blt_sub_resource
*op
;
2637 /* If we are replacing the whole resource, the CS thread might discard and
2638 * rename the buffer object, in which case ours is no longer valid. */
2639 if (dst_resource
->type
== WINED3D_RTYPE_BUFFER
&& dst_box
->right
- dst_box
->left
== dst_resource
->size
)
2640 invalidate_client_address(dst_resource
);
2642 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2643 op
->opcode
= WINED3D_CS_OP_BLT_SUB_RESOURCE
;
2644 op
->dst_resource
= dst_resource
;
2645 op
->dst_sub_resource_idx
= dst_sub_resource_idx
;
2646 op
->dst_box
= *dst_box
;
2647 op
->src_resource
= src_resource
;
2648 op
->src_sub_resource_idx
= src_sub_resource_idx
;
2649 op
->src_box
= *src_box
;
2654 memset(&op
->fx
, 0, sizeof(op
->fx
));
2655 op
->filter
= filter
;
2657 wined3d_device_context_reference_resource(context
, dst_resource
);
2659 wined3d_device_context_reference_resource(context
, src_resource
);
2661 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2662 if (flags
& WINED3D_BLT_SYNCHRONOUS
)
2663 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_DEFAULT
);
2666 static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs
*cs
, const void *data
)
2668 const struct wined3d_cs_update_sub_resource
*op
= data
;
2669 struct wined3d_resource
*resource
= op
->resource
;
2670 const struct wined3d_box
*box
= &op
->box
;
2671 struct wined3d_context
*context
;
2673 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2675 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2676 wined3d_buffer_update_sub_resource(buffer_from_resource(resource
),
2677 context
, &op
->bo
, box
->left
, box
->right
- box
->left
);
2679 wined3d_texture_update_sub_resource(texture_from_resource(resource
),
2680 op
->sub_resource_idx
, context
, &op
->bo
, box
, op
->row_pitch
, op
->slice_pitch
);
2682 context_release(context
);
2684 if (op
->bo
.flags
& UPLOAD_BO_FREE_ON_UNMAP
)
2686 if (op
->bo
.addr
.buffer_object
)
2687 FIXME("Free BO address %s.\n", debug_const_bo_address(&op
->bo
.addr
));
2689 heap_free((void *)op
->bo
.addr
.addr
);
2693 void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_context
*context
,
2694 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, const struct wined3d_box
*box
,
2695 const void *data
, unsigned int row_pitch
, unsigned int slice_pitch
)
2697 struct wined3d_cs_update_sub_resource
*op
;
2698 struct wined3d_map_desc map_desc
;
2699 struct wined3d_box dummy_box
;
2700 struct upload_bo bo
;
2702 /* If we are replacing the whole resource, the CS thread might discard and
2703 * rename the buffer object, in which case ours is no longer valid. */
2704 if (resource
->type
== WINED3D_RTYPE_BUFFER
&& box
->right
- box
->left
== resource
->size
)
2705 invalidate_client_address(resource
);
2707 if (context
->ops
->map_upload_bo(context
, resource
, sub_resource_idx
, &map_desc
, box
, WINED3D_MAP_WRITE
))
2709 wined3d_format_copy_data(resource
->format
, data
, row_pitch
, slice_pitch
, map_desc
.data
, map_desc
.row_pitch
,
2710 map_desc
.slice_pitch
, box
->right
- box
->left
, box
->bottom
- box
->top
, box
->back
- box
->front
);
2711 context
->ops
->unmap_upload_bo(context
, resource
, sub_resource_idx
, &dummy_box
, &bo
);
2712 wined3d_device_context_upload_bo(context
, resource
, sub_resource_idx
,
2713 box
, &bo
, map_desc
.row_pitch
, map_desc
.slice_pitch
);
2717 wined3d_resource_wait_idle(resource
);
2719 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_MAP
);
2720 op
->opcode
= WINED3D_CS_OP_UPDATE_SUB_RESOURCE
;
2721 op
->resource
= resource
;
2722 op
->sub_resource_idx
= sub_resource_idx
;
2724 op
->bo
.addr
.buffer_object
= 0;
2725 op
->bo
.addr
.addr
= data
;
2727 op
->row_pitch
= row_pitch
;
2728 op
->slice_pitch
= slice_pitch
;
2730 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_MAP
);
2731 /* The data pointer may go away, so we need to wait until it is read.
2732 * Copying the data may be faster if it's small. */
2733 wined3d_device_context_finish(context
, WINED3D_CS_QUEUE_MAP
);
2736 static void wined3d_cs_exec_add_dirty_texture_region(struct wined3d_cs
*cs
, const void *data
)
2738 const struct wined3d_cs_add_dirty_texture_region
*op
= data
;
2739 struct wined3d_texture
*texture
= op
->texture
;
2740 unsigned int sub_resource_idx
, i
;
2741 struct wined3d_context
*context
;
2743 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2744 sub_resource_idx
= op
->layer
* texture
->level_count
;
2745 for (i
= 0; i
< texture
->level_count
; ++i
, ++sub_resource_idx
)
2747 if (wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
))
2748 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
2750 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
2752 context_release(context
);
2755 void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs
*cs
,
2756 struct wined3d_texture
*texture
, unsigned int layer
)
2758 struct wined3d_cs_add_dirty_texture_region
*op
;
2760 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2761 op
->opcode
= WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION
;
2762 op
->texture
= texture
;
2765 wined3d_resource_reference(&texture
->resource
);
2767 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2770 static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs
*cs
, const void *data
)
2772 const struct wined3d_cs_clear_unordered_access_view
*op
= data
;
2773 struct wined3d_unordered_access_view
*view
= op
->view
;
2774 struct wined3d_context
*context
;
2776 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2777 cs
->c
.device
->adapter
->adapter_ops
->adapter_clear_uav(context
, view
, &op
->clear_value
, op
->fp
);
2778 context_release(context
);
2781 void wined3d_device_context_emit_clear_uav(struct wined3d_device_context
*context
,
2782 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
, bool fp
)
2784 struct wined3d_cs_clear_unordered_access_view
*op
;
2786 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2787 op
->opcode
= WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
;
2789 op
->clear_value
= *clear_value
;
2792 wined3d_device_context_reference_resource(context
, view
->resource
);
2794 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2797 static void wined3d_cs_exec_copy_uav_counter(struct wined3d_cs
*cs
, const void *data
)
2799 const struct wined3d_cs_copy_uav_counter
*op
= data
;
2800 struct wined3d_unordered_access_view
*view
= op
->view
;
2801 struct wined3d_context
*context
;
2803 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2804 wined3d_unordered_access_view_copy_counter(view
, op
->buffer
, op
->offset
, context
);
2805 context_release(context
);
2808 void wined3d_device_context_emit_copy_uav_counter(struct wined3d_device_context
*context
,
2809 struct wined3d_buffer
*dst_buffer
, unsigned int offset
, struct wined3d_unordered_access_view
*uav
)
2811 struct wined3d_cs_copy_uav_counter
*op
;
2813 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2814 op
->opcode
= WINED3D_CS_OP_COPY_UAV_COUNTER
;
2815 op
->buffer
= dst_buffer
;
2816 op
->offset
= offset
;
2819 wined3d_device_context_reference_resource(context
, &dst_buffer
->resource
);
2821 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2824 static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs
*cs
, const void *data
)
2826 const struct wined3d_cs_generate_mipmaps
*op
= data
;
2827 struct wined3d_shader_resource_view
*view
= op
->view
;
2828 struct wined3d_context
*context
;
2830 context
= context_acquire(cs
->c
.device
, NULL
, 0);
2831 cs
->c
.device
->adapter
->adapter_ops
->adapter_generate_mipmap(context
, view
);
2832 context_release(context
);
2835 void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context
*context
,
2836 struct wined3d_shader_resource_view
*view
)
2838 struct wined3d_cs_generate_mipmaps
*op
;
2840 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2841 op
->opcode
= WINED3D_CS_OP_GENERATE_MIPMAPS
;
2844 wined3d_device_context_reference_resource(context
, view
->resource
);
2846 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2849 static void wined3d_cs_emit_stop(struct wined3d_cs
*cs
)
2851 struct wined3d_cs_stop
*op
;
2853 op
= wined3d_device_context_require_space(&cs
->c
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2854 op
->opcode
= WINED3D_CS_OP_STOP
;
2856 wined3d_device_context_submit(&cs
->c
, WINED3D_CS_QUEUE_DEFAULT
);
2857 wined3d_cs_finish(cs
, WINED3D_CS_QUEUE_DEFAULT
);
2860 static void wined3d_cs_reference_resource(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
)
2862 wined3d_resource_reference(resource
);
2865 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
);
2867 static void (* const wined3d_cs_op_handlers
[])(struct wined3d_cs
*cs
, const void *data
) =
2869 /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop
,
2870 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present
,
2871 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear
,
2872 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch
,
2873 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw
,
2874 /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush
,
2875 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication
,
2876 /* WINED3D_CS_OP_SET_VIEWPORTS */ wined3d_cs_exec_set_viewports
,
2877 /* WINED3D_CS_OP_SET_SCISSOR_RECTS */ wined3d_cs_exec_set_scissor_rects
,
2878 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEWS */ wined3d_cs_exec_set_rendertarget_views
,
2879 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view
,
2880 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration
,
2881 /* WINED3D_CS_OP_SET_STREAM_SOURCES */ wined3d_cs_exec_set_stream_sources
,
2882 /* WINED3D_CS_OP_SET_STREAM_OUTPUTS */ wined3d_cs_exec_set_stream_outputs
,
2883 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer
,
2884 /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers
,
2885 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture
,
2886 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS */ wined3d_cs_exec_set_shader_resource_views
,
2887 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS */ wined3d_cs_exec_set_unordered_access_views
,
2888 /* WINED3D_CS_OP_SET_SAMPLERS */ wined3d_cs_exec_set_samplers
,
2889 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader
,
2890 /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state
,
2891 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE */ wined3d_cs_exec_set_depth_stencil_state
,
2892 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state
,
2893 /* WINED3D_CS_OP_SET_DEPTH_BOUNDS */ wined3d_cs_exec_set_depth_bounds
,
2894 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state
,
2895 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state
,
2896 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state
,
2897 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform
,
2898 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane
,
2899 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key
,
2900 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material
,
2901 /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light
,
2902 /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable
,
2903 /* WINED3D_CS_OP_SET_FEATURE_LEVEL */ wined3d_cs_exec_set_feature_level
,
2904 /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants
,
2905 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state
,
2906 /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback
,
2907 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue
,
2908 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource
,
2909 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource
,
2910 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map
,
2911 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap
,
2912 /* WINED3D_CS_OP_MAP_BO_ADDRESS */ wined3d_cs_exec_map_bo_address
,
2913 /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource
,
2914 /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource
,
2915 /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region
,
2916 /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view
,
2917 /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter
,
2918 /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps
,
2919 /* WINED3D_CS_OP_EXECUTE_COMMAND_LIST */ wined3d_cs_exec_execute_command_list
,
2922 void wined3d_device_context_emit_execute_command_list(struct wined3d_device_context
*context
,
2923 struct wined3d_command_list
*list
, bool restore_state
)
2925 struct wined3d_cs_execute_command_list
*op
;
2927 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
2928 op
->opcode
= WINED3D_CS_OP_EXECUTE_COMMAND_LIST
;
2931 context
->ops
->reference_command_list(context
, list
);
2933 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
2936 wined3d_device_context_set_state(context
, context
->state
);
2938 wined3d_device_context_reset_state(context
);
2941 static void *wined3d_cs_st_require_space(struct wined3d_device_context
*context
,
2942 size_t size
, enum wined3d_cs_queue_id queue_id
)
2944 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2946 if (size
> (cs
->data_size
- cs
->end
))
2951 new_size
= max(size
, cs
->data_size
* 2);
2953 new_data
= heap_realloc(cs
->data
, new_size
);
2955 new_data
= heap_alloc(new_size
);
2959 cs
->data_size
= new_size
;
2960 cs
->start
= cs
->end
= 0;
2961 cs
->data
= new_data
;
2966 return (BYTE
*)cs
->data
+ cs
->start
;
2969 static void wined3d_cs_st_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2971 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
2972 enum wined3d_cs_op opcode
;
2978 cs
->start
= cs
->end
;
2980 opcode
= *(const enum wined3d_cs_op
*)&data
[start
];
2981 if (opcode
>= WINED3D_CS_OP_STOP
)
2982 ERR("Invalid opcode %#x.\n", opcode
);
2984 wined3d_cs_op_handlers
[opcode
](cs
, &data
[start
]);
2986 if (cs
->data
== data
)
2987 cs
->start
= cs
->end
= start
;
2992 static void wined3d_cs_st_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
2996 static bool wined3d_cs_map_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
2997 unsigned int sub_resource_idx
, struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
2999 struct wined3d_client_resource
*client
= &resource
->client
;
3000 const struct wined3d_format
*format
= resource
->format
;
3003 if (flags
& (WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
3005 const struct wined3d_d3d_info
*d3d_info
= &context
->device
->adapter
->d3d_info
;
3006 struct wined3d_device
*device
= context
->device
;
3007 struct wined3d_bo_address addr
;
3008 struct wined3d_bo
*bo
;
3011 /* We can't use persistent maps if we might need to do vertex attribute
3012 * conversion; that will cause the CS thread to invalidate the BO. */
3013 if (!d3d_info
->xyzrhw
|| !d3d_info
->vertex_bgra
|| !d3d_info
->ffp_generic_attributes
)
3015 TRACE("Not returning a persistent buffer because we might need to do vertex attribute conversion.\n");
3019 if (resource
->pin_sysmem
)
3021 TRACE("Not allocating an upload buffer because system memory is pinned for this resource.\n");
3025 if ((flags
& WINED3D_MAP_NOOVERWRITE
) && client
->addr
.buffer_object
== CLIENT_BO_DISCARDED
)
3026 flags
= (flags
& ~WINED3D_MAP_NOOVERWRITE
) | WINED3D_MAP_DISCARD
;
3028 if (flags
& WINED3D_MAP_DISCARD
)
3030 if (!device
->adapter
->adapter_ops
->adapter_alloc_bo(device
, resource
, sub_resource_idx
, &addr
))
3033 /* Limit NOOVERWRITE maps to buffers for now; there are too many
3034 * ways that a texture can be invalidated to even count. */
3035 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
3036 client
->addr
= addr
;
3040 addr
= client
->addr
;
3044 if ((bo
= addr
.buffer_object
))
3046 wined3d_device_bo_map_lock(device
);
3047 if ((map_ptr
= bo
->map_ptr
))
3048 ++bo
->client_map_count
;
3049 wined3d_device_bo_map_unlock(device
);
3053 /* adapter_alloc_bo() should have given us a mapped BO if we are
3055 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3056 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the BO is not mapped.\n");
3060 map_ptr
+= (uintptr_t)addr
.addr
;
3064 assert(flags
& WINED3D_MAP_NOOVERWRITE
);
3065 WARN_(d3d_perf
)("Not accelerating a NOOVERWRITE map because the sub-resource has no valid address.\n");
3069 wined3d_resource_get_sub_resource_map_pitch(resource
, sub_resource_idx
,
3070 &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3072 client
->mapped_upload
.addr
= *wined3d_const_bo_address(&addr
);
3073 client
->mapped_upload
.flags
= 0;
3076 map_ptr
+= bo
->memory_offset
;
3077 /* If we are not mapping all buffers persistently, use
3078 * UPDATE_SUB_RESOURCE as a means of telling the CS thread to try
3079 * to unmap the resource, so that we can free VA space. */
3080 if (!bo
->coherent
|| !wined3d_map_persistent())
3081 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
;
3083 map_desc
->data
= resource_offset_map_pointer(resource
, sub_resource_idx
, map_ptr
, box
);
3085 if (flags
& WINED3D_MAP_DISCARD
)
3086 client
->mapped_upload
.flags
|= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_RENAME_ON_UNMAP
;
3088 client
->mapped_box
= *box
;
3090 TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client
->mapped_upload
.addr
),
3091 client
->mapped_upload
.flags
);
3095 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
3096 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3098 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
3099 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
3100 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
3102 if (!(map_desc
->data
= heap_alloc(size
)))
3104 WARN_(d3d_perf
)("Failed to allocate a heap memory buffer.\n");
3107 client
->mapped_upload
.addr
.buffer_object
= 0;
3108 client
->mapped_upload
.addr
.addr
= map_desc
->data
;
3109 client
->mapped_upload
.flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
| UPLOAD_BO_FREE_ON_UNMAP
;
3110 client
->mapped_box
= *box
;
3114 static bool wined3d_bo_address_is_null(struct wined3d_const_bo_address
*addr
)
3116 return !addr
->buffer_object
&& !addr
->addr
;
3119 static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context
*context
, struct wined3d_resource
*resource
,
3120 unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*upload_bo
)
3122 struct wined3d_client_resource
*client
= &resource
->client
;
3123 struct wined3d_device
*device
= context
->device
;
3124 struct wined3d_bo
*bo
;
3126 if (wined3d_bo_address_is_null(&client
->mapped_upload
.addr
))
3129 if ((bo
= client
->mapped_upload
.addr
.buffer_object
))
3131 wined3d_device_bo_map_lock(device
);
3132 --bo
->client_map_count
;
3133 wined3d_device_bo_map_unlock(device
);
3136 *upload_bo
= client
->mapped_upload
;
3137 *box
= client
->mapped_box
;
3138 memset(&client
->mapped_upload
, 0, sizeof(client
->mapped_upload
));
3139 memset(&client
->mapped_box
, 0, sizeof(client
->mapped_box
));
3143 static const struct wined3d_device_context_ops wined3d_cs_st_ops
=
3145 wined3d_cs_st_require_space
,
3146 wined3d_cs_st_submit
,
3147 wined3d_cs_st_finish
,
3148 wined3d_cs_st_push_constants
,
3149 wined3d_cs_map_upload_bo
,
3150 wined3d_cs_unmap_upload_bo
,
3151 wined3d_cs_issue_query
,
3153 wined3d_cs_reference_resource
,
3154 wined3d_cs_reference_command_list
,
3157 static BOOL
wined3d_cs_queue_is_empty(const struct wined3d_cs
*cs
, const struct wined3d_cs_queue
*queue
)
3159 wined3d_from_cs(cs
);
3160 return *(volatile ULONG
*)&queue
->head
== queue
->tail
;
3163 static void wined3d_cs_queue_submit(struct wined3d_cs_queue
*queue
, struct wined3d_cs
*cs
)
3165 struct wined3d_cs_packet
*packet
;
3168 packet
= (struct wined3d_cs_packet
*)&queue
->data
[queue
->head
& WINED3D_CS_QUEUE_MASK
];
3169 TRACE("Queuing op %s at %p.\n", debug_cs_op(*(const enum wined3d_cs_op
*)packet
->data
), packet
);
3170 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[packet
->size
]);
3171 InterlockedExchange((LONG
*)&queue
->head
, queue
->head
+ packet_size
);
3173 if (InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3174 SetEvent(cs
->event
);
3177 static void wined3d_cs_mt_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3179 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3181 if (cs
->thread_id
== GetCurrentThreadId())
3182 return wined3d_cs_st_submit(context
, queue_id
);
3184 wined3d_cs_queue_submit(&cs
->queue
[queue_id
], cs
);
3187 static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue
*queue
, size_t size
, struct wined3d_cs
*cs
)
3189 size_t queue_size
= ARRAY_SIZE(queue
->data
);
3190 size_t header_size
, packet_size
, remaining
;
3191 struct wined3d_cs_packet
*packet
;
3192 ULONG head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3194 header_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[0]);
3195 packet_size
= FIELD_OFFSET(struct wined3d_cs_packet
, data
[size
]);
3196 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
3197 size
= packet_size
- header_size
;
3198 if (packet_size
>= WINED3D_CS_QUEUE_SIZE
)
3200 ERR("Packet size %Iu >= queue size %u.\n", packet_size
, WINED3D_CS_QUEUE_SIZE
);
3204 remaining
= queue_size
- head
;
3205 if (remaining
< packet_size
)
3207 size_t nop_size
= remaining
- header_size
;
3208 struct wined3d_cs_nop
*nop
;
3210 TRACE("Inserting a nop for %Iu + %Iu bytes.\n", header_size
, nop_size
);
3212 nop
= wined3d_cs_queue_require_space(queue
, nop_size
, cs
);
3214 nop
->opcode
= WINED3D_CS_OP_NOP
;
3216 wined3d_cs_queue_submit(queue
, cs
);
3217 head
= queue
->head
& WINED3D_CS_QUEUE_MASK
;
3223 ULONG tail
= (*(volatile ULONG
*)&queue
->tail
) & WINED3D_CS_QUEUE_MASK
;
3229 new_pos
= (head
+ packet_size
) & WINED3D_CS_QUEUE_MASK
;
3230 /* Head ahead of tail. We checked the remaining size above, so we only
3231 * need to make sure we don't make head equal to tail. */
3232 if (head
> tail
&& (new_pos
!= tail
))
3234 /* Tail ahead of head. Make sure the new head is before the tail as
3235 * well. Note that new_pos is 0 when it's at the end of the queue. */
3236 if (new_pos
< tail
&& new_pos
)
3239 TRACE("Waiting for free space. Head %lu, tail %lu, packet size %Iu.\n",
3240 head
, tail
, packet_size
);
3243 packet
= (struct wined3d_cs_packet
*)&queue
->data
[head
];
3244 packet
->size
= size
;
3245 return packet
->data
;
3248 static void *wined3d_cs_mt_require_space(struct wined3d_device_context
*context
,
3249 size_t size
, enum wined3d_cs_queue_id queue_id
)
3251 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3253 if (cs
->thread_id
== GetCurrentThreadId())
3254 return wined3d_cs_st_require_space(context
, size
, queue_id
);
3256 return wined3d_cs_queue_require_space(&cs
->queue
[queue_id
], size
, cs
);
3259 static void wined3d_cs_mt_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
3261 struct wined3d_cs
*cs
= wined3d_cs_from_context(context
);
3263 if (cs
->thread_id
== GetCurrentThreadId())
3264 return wined3d_cs_st_finish(context
, queue_id
);
3266 while (cs
->queue
[queue_id
].head
!= *(volatile ULONG
*)&cs
->queue
[queue_id
].tail
)
3270 static const struct wined3d_device_context_ops wined3d_cs_mt_ops
=
3272 wined3d_cs_mt_require_space
,
3273 wined3d_cs_mt_submit
,
3274 wined3d_cs_mt_finish
,
3275 wined3d_cs_mt_push_constants
,
3276 wined3d_cs_map_upload_bo
,
3277 wined3d_cs_unmap_upload_bo
,
3278 wined3d_cs_issue_query
,
3280 wined3d_cs_reference_resource
,
3281 wined3d_cs_reference_command_list
,
3284 static void poll_queries(struct wined3d_cs
*cs
)
3286 struct wined3d_query
*query
, *cursor
;
3288 LIST_FOR_EACH_ENTRY_SAFE(query
, cursor
, &cs
->query_poll_list
, struct wined3d_query
, poll_list_entry
)
3290 if (!query
->query_ops
->query_poll(query
, 0))
3293 list_remove(&query
->poll_list_entry
);
3294 list_init(&query
->poll_list_entry
);
3295 InterlockedIncrement(&query
->counter_retrieved
);
3299 static void wined3d_cs_wait_event(struct wined3d_cs
*cs
)
3301 InterlockedExchange(&cs
->waiting_for_event
, TRUE
);
3303 /* The main thread might have enqueued a command and blocked on it after
3304 * the CS thread decided to enter wined3d_cs_wait_event(), but before
3305 * "waiting_for_event" was set.
3307 * Likewise, we can race with the main thread when resetting
3308 * "waiting_for_event", in which case we would need to call
3309 * WaitForSingleObject() because the main thread called SetEvent(). */
3310 if (!(wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
])
3311 && wined3d_cs_queue_is_empty(cs
, &cs
->queue
[WINED3D_CS_QUEUE_MAP
]))
3312 && InterlockedCompareExchange(&cs
->waiting_for_event
, FALSE
, TRUE
))
3315 WaitForSingleObject(cs
->event
, INFINITE
);
3318 static void wined3d_cs_command_lock(const struct wined3d_cs
*cs
)
3320 if (cs
->serialize_commands
)
3321 EnterCriticalSection(&wined3d_command_cs
);
3324 static void wined3d_cs_command_unlock(const struct wined3d_cs
*cs
)
3326 if (cs
->serialize_commands
)
3327 LeaveCriticalSection(&wined3d_command_cs
);
3330 static inline bool wined3d_cs_execute_next(struct wined3d_cs
*cs
, struct wined3d_cs_queue
*queue
)
3332 struct wined3d_cs_packet
*packet
;
3333 enum wined3d_cs_op opcode
;
3337 packet
= wined3d_next_cs_packet(queue
->data
, &tail
, WINED3D_CS_QUEUE_MASK
);
3341 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3343 TRACE("Executing %s at %p.\n", debug_cs_op(opcode
), packet
);
3344 if (opcode
>= WINED3D_CS_OP_STOP
)
3346 if (opcode
> WINED3D_CS_OP_STOP
)
3347 ERR("Invalid opcode %#x.\n", opcode
);
3351 wined3d_cs_command_lock(cs
);
3352 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3353 wined3d_cs_command_unlock(cs
);
3354 TRACE("%s at %p executed.\n", debug_cs_op(opcode
), packet
);
3357 InterlockedExchange((LONG
*)&queue
->tail
, tail
);
3361 static void wined3d_cs_exec_execute_command_list(struct wined3d_cs
*cs
, const void *data
)
3363 const struct wined3d_cs_execute_command_list
*op
= data
;
3364 SIZE_T start
= 0, end
= op
->list
->data_size
;
3365 const BYTE
*cs_data
= op
->list
->data
;
3366 struct wined3d_cs_queue
*queue
;
3368 TRACE("Executing command list %p.\n", op
->list
);
3370 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3373 const struct wined3d_cs_packet
*packet
;
3374 enum wined3d_cs_op opcode
;
3376 while (!wined3d_cs_queue_is_empty(cs
, queue
))
3377 wined3d_cs_execute_next(cs
, queue
);
3379 packet
= wined3d_next_cs_packet(cs_data
, &start
, WINED3D_CS_QUEUE_MASK
);
3380 opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3382 if (opcode
>= WINED3D_CS_OP_STOP
)
3383 ERR("Invalid opcode %#x.\n", opcode
);
3385 wined3d_cs_op_handlers
[opcode
](cs
, packet
->data
);
3386 TRACE("%s executed.\n", debug_cs_op(opcode
));
3390 static DWORD WINAPI
wined3d_cs_run(void *ctx
)
3392 struct wined3d_cs_queue
*queue
;
3393 unsigned int spin_count
= 0;
3394 struct wined3d_cs
*cs
= ctx
;
3395 HMODULE wined3d_module
;
3396 unsigned int poll
= 0;
3399 TRACE("Started.\n");
3400 SetThreadDescription(GetCurrentThread(), L
"wined3d_cs");
3402 /* Copy the module handle to a local variable to avoid racing with the
3403 * thread freeing "cs" before the FreeLibraryAndExitThread() call. */
3404 wined3d_module
= cs
->wined3d_module
;
3406 list_init(&cs
->query_poll_list
);
3407 cs
->thread_id
= GetCurrentThreadId();
3410 if (++poll
== WINED3D_CS_QUERY_POLL_INTERVAL
)
3412 wined3d_cs_command_lock(cs
);
3414 wined3d_cs_command_unlock(cs
);
3418 queue
= &cs
->queue
[WINED3D_CS_QUEUE_MAP
];
3419 if (wined3d_cs_queue_is_empty(cs
, queue
))
3421 queue
= &cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
];
3422 if (wined3d_cs_queue_is_empty(cs
, queue
))
3425 if (++spin_count
>= WINED3D_CS_SPIN_COUNT
)
3427 if (list_empty(&cs
->query_poll_list
))
3428 wined3d_cs_wait_event(cs
);
3437 run
= wined3d_cs_execute_next(cs
, queue
);
3440 cs
->queue
[WINED3D_CS_QUEUE_MAP
].tail
= cs
->queue
[WINED3D_CS_QUEUE_MAP
].head
;
3441 cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].tail
= cs
->queue
[WINED3D_CS_QUEUE_DEFAULT
].head
;
3442 TRACE("Stopped.\n");
3443 FreeLibraryAndExitThread(wined3d_module
, 0);
3446 struct wined3d_cs
*wined3d_cs_create(struct wined3d_device
*device
,
3447 const enum wined3d_feature_level
*levels
, unsigned int level_count
)
3449 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3450 struct wined3d_cs
*cs
;
3452 if (!(cs
= heap_alloc_zero(sizeof(*cs
))))
3455 if (FAILED(wined3d_state_create(device
, levels
, level_count
, &cs
->c
.state
)))
3461 cs
->c
.ops
= &wined3d_cs_st_ops
;
3462 cs
->c
.device
= device
;
3463 cs
->serialize_commands
= TRACE_ON(d3d_sync
) || wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_SERIALIZE
;
3465 if (cs
->serialize_commands
)
3466 ERR_(d3d_sync
)("Forcing serialization of all command streams.\n");
3468 state_init(&cs
->state
, d3d_info
, WINED3D_STATE_NO_REF
| WINED3D_STATE_INIT_DEFAULT
, cs
->c
.state
->feature_level
);
3470 cs
->data_size
= WINED3D_INITIAL_CS_SIZE
;
3471 if (!(cs
->data
= heap_alloc(cs
->data_size
)))
3474 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
)
3476 if (!d3d_info
->fences
)
3478 WARN("Disabling CSMT, adapter doesn't support fences.\n");
3479 wined3d_settings
.cs_multithreaded
&= ~WINED3D_CSMT_ENABLE
;
3483 if (wined3d_settings
.cs_multithreaded
& WINED3D_CSMT_ENABLE
3484 && !RtlIsCriticalSectionLockedByThread(NtCurrentTeb()->Peb
->LoaderLock
))
3486 cs
->c
.ops
= &wined3d_cs_mt_ops
;
3488 if (!(cs
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
3490 ERR("Failed to create command stream event.\n");
3491 heap_free(cs
->data
);
3494 if (!(cs
->present_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
3496 ERR("Failed to create command stream present event.\n");
3497 heap_free(cs
->data
);
3501 if (!(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
3502 (const WCHAR
*)wined3d_cs_run
, &cs
->wined3d_module
)))
3504 ERR("Failed to get wined3d module handle.\n");
3505 CloseHandle(cs
->present_event
);
3506 CloseHandle(cs
->event
);
3507 heap_free(cs
->data
);
3511 if (!(cs
->thread
= CreateThread(NULL
, 0, wined3d_cs_run
, cs
, 0, NULL
)))
3513 ERR("Failed to create wined3d command stream thread.\n");
3514 FreeLibrary(cs
->wined3d_module
);
3515 CloseHandle(cs
->present_event
);
3516 CloseHandle(cs
->event
);
3517 heap_free(cs
->data
);
3522 TRACE("Created command stream %p.\n", cs
);
3526 wined3d_state_destroy(cs
->c
.state
);
3527 state_cleanup(&cs
->state
);
3532 void wined3d_cs_destroy(struct wined3d_cs
*cs
)
3536 wined3d_cs_emit_stop(cs
);
3537 CloseHandle(cs
->thread
);
3538 if (!CloseHandle(cs
->present_event
))
3539 ERR("Closing present event failed.\n");
3540 if (!CloseHandle(cs
->event
))
3541 ERR("Closing event failed.\n");
3544 wined3d_state_destroy(cs
->c
.state
);
3545 state_cleanup(&cs
->state
);
3546 heap_free(cs
->data
);
3550 static void wined3d_cs_packet_decref_objects(const struct wined3d_cs_packet
*packet
)
3552 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3557 case WINED3D_CS_OP_SET_SAMPLERS
:
3559 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3561 for (i
= 0; i
< op
->count
; ++i
)
3563 if (op
->samplers
[i
])
3564 wined3d_sampler_decref(op
->samplers
[i
]);
3569 case WINED3D_CS_OP_SET_SHADER
:
3571 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3574 wined3d_shader_decref(op
->shader
);
3578 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3580 struct wined3d_cs_set_depth_stencil_state
*op
;
3582 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3584 wined3d_depth_stencil_state_decref(op
->state
);
3588 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3590 struct wined3d_cs_set_rasterizer_state
*op
;
3592 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3594 wined3d_rasterizer_state_decref(op
->state
);
3598 case WINED3D_CS_OP_SET_BLEND_STATE
:
3600 struct wined3d_cs_set_blend_state
*op
;
3602 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3604 wined3d_blend_state_decref(op
->state
);
3608 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3610 struct wined3d_cs_set_rendertarget_views
*op
;
3612 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3613 for (i
= 0; i
< op
->count
; ++i
)
3616 wined3d_rendertarget_view_decref(op
->views
[i
]);
3621 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3623 struct wined3d_cs_set_shader_resource_views
*op
;
3625 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3626 for (i
= 0; i
< op
->count
; ++i
)
3629 wined3d_shader_resource_view_decref(op
->views
[i
]);
3634 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3636 struct wined3d_cs_set_unordered_access_views
*op
;
3638 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3639 for (i
= 0; i
< op
->count
; ++i
)
3641 if (op
->uavs
[i
].view
)
3642 wined3d_unordered_access_view_decref(op
->uavs
[i
].view
);
3647 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3649 struct wined3d_cs_set_depth_stencil_view
*op
;
3651 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3653 wined3d_rendertarget_view_decref(op
->view
);
3657 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3659 struct wined3d_cs_set_constant_buffers
*op
;
3661 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3662 for (i
= 0; i
< op
->count
; ++i
)
3664 if (op
->buffers
[i
].buffer
)
3665 wined3d_buffer_decref(op
->buffers
[i
].buffer
);
3670 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3672 struct wined3d_cs_clear_unordered_access_view
*op
;
3674 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3675 wined3d_unordered_access_view_decref(op
->view
);
3679 case WINED3D_CS_OP_CLEAR
:
3681 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3683 for (i
= 0; i
< op
->rt_count
; ++i
)
3685 if (op
->fb
.render_targets
[i
])
3686 wined3d_rendertarget_view_decref(op
->fb
.render_targets
[i
]);
3688 if (op
->fb
.depth_stencil
)
3689 wined3d_rendertarget_view_decref(op
->fb
.depth_stencil
);
3693 case WINED3D_CS_OP_DISPATCH
:
3695 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3697 if (op
->parameters
.indirect
)
3698 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3702 case WINED3D_CS_OP_DRAW
:
3704 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3706 if (op
->parameters
.indirect
)
3707 wined3d_buffer_decref(op
->parameters
.u
.indirect
.buffer
);
3711 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3713 struct wined3d_cs_set_index_buffer
*op
;
3715 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3717 wined3d_buffer_decref(op
->buffer
);
3721 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3723 struct wined3d_cs_set_stream_outputs
*op
;
3725 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3726 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3728 if (op
->outputs
[i
].buffer
)
3729 wined3d_buffer_decref(op
->outputs
[i
].buffer
);
3734 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3736 struct wined3d_cs_set_stream_sources
*op
;
3738 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3739 for (i
= 0; i
< op
->count
; ++i
)
3741 if (op
->streams
[i
].buffer
)
3742 wined3d_buffer_decref(op
->streams
[i
].buffer
);
3747 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3749 struct wined3d_cs_update_sub_resource
*op
;
3751 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3752 wined3d_resource_decref(op
->resource
);
3756 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3758 struct wined3d_cs_blt_sub_resource
*op
;
3760 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
3761 if (op
->src_resource
)
3762 wined3d_resource_decref(op
->src_resource
);
3763 wined3d_resource_decref(op
->dst_resource
);
3767 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
3769 struct wined3d_cs_copy_uav_counter
*op
;
3771 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
3772 wined3d_buffer_decref(op
->buffer
);
3773 wined3d_unordered_access_view_decref(op
->view
);
3777 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
3779 struct wined3d_cs_generate_mipmaps
*op
;
3781 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
3782 wined3d_shader_resource_view_decref(op
->view
);
3791 static void wined3d_cs_packet_incref_objects(struct wined3d_cs_packet
*packet
)
3793 enum wined3d_cs_op opcode
= *(const enum wined3d_cs_op
*)packet
->data
;
3798 case WINED3D_CS_OP_SET_SAMPLERS
:
3800 struct wined3d_cs_set_samplers
*op
= (struct wined3d_cs_set_samplers
*)packet
->data
;
3802 for (i
= 0; i
< op
->count
; ++i
)
3804 if (op
->samplers
[i
])
3805 wined3d_sampler_incref(op
->samplers
[i
]);
3810 case WINED3D_CS_OP_SET_SHADER
:
3812 struct wined3d_cs_set_shader
*op
= (struct wined3d_cs_set_shader
*)packet
->data
;
3815 wined3d_shader_incref(op
->shader
);
3819 case WINED3D_CS_OP_SET_DEPTH_STENCIL_STATE
:
3821 struct wined3d_cs_set_depth_stencil_state
*op
;
3823 op
= (struct wined3d_cs_set_depth_stencil_state
*)packet
->data
;
3825 wined3d_depth_stencil_state_incref(op
->state
);
3829 case WINED3D_CS_OP_SET_RASTERIZER_STATE
:
3831 struct wined3d_cs_set_rasterizer_state
*op
;
3833 op
= (struct wined3d_cs_set_rasterizer_state
*)packet
->data
;
3835 wined3d_rasterizer_state_incref(op
->state
);
3839 case WINED3D_CS_OP_SET_BLEND_STATE
:
3841 struct wined3d_cs_set_blend_state
*op
;
3843 op
= (struct wined3d_cs_set_blend_state
*)packet
->data
;
3845 wined3d_blend_state_incref(op
->state
);
3849 case WINED3D_CS_OP_SET_RENDERTARGET_VIEWS
:
3851 struct wined3d_cs_set_rendertarget_views
*op
;
3853 op
= (struct wined3d_cs_set_rendertarget_views
*)packet
->data
;
3854 for (i
= 0; i
< op
->count
; ++i
)
3857 wined3d_rendertarget_view_incref(op
->views
[i
]);
3862 case WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEWS
:
3864 struct wined3d_cs_set_shader_resource_views
*op
;
3866 op
= (struct wined3d_cs_set_shader_resource_views
*)packet
->data
;
3867 for (i
= 0; i
< op
->count
; ++i
)
3870 wined3d_shader_resource_view_incref(op
->views
[i
]);
3875 case WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEWS
:
3877 struct wined3d_cs_set_unordered_access_views
*op
;
3879 op
= (struct wined3d_cs_set_unordered_access_views
*)packet
->data
;
3880 for (i
= 0; i
< op
->count
; ++i
)
3882 if (op
->uavs
[i
].view
)
3883 wined3d_unordered_access_view_incref(op
->uavs
[i
].view
);
3888 case WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW
:
3890 struct wined3d_cs_set_depth_stencil_view
*op
;
3892 op
= (struct wined3d_cs_set_depth_stencil_view
*)packet
->data
;
3894 wined3d_rendertarget_view_incref(op
->view
);
3898 case WINED3D_CS_OP_SET_CONSTANT_BUFFERS
:
3900 struct wined3d_cs_set_constant_buffers
*op
;
3902 op
= (struct wined3d_cs_set_constant_buffers
*)packet
->data
;
3903 for (i
= 0; i
< op
->count
; ++i
)
3905 if (op
->buffers
[i
].buffer
)
3906 wined3d_buffer_incref(op
->buffers
[i
].buffer
);
3911 case WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW
:
3913 struct wined3d_cs_clear_unordered_access_view
*op
;
3915 op
= (struct wined3d_cs_clear_unordered_access_view
*)packet
->data
;
3916 wined3d_unordered_access_view_incref(op
->view
);
3920 case WINED3D_CS_OP_CLEAR
:
3922 struct wined3d_cs_clear
*op
= (struct wined3d_cs_clear
*)packet
->data
;
3924 for (i
= 0; i
< op
->rt_count
; ++i
)
3926 if (op
->fb
.render_targets
[i
])
3927 wined3d_rendertarget_view_incref(op
->fb
.render_targets
[i
]);
3929 if (op
->fb
.depth_stencil
)
3930 wined3d_rendertarget_view_incref(op
->fb
.depth_stencil
);
3934 case WINED3D_CS_OP_DISPATCH
:
3936 struct wined3d_cs_dispatch
*op
= (struct wined3d_cs_dispatch
*)packet
->data
;
3938 if (op
->parameters
.indirect
)
3939 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3943 case WINED3D_CS_OP_DRAW
:
3945 struct wined3d_cs_draw
*op
= (struct wined3d_cs_draw
*)packet
->data
;
3947 if (op
->parameters
.indirect
)
3948 wined3d_buffer_incref(op
->parameters
.u
.indirect
.buffer
);
3952 case WINED3D_CS_OP_SET_INDEX_BUFFER
:
3954 struct wined3d_cs_set_index_buffer
*op
;
3956 op
= (struct wined3d_cs_set_index_buffer
*)packet
->data
;
3958 wined3d_buffer_incref(op
->buffer
);
3962 case WINED3D_CS_OP_SET_STREAM_OUTPUTS
:
3964 struct wined3d_cs_set_stream_outputs
*op
;
3966 op
= (struct wined3d_cs_set_stream_outputs
*)packet
->data
;
3967 for (i
= 0; i
< ARRAY_SIZE(op
->outputs
); ++i
)
3969 if (op
->outputs
[i
].buffer
)
3970 wined3d_buffer_incref(op
->outputs
[i
].buffer
);
3975 case WINED3D_CS_OP_SET_STREAM_SOURCES
:
3977 struct wined3d_cs_set_stream_sources
*op
;
3979 op
= (struct wined3d_cs_set_stream_sources
*)packet
->data
;
3980 for (i
= 0; i
< op
->count
; ++i
)
3982 if (op
->streams
[i
].buffer
)
3983 wined3d_buffer_incref(op
->streams
[i
].buffer
);
3988 case WINED3D_CS_OP_UPDATE_SUB_RESOURCE
:
3990 struct wined3d_cs_update_sub_resource
*op
;
3992 op
= (struct wined3d_cs_update_sub_resource
*)packet
->data
;
3993 wined3d_resource_incref(op
->resource
);
3997 case WINED3D_CS_OP_BLT_SUB_RESOURCE
:
3999 struct wined3d_cs_blt_sub_resource
*op
;
4001 op
= (struct wined3d_cs_blt_sub_resource
*)packet
->data
;
4002 if (op
->src_resource
)
4003 wined3d_resource_incref(op
->src_resource
);
4004 wined3d_resource_incref(op
->dst_resource
);
4008 case WINED3D_CS_OP_COPY_UAV_COUNTER
:
4010 struct wined3d_cs_copy_uav_counter
*op
;
4012 op
= (struct wined3d_cs_copy_uav_counter
*)packet
->data
;
4013 wined3d_buffer_incref(op
->buffer
);
4014 wined3d_unordered_access_view_incref(op
->view
);
4018 case WINED3D_CS_OP_GENERATE_MIPMAPS
:
4020 struct wined3d_cs_generate_mipmaps
*op
;
4022 op
= (struct wined3d_cs_generate_mipmaps
*)packet
->data
;
4023 wined3d_shader_resource_view_incref(op
->view
);
4032 struct wined3d_deferred_context
4034 struct wined3d_device_context c
;
4036 SIZE_T data_size
, data_capacity
;
4039 SIZE_T resource_count
, resources_capacity
;
4040 struct wined3d_resource
**resources
;
4042 SIZE_T upload_count
, uploads_capacity
;
4043 struct wined3d_deferred_upload
*uploads
;
4046 LONG
*upload_heap_refcount
;
4048 /* List of command lists queued for execution on this context. A command
4049 * list can be the only thing holding a pointer to another command list, so
4050 * we need to hold a reference here and in wined3d_command_list as well. */
4051 SIZE_T command_list_count
, command_lists_capacity
;
4052 struct wined3d_command_list
**command_lists
;
4054 SIZE_T query_count
, queries_capacity
;
4055 struct wined3d_deferred_query_issue
*queries
;
4058 static struct wined3d_deferred_context
*wined3d_deferred_context_from_context(struct wined3d_device_context
*context
)
4060 return CONTAINING_RECORD(context
, struct wined3d_deferred_context
, c
);
4063 static void *wined3d_deferred_context_require_space(struct wined3d_device_context
*context
,
4064 size_t size
, enum wined3d_cs_queue_id queue_id
)
4066 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4067 struct wined3d_cs_packet
*packet
;
4068 size_t header_size
, packet_size
;
4070 if (queue_id
!= WINED3D_CS_QUEUE_DEFAULT
)
4073 header_size
= offsetof(struct wined3d_cs_packet
, data
[0]);
4074 packet_size
= offsetof(struct wined3d_cs_packet
, data
[size
]);
4075 packet_size
= (packet_size
+ header_size
- 1) & ~(header_size
- 1);
4077 if (!wined3d_array_reserve(&deferred
->data
, &deferred
->data_capacity
, deferred
->data_size
+ packet_size
, 1))
4080 packet
= (struct wined3d_cs_packet
*)((BYTE
*)deferred
->data
+ deferred
->data_size
);
4081 TRACE("size was %Iu, adding %Iu\n", (size_t)deferred
->data_size
, packet_size
);
4082 packet
->size
= packet_size
- header_size
;
4083 return &packet
->data
;
4086 static void wined3d_deferred_context_submit(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4088 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4089 struct wined3d_cs_packet
*packet
;
4091 assert(queue_id
== WINED3D_CS_QUEUE_DEFAULT
);
4092 packet
= wined3d_next_cs_packet(deferred
->data
, &deferred
->data_size
, ~(SIZE_T
)0);
4093 wined3d_cs_packet_incref_objects(packet
);
4096 static void wined3d_deferred_context_finish(struct wined3d_device_context
*context
, enum wined3d_cs_queue_id queue_id
)
4098 /* This should not happen; we cannot meaningfully finish a deferred context. */
4099 ERR("Ignoring finish() on a deferred context.\n");
4102 static void wined3d_deferred_context_push_constants(struct wined3d_device_context
*context
,
4103 enum wined3d_push_constants p
, unsigned int start_idx
, unsigned int count
, const void *constants
)
4105 FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context
, p
, start_idx
, count
, constants
);
4108 static struct wined3d_deferred_upload
*deferred_context_get_upload(struct wined3d_deferred_context
*deferred
,
4109 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
4111 SIZE_T i
= deferred
->upload_count
;
4115 struct wined3d_deferred_upload
*upload
= &deferred
->uploads
[i
];
4117 if (upload
->resource
== resource
&& upload
->sub_resource_idx
== sub_resource_idx
)
4124 static bool wined3d_deferred_context_map_upload_bo(struct wined3d_device_context
*context
,
4125 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
4126 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, uint32_t flags
)
4128 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4129 const struct wined3d_format
*format
= resource
->format
;
4130 struct wined3d_deferred_upload
*upload
;
4134 wined3d_format_calculate_pitch(format
, 1, box
->right
- box
->left
,
4135 box
->bottom
- box
->top
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
4137 size
= (box
->back
- box
->front
- 1) * map_desc
->slice_pitch
4138 + ((box
->bottom
- box
->top
- 1) / format
->block_height
) * map_desc
->row_pitch
4139 + ((box
->right
- box
->left
+ format
->block_width
- 1) / format
->block_width
) * format
->block_byte_count
;
4141 if (!(flags
& WINED3D_MAP_WRITE
))
4143 WARN("Flags %#x are not valid on a deferred context.\n", flags
);
4147 if (flags
& ~(WINED3D_MAP_WRITE
| WINED3D_MAP_DISCARD
| WINED3D_MAP_NOOVERWRITE
))
4149 FIXME("Unhandled flags %#x.\n", flags
);
4153 if (flags
& WINED3D_MAP_NOOVERWRITE
)
4155 if (!(upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4158 upload
->upload_flags
= 0;
4159 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4163 if (!wined3d_array_reserve((void **)&deferred
->uploads
, &deferred
->uploads_capacity
,
4164 deferred
->upload_count
+ 1, sizeof(*deferred
->uploads
)))
4167 if (!deferred
->upload_heap
)
4169 if (!(deferred
->upload_heap
= HeapCreate(0, 0, 0)))
4171 ERR("Failed to create upload heap.\n");
4175 if (!(deferred
->upload_heap_refcount
= heap_alloc(sizeof(*deferred
->upload_heap_refcount
))))
4177 HeapDestroy(deferred
->upload_heap
);
4178 deferred
->upload_heap
= 0;
4182 *deferred
->upload_heap_refcount
= 1;
4185 if (!(sysmem
= HeapAlloc(deferred
->upload_heap
, 0, size
+ RESOURCE_ALIGNMENT
- 1)))
4188 upload
= &deferred
->uploads
[deferred
->upload_count
++];
4189 upload
->upload_flags
= UPLOAD_BO_UPLOAD_ON_UNMAP
;
4190 upload
->resource
= resource
;
4191 wined3d_resource_incref(resource
);
4192 upload
->sub_resource_idx
= sub_resource_idx
;
4193 upload
->sysmem
= sysmem
;
4196 map_desc
->data
= (void *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4200 static bool wined3d_deferred_context_unmap_upload_bo(struct wined3d_device_context
*context
,
4201 struct wined3d_resource
*resource
, unsigned int sub_resource_idx
, struct wined3d_box
*box
, struct upload_bo
*bo
)
4203 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4204 const struct wined3d_deferred_upload
*upload
;
4206 if ((upload
= deferred_context_get_upload(deferred
, resource
, sub_resource_idx
)))
4209 bo
->addr
.buffer_object
= 0;
4210 bo
->addr
.addr
= (uint8_t *)align((size_t)upload
->sysmem
, RESOURCE_ALIGNMENT
);
4211 bo
->flags
= upload
->upload_flags
;
4218 static void wined3d_deferred_context_issue_query(struct wined3d_device_context
*context
,
4219 struct wined3d_query
*query
, unsigned int flags
)
4221 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4222 struct wined3d_cs_query_issue
*op
;
4224 op
= wined3d_device_context_require_space(context
, sizeof(*op
), WINED3D_CS_QUEUE_DEFAULT
);
4225 op
->opcode
= WINED3D_CS_OP_QUERY_ISSUE
;
4229 wined3d_device_context_submit(context
, WINED3D_CS_QUEUE_DEFAULT
);
4231 if (!wined3d_array_reserve((void **)&deferred
->queries
, &deferred
->queries_capacity
,
4232 deferred
->query_count
+ 1, sizeof(*deferred
->queries
)))
4234 ERR("Failed to reserve memory.\n");
4238 deferred
->queries
[deferred
->query_count
].flags
= flags
;
4239 wined3d_query_incref(deferred
->queries
[deferred
->query_count
++].query
= query
);
4242 static void wined3d_deferred_context_flush(struct wined3d_device_context
*context
)
4244 FIXME("context %p, stub!\n", context
);
4247 static void wined3d_deferred_context_reference_resource(struct wined3d_device_context
*context
,
4248 struct wined3d_resource
*resource
)
4250 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4252 if (!wined3d_array_reserve((void **)&deferred
->resources
, &deferred
->resources_capacity
,
4253 deferred
->resource_count
+ 1, sizeof(*deferred
->resources
)))
4256 deferred
->resources
[deferred
->resource_count
++] = resource
;
4257 wined3d_resource_incref(resource
);
4260 static void wined3d_deferred_context_reference_command_list(struct wined3d_device_context
*context
,
4261 struct wined3d_command_list
*list
)
4263 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4265 /* Grab a reference to the command list. Note that this implicitly prevents
4266 * any dependent command lists or resources from being freed as well. */
4267 if (!wined3d_array_reserve((void **)&deferred
->command_lists
, &deferred
->command_lists_capacity
,
4268 deferred
->command_list_count
+ 1, sizeof(*deferred
->command_lists
)))
4271 wined3d_command_list_incref(deferred
->command_lists
[deferred
->command_list_count
++] = list
);
4274 static const struct wined3d_device_context_ops wined3d_deferred_context_ops
=
4276 wined3d_deferred_context_require_space
,
4277 wined3d_deferred_context_submit
,
4278 wined3d_deferred_context_finish
,
4279 wined3d_deferred_context_push_constants
,
4280 wined3d_deferred_context_map_upload_bo
,
4281 wined3d_deferred_context_unmap_upload_bo
,
4282 wined3d_deferred_context_issue_query
,
4283 wined3d_deferred_context_flush
,
4284 wined3d_deferred_context_reference_resource
,
4285 wined3d_deferred_context_reference_command_list
,
4288 HRESULT CDECL
wined3d_deferred_context_create(struct wined3d_device
*device
, struct wined3d_device_context
**context
)
4290 struct wined3d_deferred_context
*object
;
4293 TRACE("device %p, context %p.\n", device
, context
);
4295 if (!(object
= heap_alloc_zero(sizeof(*object
))))
4296 return E_OUTOFMEMORY
;
4298 if (FAILED(hr
= wined3d_state_create(device
, &device
->cs
->c
.state
->feature_level
, 1, &object
->c
.state
)))
4304 object
->c
.ops
= &wined3d_deferred_context_ops
;
4305 object
->c
.device
= device
;
4307 /* Make sure the first command list gets the state reset when executed.
4308 * Resets for subsequent command lists are encoded in wined3d_deferred_context_record_command_list(). */
4309 wined3d_device_context_emit_reset_state(&object
->c
, true);
4311 TRACE("Created deferred context %p.\n", object
);
4312 *context
= &object
->c
;
4317 void CDECL
wined3d_deferred_context_destroy(struct wined3d_device_context
*context
)
4319 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4320 const struct wined3d_cs_packet
*packet
;
4321 SIZE_T i
, offset
= 0;
4323 TRACE("context %p.\n", context
);
4325 for (i
= 0; i
< deferred
->resource_count
; ++i
)
4326 wined3d_resource_decref(deferred
->resources
[i
]);
4327 heap_free(deferred
->resources
);
4329 for (i
= 0; i
< deferred
->upload_count
; ++i
)
4331 wined3d_resource_decref(deferred
->uploads
[i
].resource
);
4332 HeapFree(deferred
->upload_heap
, 0, deferred
->uploads
[i
].resource
);
4335 if (deferred
->upload_heap
)
4337 if (!InterlockedDecrement(deferred
->upload_heap_refcount
))
4339 HeapDestroy(deferred
->upload_heap
);
4340 heap_free(deferred
->upload_heap_refcount
);
4344 heap_free(deferred
->uploads
);
4346 for (i
= 0; i
< deferred
->command_list_count
; ++i
)
4347 wined3d_command_list_decref(deferred
->command_lists
[i
]);
4348 heap_free(deferred
->command_lists
);
4350 for (i
= 0; i
< deferred
->query_count
; ++i
)
4351 wined3d_query_decref(deferred
->queries
[i
].query
);
4352 heap_free(deferred
->queries
);
4354 while (offset
< deferred
->data_size
)
4356 packet
= wined3d_next_cs_packet(deferred
->data
, &offset
, ~(SIZE_T
)0);
4357 wined3d_cs_packet_decref_objects(packet
);
4360 wined3d_state_destroy(deferred
->c
.state
);
4361 heap_free(deferred
->data
);
4362 heap_free(deferred
);
4365 HRESULT CDECL
wined3d_deferred_context_record_command_list(struct wined3d_device_context
*context
,
4366 bool restore
, struct wined3d_command_list
**list
)
4368 struct wined3d_deferred_context
*deferred
= wined3d_deferred_context_from_context(context
);
4369 struct wined3d_command_list
*object
;
4372 TRACE("context %p, list %p.\n", context
, list
);
4374 wined3d_device_context_lock(context
);
4375 memory
= heap_alloc(sizeof(*object
) + deferred
->resource_count
* sizeof(*object
->resources
)
4376 + deferred
->upload_count
* sizeof(*object
->uploads
)
4377 + deferred
->command_list_count
* sizeof(*object
->command_lists
)
4378 + deferred
->query_count
* sizeof(*object
->queries
)
4379 + deferred
->data_size
);
4383 wined3d_device_context_unlock(context
);
4384 return E_OUTOFMEMORY
;
4388 memory
= &object
[1];
4389 memset(object
, 0, sizeof(*object
));
4390 object
->refcount
= 1;
4391 object
->device
= deferred
->c
.device
;
4393 object
->resources
= memory
;
4394 memory
= &object
->resources
[deferred
->resource_count
];
4395 object
->resource_count
= deferred
->resource_count
;
4396 memcpy(object
->resources
, deferred
->resources
, deferred
->resource_count
* sizeof(*object
->resources
));
4397 /* Transfer our references to the resources to the command list. */
4399 object
->uploads
= memory
;
4400 memory
= &object
->uploads
[deferred
->upload_count
];
4401 object
->upload_count
= deferred
->upload_count
;
4402 memcpy(object
->uploads
, deferred
->uploads
, deferred
->upload_count
* sizeof(*object
->uploads
));
4403 /* Transfer our references to the resources to the command list. */
4405 object
->command_lists
= memory
;
4406 memory
= &object
->command_lists
[deferred
->command_list_count
];
4407 object
->command_list_count
= deferred
->command_list_count
;
4408 memcpy(object
->command_lists
, deferred
->command_lists
,
4409 deferred
->command_list_count
* sizeof(*object
->command_lists
));
4410 /* Transfer our references to the command lists to the command list. */
4412 object
->queries
= memory
;
4413 memory
= &object
->queries
[deferred
->query_count
];
4414 object
->query_count
= deferred
->query_count
;
4415 memcpy(object
->queries
, deferred
->queries
, deferred
->query_count
* sizeof(*object
->queries
));
4416 /* Transfer our references to the queries to the command list. */
4418 object
->data
= memory
;
4419 object
->data_size
= deferred
->data_size
;
4420 memcpy(object
->data
, deferred
->data
, deferred
->data_size
);
4422 deferred
->data_size
= 0;
4423 deferred
->resource_count
= 0;
4424 deferred
->upload_count
= 0;
4425 deferred
->command_list_count
= 0;
4426 deferred
->query_count
= 0;
4428 object
->upload_heap
= deferred
->upload_heap
;
4429 if ((object
->upload_heap_refcount
= deferred
->upload_heap_refcount
))
4430 InterlockedIncrement(object
->upload_heap_refcount
);
4432 /* This is in fact recorded into a subsequent command list. */
4434 wined3d_device_context_set_state(&deferred
->c
, deferred
->c
.state
);
4436 wined3d_device_context_reset_state(&deferred
->c
);
4438 TRACE("Created command list %p.\n", object
);
4440 wined3d_device_context_unlock(context
);
4445 static void wined3d_command_list_destroy_object(void *object
)
4447 struct wined3d_command_list
*list
= object
;
4450 TRACE("list %p.\n", list
);
4452 for (i
= 0; i
< list
->upload_count
; ++i
)
4453 HeapFree(list
->upload_heap
, 0, list
->uploads
[i
].sysmem
);
4455 if (list
->upload_heap
)
4457 if (!InterlockedDecrement(list
->upload_heap_refcount
))
4459 HeapDestroy(list
->upload_heap
);
4460 heap_free(list
->upload_heap_refcount
);
4467 ULONG CDECL
wined3d_command_list_incref(struct wined3d_command_list
*list
)
4469 unsigned int refcount
= InterlockedIncrement(&list
->refcount
);
4471 TRACE("%p increasing refcount to %u.\n", list
, refcount
);
4476 ULONG CDECL
wined3d_command_list_decref(struct wined3d_command_list
*list
)
4478 unsigned int refcount
= InterlockedDecrement(&list
->refcount
);
4479 struct wined3d_device
*device
= list
->device
;
4480 const struct wined3d_cs_packet
*packet
;
4483 TRACE("%p decreasing refcount to %u.\n", list
, refcount
);
4487 for (i
= 0; i
< list
->command_list_count
; ++i
)
4488 wined3d_command_list_decref(list
->command_lists
[i
]);
4489 for (i
= 0; i
< list
->resource_count
; ++i
)
4490 wined3d_resource_decref(list
->resources
[i
]);
4491 for (i
= 0; i
< list
->upload_count
; ++i
)
4492 wined3d_resource_decref(list
->uploads
[i
].resource
);
4493 for (i
= 0; i
< list
->query_count
; ++i
)
4494 wined3d_query_decref(list
->queries
[i
].query
);
4497 while (offset
< list
->data_size
)
4499 packet
= wined3d_next_cs_packet(list
->data
, &offset
, ~(SIZE_T
)0);
4500 wined3d_cs_packet_decref_objects(packet
);
4503 wined3d_mutex_lock();
4504 wined3d_cs_destroy_object(device
->cs
, wined3d_command_list_destroy_object
, list
);
4505 wined3d_mutex_unlock();