wined3d: Fix bind count for shader resource views.
[wine.git] / dlls / wined3d / cs.c
blob3a46a3c9a30f125775108421686175c800d89128
1 /*
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 "config.h"
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
25 #define WINED3D_INITIAL_CS_SIZE 4096
27 enum wined3d_cs_op
29 WINED3D_CS_OP_PRESENT,
30 WINED3D_CS_OP_CLEAR,
31 WINED3D_CS_OP_DISPATCH,
32 WINED3D_CS_OP_DRAW,
33 WINED3D_CS_OP_SET_PREDICATION,
34 WINED3D_CS_OP_SET_VIEWPORT,
35 WINED3D_CS_OP_SET_SCISSOR_RECT,
36 WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
37 WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
38 WINED3D_CS_OP_SET_VERTEX_DECLARATION,
39 WINED3D_CS_OP_SET_STREAM_SOURCE,
40 WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ,
41 WINED3D_CS_OP_SET_STREAM_OUTPUT,
42 WINED3D_CS_OP_SET_INDEX_BUFFER,
43 WINED3D_CS_OP_SET_CONSTANT_BUFFER,
44 WINED3D_CS_OP_SET_TEXTURE,
45 WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW,
46 WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW,
47 WINED3D_CS_OP_SET_SAMPLER,
48 WINED3D_CS_OP_SET_SHADER,
49 WINED3D_CS_OP_SET_RASTERIZER_STATE,
50 WINED3D_CS_OP_SET_RENDER_STATE,
51 WINED3D_CS_OP_SET_TEXTURE_STATE,
52 WINED3D_CS_OP_SET_SAMPLER_STATE,
53 WINED3D_CS_OP_SET_TRANSFORM,
54 WINED3D_CS_OP_SET_CLIP_PLANE,
55 WINED3D_CS_OP_SET_COLOR_KEY,
56 WINED3D_CS_OP_SET_MATERIAL,
57 WINED3D_CS_OP_RESET_STATE,
58 WINED3D_CS_OP_DESTROY_OBJECT,
59 WINED3D_CS_OP_QUERY_ISSUE,
60 WINED3D_CS_OP_PRELOAD_RESOURCE,
61 WINED3D_CS_OP_UNLOAD_RESOURCE,
62 WINED3D_CS_OP_MAP,
63 WINED3D_CS_OP_UNMAP,
66 struct wined3d_cs_present
68 enum wined3d_cs_op opcode;
69 HWND dst_window_override;
70 struct wined3d_swapchain *swapchain;
71 RECT src_rect;
72 RECT dst_rect;
73 DWORD flags;
76 struct wined3d_cs_clear
78 enum wined3d_cs_op opcode;
79 DWORD flags;
80 struct wined3d_color color;
81 float depth;
82 DWORD stencil;
83 unsigned int rect_count;
84 RECT rects[1];
87 struct wined3d_cs_dispatch
89 enum wined3d_cs_op opcode;
90 unsigned int group_count_x;
91 unsigned int group_count_y;
92 unsigned int group_count_z;
95 struct wined3d_cs_draw
97 enum wined3d_cs_op opcode;
98 int base_vertex_idx;
99 unsigned int start_idx;
100 unsigned int index_count;
101 unsigned int start_instance;
102 unsigned int instance_count;
103 BOOL indexed;
106 struct wined3d_cs_set_predication
108 enum wined3d_cs_op opcode;
109 struct wined3d_query *predicate;
110 BOOL value;
113 struct wined3d_cs_set_viewport
115 enum wined3d_cs_op opcode;
116 struct wined3d_viewport viewport;
119 struct wined3d_cs_set_scissor_rect
121 enum wined3d_cs_op opcode;
122 RECT rect;
125 struct wined3d_cs_set_rendertarget_view
127 enum wined3d_cs_op opcode;
128 unsigned int view_idx;
129 struct wined3d_rendertarget_view *view;
132 struct wined3d_cs_set_depth_stencil_view
134 enum wined3d_cs_op opcode;
135 struct wined3d_rendertarget_view *view;
138 struct wined3d_cs_set_vertex_declaration
140 enum wined3d_cs_op opcode;
141 struct wined3d_vertex_declaration *declaration;
144 struct wined3d_cs_set_stream_source
146 enum wined3d_cs_op opcode;
147 UINT stream_idx;
148 struct wined3d_buffer *buffer;
149 UINT offset;
150 UINT stride;
153 struct wined3d_cs_set_stream_source_freq
155 enum wined3d_cs_op opcode;
156 UINT stream_idx;
157 UINT frequency;
158 UINT flags;
161 struct wined3d_cs_set_stream_output
163 enum wined3d_cs_op opcode;
164 UINT stream_idx;
165 struct wined3d_buffer *buffer;
166 UINT offset;
169 struct wined3d_cs_set_index_buffer
171 enum wined3d_cs_op opcode;
172 struct wined3d_buffer *buffer;
173 enum wined3d_format_id format_id;
174 unsigned int offset;
177 struct wined3d_cs_set_constant_buffer
179 enum wined3d_cs_op opcode;
180 enum wined3d_shader_type type;
181 UINT cb_idx;
182 struct wined3d_buffer *buffer;
185 struct wined3d_cs_set_texture
187 enum wined3d_cs_op opcode;
188 UINT stage;
189 struct wined3d_texture *texture;
192 struct wined3d_cs_set_color_key
194 enum wined3d_cs_op opcode;
195 struct wined3d_texture *texture;
196 WORD flags;
197 WORD set;
198 struct wined3d_color_key color_key;
201 struct wined3d_cs_set_shader_resource_view
203 enum wined3d_cs_op opcode;
204 enum wined3d_shader_type type;
205 UINT view_idx;
206 struct wined3d_shader_resource_view *view;
209 struct wined3d_cs_set_unordered_access_view
211 enum wined3d_cs_op opcode;
212 enum wined3d_pipeline pipeline;
213 unsigned int view_idx;
214 struct wined3d_unordered_access_view *view;
217 struct wined3d_cs_set_sampler
219 enum wined3d_cs_op opcode;
220 enum wined3d_shader_type type;
221 UINT sampler_idx;
222 struct wined3d_sampler *sampler;
225 struct wined3d_cs_set_shader
227 enum wined3d_cs_op opcode;
228 enum wined3d_shader_type type;
229 struct wined3d_shader *shader;
232 struct wined3d_cs_set_rasterizer_state
234 enum wined3d_cs_op opcode;
235 struct wined3d_rasterizer_state *state;
238 struct wined3d_cs_set_render_state
240 enum wined3d_cs_op opcode;
241 enum wined3d_render_state state;
242 DWORD value;
245 struct wined3d_cs_set_texture_state
247 enum wined3d_cs_op opcode;
248 UINT stage;
249 enum wined3d_texture_stage_state state;
250 DWORD value;
253 struct wined3d_cs_set_sampler_state
255 enum wined3d_cs_op opcode;
256 UINT sampler_idx;
257 enum wined3d_sampler_state state;
258 DWORD value;
261 struct wined3d_cs_set_transform
263 enum wined3d_cs_op opcode;
264 enum wined3d_transform_state state;
265 struct wined3d_matrix matrix;
268 struct wined3d_cs_set_clip_plane
270 enum wined3d_cs_op opcode;
271 UINT plane_idx;
272 struct wined3d_vec4 plane;
275 struct wined3d_cs_set_material
277 enum wined3d_cs_op opcode;
278 struct wined3d_material material;
281 struct wined3d_cs_reset_state
283 enum wined3d_cs_op opcode;
286 struct wined3d_cs_destroy_object
288 enum wined3d_cs_op opcode;
289 void (*callback)(void *object);
290 void *object;
293 struct wined3d_cs_query_issue
295 enum wined3d_cs_op opcode;
296 struct wined3d_query *query;
297 DWORD flags;
300 struct wined3d_cs_preload_resource
302 enum wined3d_cs_op opcode;
303 struct wined3d_resource *resource;
306 struct wined3d_cs_unload_resource
308 enum wined3d_cs_op opcode;
309 struct wined3d_resource *resource;
312 struct wined3d_cs_map
314 enum wined3d_cs_op opcode;
315 struct wined3d_resource *resource;
316 unsigned int sub_resource_idx;
317 struct wined3d_map_desc *map_desc;
318 const struct wined3d_box *box;
319 DWORD flags;
320 HRESULT *hr;
323 struct wined3d_cs_unmap
325 enum wined3d_cs_op opcode;
326 struct wined3d_resource *resource;
327 unsigned int sub_resource_idx;
328 HRESULT *hr;
331 static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
333 const struct wined3d_cs_present *op = data;
334 struct wined3d_swapchain *swapchain;
335 unsigned int i;
337 swapchain = op->swapchain;
338 wined3d_swapchain_set_window(swapchain, op->dst_window_override);
340 swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags);
342 wined3d_resource_release(&swapchain->front_buffer->resource);
343 for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
345 wined3d_resource_release(&swapchain->back_buffers[i]->resource);
349 void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
350 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags)
352 struct wined3d_cs_present *op;
353 unsigned int i;
355 op = cs->ops->require_space(cs, sizeof(*op));
356 op->opcode = WINED3D_CS_OP_PRESENT;
357 op->dst_window_override = dst_window_override;
358 op->swapchain = swapchain;
359 op->src_rect = *src_rect;
360 op->dst_rect = *dst_rect;
361 op->flags = flags;
363 wined3d_resource_acquire(&swapchain->front_buffer->resource);
364 for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
366 wined3d_resource_acquire(&swapchain->back_buffers[i]->resource);
369 cs->ops->submit(cs);
372 static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
374 const struct wined3d_cs_clear *op = data;
375 const struct wined3d_state *state;
376 struct wined3d_device *device;
377 unsigned int i;
378 RECT draw_rect;
380 device = cs->device;
381 state = &device->state;
382 wined3d_get_draw_rect(state, &draw_rect);
383 device_clear_render_targets(device, device->adapter->gl_info.limits.buffers,
384 &device->fb, op->rect_count, op->rects, &draw_rect, op->flags,
385 &op->color, op->depth, op->stencil);
387 if (op->flags & WINED3DCLEAR_TARGET)
389 for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
391 if (state->fb->render_targets[i])
392 wined3d_resource_release(state->fb->render_targets[i]->resource);
395 if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
396 wined3d_resource_release(state->fb->depth_stencil->resource);
399 void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects,
400 DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil)
402 const struct wined3d_state *state = &cs->device->state;
403 struct wined3d_cs_clear *op;
404 unsigned int i;
406 op = cs->ops->require_space(cs, FIELD_OFFSET(struct wined3d_cs_clear, rects[rect_count]));
407 op->opcode = WINED3D_CS_OP_CLEAR;
408 op->flags = flags;
409 op->color = *color;
410 op->depth = depth;
411 op->stencil = stencil;
412 op->rect_count = rect_count;
413 memcpy(op->rects, rects, sizeof(*rects) * rect_count);
415 if (flags & WINED3DCLEAR_TARGET)
417 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
419 if (state->fb->render_targets[i])
420 wined3d_resource_acquire(state->fb->render_targets[i]->resource);
423 if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
424 wined3d_resource_acquire(state->fb->depth_stencil->resource);
426 cs->ops->submit(cs);
429 static void acquire_shader_resources(const struct wined3d_state *state, unsigned int shader_mask)
431 struct wined3d_shader_sampler_map_entry *entry;
432 struct wined3d_shader_resource_view *view;
433 struct wined3d_shader *shader;
434 unsigned int i, j;
436 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
438 if (!(shader_mask & (1u << i)))
439 continue;
441 if (!(shader = state->shader[i]))
442 continue;
444 for (j = 0; j < WINED3D_MAX_CBS; ++j)
446 if (state->cb[i][j])
447 wined3d_resource_acquire(&state->cb[i][j]->resource);
450 for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
452 entry = &shader->reg_maps.sampler_map.entries[j];
454 if (!(view = state->shader_resource_view[i][entry->resource_idx]))
455 continue;
457 wined3d_resource_acquire(view->resource);
462 static void release_shader_resources(const struct wined3d_state *state, unsigned int shader_mask)
464 struct wined3d_shader_sampler_map_entry *entry;
465 struct wined3d_shader_resource_view *view;
466 struct wined3d_shader *shader;
467 unsigned int i, j;
469 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
471 if (!(shader_mask & (1u << i)))
472 continue;
474 if (!(shader = state->shader[i]))
475 continue;
477 for (j = 0; j < WINED3D_MAX_CBS; ++j)
479 if (state->cb[i][j])
480 wined3d_resource_release(&state->cb[i][j]->resource);
483 for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
485 entry = &shader->reg_maps.sampler_map.entries[j];
487 if (!(view = state->shader_resource_view[i][entry->resource_idx]))
488 continue;
490 wined3d_resource_release(view->resource);
495 static void acquire_unordered_access_resources(const struct wined3d_shader *shader,
496 struct wined3d_unordered_access_view * const *views)
498 unsigned int i;
500 if (!shader)
501 return;
503 for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
505 if (!shader->reg_maps.uav_resource_info[i].type)
506 continue;
508 if (!views[i])
509 continue;
511 wined3d_resource_acquire(views[i]->resource);
515 static void release_unordered_access_resources(const struct wined3d_shader *shader,
516 struct wined3d_unordered_access_view * const *views)
518 unsigned int i;
520 if (!shader)
521 return;
523 for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
525 if (!shader->reg_maps.uav_resource_info[i].type)
526 continue;
528 if (!views[i])
529 continue;
531 wined3d_resource_release(views[i]->resource);
535 static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data)
537 struct wined3d_state *state = &cs->device->state;
538 const struct wined3d_cs_dispatch *op = data;
540 dispatch_compute(cs->device, state,
541 op->group_count_x, op->group_count_y, op->group_count_z);
543 release_shader_resources(state, 1u << WINED3D_SHADER_TYPE_COMPUTE);
544 release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_COMPUTE],
545 state->unordered_access_view[WINED3D_PIPELINE_COMPUTE]);
548 void wined3d_cs_emit_dispatch(struct wined3d_cs *cs,
549 unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z)
551 const struct wined3d_state *state = &cs->device->state;
552 struct wined3d_cs_dispatch *op;
554 op = cs->ops->require_space(cs, sizeof(*op));
555 op->opcode = WINED3D_CS_OP_DISPATCH;
556 op->group_count_x = group_count_x;
557 op->group_count_y = group_count_y;
558 op->group_count_z = group_count_z;
560 acquire_shader_resources(state, 1u << WINED3D_SHADER_TYPE_COMPUTE);
561 acquire_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_COMPUTE],
562 state->unordered_access_view[WINED3D_PIPELINE_COMPUTE]);
564 cs->ops->submit(cs);
567 static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
569 struct wined3d_state *state = &cs->device->state;
570 const struct wined3d_cs_draw *op = data;
571 unsigned int i;
573 if (!cs->device->adapter->gl_info.supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]
574 && state->load_base_vertex_index != op->base_vertex_idx)
576 state->load_base_vertex_index = op->base_vertex_idx;
577 device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
580 draw_primitive(cs->device, state, op->base_vertex_idx, op->start_idx,
581 op->index_count, op->start_instance, op->instance_count, op->indexed);
583 if (op->indexed)
584 wined3d_resource_release(&state->index_buffer->resource);
585 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
587 if (state->streams[i].buffer)
588 wined3d_resource_release(&state->streams[i].buffer->resource);
590 for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
592 if (state->textures[i])
593 wined3d_resource_release(&state->textures[i]->resource);
595 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
597 if (state->fb->render_targets[i])
598 wined3d_resource_release(state->fb->render_targets[i]->resource);
600 if (state->fb->depth_stencil)
601 wined3d_resource_release(state->fb->depth_stencil->resource);
602 release_shader_resources(state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE));
603 release_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_PIXEL],
604 state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]);
607 void wined3d_cs_emit_draw(struct wined3d_cs *cs, int base_vertex_idx, unsigned int start_idx,
608 unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed)
610 const struct wined3d_state *state = &cs->device->state;
611 struct wined3d_cs_draw *op;
612 unsigned int i;
614 op = cs->ops->require_space(cs, sizeof(*op));
615 op->opcode = WINED3D_CS_OP_DRAW;
616 op->base_vertex_idx = base_vertex_idx;
617 op->start_idx = start_idx;
618 op->index_count = index_count;
619 op->start_instance = start_instance;
620 op->instance_count = instance_count;
621 op->indexed = indexed;
623 if (indexed)
624 wined3d_resource_acquire(&state->index_buffer->resource);
625 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
627 if (state->streams[i].buffer)
628 wined3d_resource_acquire(&state->streams[i].buffer->resource);
630 for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
632 if (state->textures[i])
633 wined3d_resource_acquire(&state->textures[i]->resource);
635 for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
637 if (state->fb->render_targets[i])
638 wined3d_resource_acquire(state->fb->render_targets[i]->resource);
640 if (state->fb->depth_stencil)
641 wined3d_resource_acquire(state->fb->depth_stencil->resource);
642 acquire_shader_resources(state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE));
643 acquire_unordered_access_resources(state->shader[WINED3D_SHADER_TYPE_PIXEL],
644 state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]);
646 cs->ops->submit(cs);
649 static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data)
651 const struct wined3d_cs_set_predication *op = data;
653 cs->state.predicate = op->predicate;
654 cs->state.predicate_value = op->value;
657 void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value)
659 struct wined3d_cs_set_predication *op;
661 op = cs->ops->require_space(cs, sizeof(*op));
662 op->opcode = WINED3D_CS_OP_SET_PREDICATION;
663 op->predicate = predicate;
664 op->value = value;
666 cs->ops->submit(cs);
669 static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data)
671 const struct wined3d_cs_set_viewport *op = data;
673 cs->state.viewport = op->viewport;
674 device_invalidate_state(cs->device, STATE_VIEWPORT);
677 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport)
679 struct wined3d_cs_set_viewport *op;
681 op = cs->ops->require_space(cs, sizeof(*op));
682 op->opcode = WINED3D_CS_OP_SET_VIEWPORT;
683 op->viewport = *viewport;
685 cs->ops->submit(cs);
688 static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data)
690 const struct wined3d_cs_set_scissor_rect *op = data;
692 cs->state.scissor_rect = op->rect;
693 device_invalidate_state(cs->device, STATE_SCISSORRECT);
696 void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
698 struct wined3d_cs_set_scissor_rect *op;
700 op = cs->ops->require_space(cs, sizeof(*op));
701 op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT;
702 op->rect = *rect;
704 cs->ops->submit(cs);
707 static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
709 const struct wined3d_cs_set_rendertarget_view *op = data;
711 cs->state.fb->render_targets[op->view_idx] = op->view;
712 device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
715 void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
716 struct wined3d_rendertarget_view *view)
718 struct wined3d_cs_set_rendertarget_view *op;
720 op = cs->ops->require_space(cs, sizeof(*op));
721 op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
722 op->view_idx = view_idx;
723 op->view = view;
725 cs->ops->submit(cs);
728 static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data)
730 const struct wined3d_cs_set_depth_stencil_view *op = data;
731 struct wined3d_device *device = cs->device;
732 struct wined3d_rendertarget_view *prev;
734 if ((prev = cs->state.fb->depth_stencil))
736 struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev);
738 if (prev_surface && (device->swapchains[0]->desc.flags & WINED3D_SWAPCHAIN_DISCARD_DEPTHSTENCIL
739 || prev_surface->container->flags & WINED3D_TEXTURE_DISCARD))
741 wined3d_texture_validate_location(prev_surface->container,
742 prev->sub_resource_idx, WINED3D_LOCATION_DISCARDED);
746 cs->fb.depth_stencil = op->view;
748 if (!prev != !op->view)
750 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
751 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE));
752 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE));
753 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
754 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
756 else if (prev && (prev->format_flags & WINED3DFMT_FLAG_FLOAT)
757 != (op->view->format_flags & WINED3DFMT_FLAG_FLOAT))
759 device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
762 device_invalidate_state(device, STATE_FRAMEBUFFER);
765 void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view)
767 struct wined3d_cs_set_depth_stencil_view *op;
769 op = cs->ops->require_space(cs, sizeof(*op));
770 op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW;
771 op->view = view;
773 cs->ops->submit(cs);
776 static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data)
778 const struct wined3d_cs_set_vertex_declaration *op = data;
780 cs->state.vertex_declaration = op->declaration;
781 device_invalidate_state(cs->device, STATE_VDECL);
784 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration)
786 struct wined3d_cs_set_vertex_declaration *op;
788 op = cs->ops->require_space(cs, sizeof(*op));
789 op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION;
790 op->declaration = declaration;
792 cs->ops->submit(cs);
795 static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data)
797 const struct wined3d_cs_set_stream_source *op = data;
798 struct wined3d_stream_state *stream;
799 struct wined3d_buffer *prev;
801 stream = &cs->state.streams[op->stream_idx];
802 prev = stream->buffer;
803 stream->buffer = op->buffer;
804 stream->offset = op->offset;
805 stream->stride = op->stride;
807 if (op->buffer)
808 InterlockedIncrement(&op->buffer->resource.bind_count);
809 if (prev)
810 InterlockedDecrement(&prev->resource.bind_count);
812 device_invalidate_state(cs->device, STATE_STREAMSRC);
815 void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
816 struct wined3d_buffer *buffer, UINT offset, UINT stride)
818 struct wined3d_cs_set_stream_source *op;
820 op = cs->ops->require_space(cs, sizeof(*op));
821 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE;
822 op->stream_idx = stream_idx;
823 op->buffer = buffer;
824 op->offset = offset;
825 op->stride = stride;
827 cs->ops->submit(cs);
830 static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data)
832 const struct wined3d_cs_set_stream_source_freq *op = data;
833 struct wined3d_stream_state *stream;
835 stream = &cs->state.streams[op->stream_idx];
836 stream->frequency = op->frequency;
837 stream->flags = op->flags;
839 device_invalidate_state(cs->device, STATE_STREAMSRC);
842 void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags)
844 struct wined3d_cs_set_stream_source_freq *op;
846 op = cs->ops->require_space(cs, sizeof(*op));
847 op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ;
848 op->stream_idx = stream_idx;
849 op->frequency = frequency;
850 op->flags = flags;
852 cs->ops->submit(cs);
855 static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data)
857 const struct wined3d_cs_set_stream_output *op = data;
858 struct wined3d_stream_output *stream;
859 struct wined3d_buffer *prev;
861 stream = &cs->state.stream_output[op->stream_idx];
862 prev = stream->buffer;
863 stream->buffer = op->buffer;
864 stream->offset = op->offset;
866 if (op->buffer)
867 InterlockedIncrement(&op->buffer->resource.bind_count);
868 if (prev)
869 InterlockedDecrement(&prev->resource.bind_count);
872 void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx,
873 struct wined3d_buffer *buffer, UINT offset)
875 struct wined3d_cs_set_stream_output *op;
877 op = cs->ops->require_space(cs, sizeof(*op));
878 op->opcode = WINED3D_CS_OP_SET_STREAM_OUTPUT;
879 op->stream_idx = stream_idx;
880 op->buffer = buffer;
881 op->offset = offset;
883 cs->ops->submit(cs);
886 static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data)
888 const struct wined3d_cs_set_index_buffer *op = data;
889 struct wined3d_buffer *prev;
891 prev = cs->state.index_buffer;
892 cs->state.index_buffer = op->buffer;
893 cs->state.index_format = op->format_id;
894 cs->state.index_offset = op->offset;
896 if (op->buffer)
897 InterlockedIncrement(&op->buffer->resource.bind_count);
898 if (prev)
899 InterlockedDecrement(&prev->resource.bind_count);
901 device_invalidate_state(cs->device, STATE_INDEXBUFFER);
904 void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
905 enum wined3d_format_id format_id, unsigned int offset)
907 struct wined3d_cs_set_index_buffer *op;
909 op = cs->ops->require_space(cs, sizeof(*op));
910 op->opcode = WINED3D_CS_OP_SET_INDEX_BUFFER;
911 op->buffer = buffer;
912 op->format_id = format_id;
913 op->offset = offset;
915 cs->ops->submit(cs);
918 static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data)
920 const struct wined3d_cs_set_constant_buffer *op = data;
921 struct wined3d_buffer *prev;
923 prev = cs->state.cb[op->type][op->cb_idx];
924 cs->state.cb[op->type][op->cb_idx] = op->buffer;
926 if (op->buffer)
927 InterlockedIncrement(&op->buffer->resource.bind_count);
928 if (prev)
929 InterlockedDecrement(&prev->resource.bind_count);
931 device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
934 void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
935 UINT cb_idx, struct wined3d_buffer *buffer)
937 struct wined3d_cs_set_constant_buffer *op;
939 op = cs->ops->require_space(cs, sizeof(*op));
940 op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER;
941 op->type = type;
942 op->cb_idx = cb_idx;
943 op->buffer = buffer;
945 cs->ops->submit(cs);
948 static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
950 const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
951 const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
952 const struct wined3d_cs_set_texture *op = data;
953 struct wined3d_texture *prev;
954 BOOL old_use_color_key = FALSE, new_use_color_key = FALSE;
956 prev = cs->state.textures[op->stage];
957 cs->state.textures[op->stage] = op->texture;
959 if (op->texture)
961 const struct wined3d_format *new_format = op->texture->resource.format;
962 const struct wined3d_format *old_format = prev ? prev->resource.format : NULL;
963 unsigned int old_fmt_flags = prev ? prev->resource.format_flags : 0;
964 unsigned int new_fmt_flags = op->texture->resource.format_flags;
966 if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
967 op->texture->sampler = op->stage;
969 if (!prev || op->texture->target != prev->target
970 || (!is_same_fixup(new_format->color_fixup, old_format->color_fixup)
971 && !(can_use_texture_swizzle(gl_info, new_format) && can_use_texture_swizzle(gl_info, old_format)))
972 || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW))
973 device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
975 if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
977 /* The source arguments for color and alpha ops have different
978 * meanings when a NULL texture is bound, so the COLOR_OP and
979 * ALPHA_OP have to be dirtified. */
980 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
981 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
984 if (!op->stage && op->texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
985 new_use_color_key = TRUE;
988 if (prev)
990 if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
992 unsigned int i;
994 /* Search for other stages the texture is bound to. Shouldn't
995 * happen if applications bind textures to a single stage only. */
996 TRACE("Searching for other stages the texture is bound to.\n");
997 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
999 if (cs->state.textures[i] == prev)
1001 TRACE("Texture is also bound to stage %u.\n", i);
1002 prev->sampler = i;
1003 break;
1008 if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
1010 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
1011 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
1014 if (!op->stage && prev->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
1015 old_use_color_key = TRUE;
1018 device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
1020 if (new_use_color_key != old_use_color_key)
1021 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
1023 if (new_use_color_key)
1024 device_invalidate_state(cs->device, STATE_COLOR_KEY);
1027 void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
1029 struct wined3d_cs_set_texture *op;
1031 op = cs->ops->require_space(cs, sizeof(*op));
1032 op->opcode = WINED3D_CS_OP_SET_TEXTURE;
1033 op->stage = stage;
1034 op->texture = texture;
1036 cs->ops->submit(cs);
1039 static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data)
1041 const struct wined3d_cs_set_shader_resource_view *op = data;
1042 struct wined3d_shader_resource_view *prev;
1044 prev = cs->state.shader_resource_view[op->type][op->view_idx];
1045 cs->state.shader_resource_view[op->type][op->view_idx] = op->view;
1047 if (op->view)
1048 InterlockedIncrement(&op->view->resource->bind_count);
1049 if (prev)
1050 InterlockedDecrement(&prev->resource->bind_count);
1052 if (op->type != WINED3D_SHADER_TYPE_COMPUTE)
1053 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
1056 void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type,
1057 UINT view_idx, struct wined3d_shader_resource_view *view)
1059 struct wined3d_cs_set_shader_resource_view *op;
1061 op = cs->ops->require_space(cs, sizeof(*op));
1062 op->opcode = WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW;
1063 op->type = type;
1064 op->view_idx = view_idx;
1065 op->view = view;
1067 cs->ops->submit(cs);
1070 static void wined3d_cs_exec_set_unordered_access_view(struct wined3d_cs *cs, const void *data)
1072 const struct wined3d_cs_set_unordered_access_view *op = data;
1073 struct wined3d_unordered_access_view *prev;
1075 prev = cs->state.unordered_access_view[op->pipeline][op->view_idx];
1076 cs->state.unordered_access_view[op->pipeline][op->view_idx] = op->view;
1078 if (op->view)
1079 InterlockedIncrement(&op->view->resource->bind_count);
1080 if (prev)
1081 InterlockedDecrement(&prev->resource->bind_count);
1083 device_invalidate_state(cs->device, STATE_UNORDERED_ACCESS_VIEW_BINDING(op->pipeline));
1086 void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, enum wined3d_pipeline pipeline,
1087 unsigned int view_idx, struct wined3d_unordered_access_view *view)
1089 struct wined3d_cs_set_unordered_access_view *op;
1091 op = cs->ops->require_space(cs, sizeof(*op));
1092 op->opcode = WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW;
1093 op->pipeline = pipeline;
1094 op->view_idx = view_idx;
1095 op->view = view;
1097 cs->ops->submit(cs);
1100 static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data)
1102 const struct wined3d_cs_set_sampler *op = data;
1104 cs->state.sampler[op->type][op->sampler_idx] = op->sampler;
1105 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
1108 void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
1109 UINT sampler_idx, struct wined3d_sampler *sampler)
1111 struct wined3d_cs_set_sampler *op;
1113 op = cs->ops->require_space(cs, sizeof(*op));
1114 op->opcode = WINED3D_CS_OP_SET_SAMPLER;
1115 op->type = type;
1116 op->sampler_idx = sampler_idx;
1117 op->sampler = sampler;
1119 cs->ops->submit(cs);
1122 static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data)
1124 const struct wined3d_cs_set_shader *op = data;
1126 cs->state.shader[op->type] = op->shader;
1127 device_invalidate_state(cs->device, STATE_SHADER(op->type));
1128 if (op->type != WINED3D_SHADER_TYPE_COMPUTE)
1129 device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING);
1132 void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader)
1134 struct wined3d_cs_set_shader *op;
1136 op = cs->ops->require_space(cs, sizeof(*op));
1137 op->opcode = WINED3D_CS_OP_SET_SHADER;
1138 op->type = type;
1139 op->shader = shader;
1141 cs->ops->submit(cs);
1144 static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs *cs, const void *data)
1146 const struct wined3d_cs_set_rasterizer_state *op = data;
1148 cs->state.rasterizer_state = op->state;
1149 device_invalidate_state(cs->device, STATE_FRONTFACE);
1152 void wined3d_cs_emit_set_rasterizer_state(struct wined3d_cs *cs,
1153 struct wined3d_rasterizer_state *rasterizer_state)
1155 struct wined3d_cs_set_rasterizer_state *op;
1157 op = cs->ops->require_space(cs, sizeof(*op));
1158 op->opcode = WINED3D_CS_OP_SET_RASTERIZER_STATE;
1159 op->state = rasterizer_state;
1161 cs->ops->submit(cs);
1164 static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data)
1166 const struct wined3d_cs_set_render_state *op = data;
1168 cs->state.render_states[op->state] = op->value;
1169 device_invalidate_state(cs->device, STATE_RENDER(op->state));
1172 void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value)
1174 struct wined3d_cs_set_render_state *op;
1176 op = cs->ops->require_space(cs, sizeof(*op));
1177 op->opcode = WINED3D_CS_OP_SET_RENDER_STATE;
1178 op->state = state;
1179 op->value = value;
1181 cs->ops->submit(cs);
1184 static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
1186 const struct wined3d_cs_set_texture_state *op = data;
1188 cs->state.texture_states[op->stage][op->state] = op->value;
1189 device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, op->state));
1192 void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage,
1193 enum wined3d_texture_stage_state state, DWORD value)
1195 struct wined3d_cs_set_texture_state *op;
1197 op = cs->ops->require_space(cs, sizeof(*op));
1198 op->opcode = WINED3D_CS_OP_SET_TEXTURE_STATE;
1199 op->stage = stage;
1200 op->state = state;
1201 op->value = value;
1203 cs->ops->submit(cs);
1206 static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data)
1208 const struct wined3d_cs_set_sampler_state *op = data;
1210 cs->state.sampler_states[op->sampler_idx][op->state] = op->value;
1211 device_invalidate_state(cs->device, STATE_SAMPLER(op->sampler_idx));
1214 void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
1215 enum wined3d_sampler_state state, DWORD value)
1217 struct wined3d_cs_set_sampler_state *op;
1219 op = cs->ops->require_space(cs, sizeof(*op));
1220 op->opcode = WINED3D_CS_OP_SET_SAMPLER_STATE;
1221 op->sampler_idx = sampler_idx;
1222 op->state = state;
1223 op->value = value;
1225 cs->ops->submit(cs);
1228 static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data)
1230 const struct wined3d_cs_set_transform *op = data;
1232 cs->state.transforms[op->state] = op->matrix;
1233 if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->d3d_info.limits.ffp_vertex_blend_matrices))
1234 device_invalidate_state(cs->device, STATE_TRANSFORM(op->state));
1237 void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state,
1238 const struct wined3d_matrix *matrix)
1240 struct wined3d_cs_set_transform *op;
1242 op = cs->ops->require_space(cs, sizeof(*op));
1243 op->opcode = WINED3D_CS_OP_SET_TRANSFORM;
1244 op->state = state;
1245 op->matrix = *matrix;
1247 cs->ops->submit(cs);
1250 static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data)
1252 const struct wined3d_cs_set_clip_plane *op = data;
1254 cs->state.clip_planes[op->plane_idx] = op->plane;
1255 device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx));
1258 void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane)
1260 struct wined3d_cs_set_clip_plane *op;
1262 op = cs->ops->require_space(cs, sizeof(*op));
1263 op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE;
1264 op->plane_idx = plane_idx;
1265 op->plane = *plane;
1267 cs->ops->submit(cs);
1270 static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *data)
1272 const struct wined3d_cs_set_color_key *op = data;
1273 struct wined3d_texture *texture = op->texture;
1275 if (op->set)
1277 switch (op->flags)
1279 case WINED3D_CKEY_DST_BLT:
1280 texture->async.dst_blt_color_key = op->color_key;
1281 texture->async.color_key_flags |= WINED3D_CKEY_DST_BLT;
1282 break;
1284 case WINED3D_CKEY_DST_OVERLAY:
1285 texture->async.dst_overlay_color_key = op->color_key;
1286 texture->async.color_key_flags |= WINED3D_CKEY_DST_OVERLAY;
1287 break;
1289 case WINED3D_CKEY_SRC_BLT:
1290 if (texture == cs->state.textures[0])
1292 device_invalidate_state(cs->device, STATE_COLOR_KEY);
1293 if (!(texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
1294 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
1297 texture->async.src_blt_color_key = op->color_key;
1298 texture->async.color_key_flags |= WINED3D_CKEY_SRC_BLT;
1299 break;
1301 case WINED3D_CKEY_SRC_OVERLAY:
1302 texture->async.src_overlay_color_key = op->color_key;
1303 texture->async.color_key_flags |= WINED3D_CKEY_SRC_OVERLAY;
1304 break;
1307 else
1309 switch (op->flags)
1311 case WINED3D_CKEY_DST_BLT:
1312 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
1313 break;
1315 case WINED3D_CKEY_DST_OVERLAY:
1316 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_OVERLAY;
1317 break;
1319 case WINED3D_CKEY_SRC_BLT:
1320 if (texture == cs->state.textures[0] && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT)
1321 device_invalidate_state(cs->device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE));
1323 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_BLT;
1324 break;
1326 case WINED3D_CKEY_SRC_OVERLAY:
1327 texture->async.color_key_flags &= ~WINED3D_CKEY_SRC_OVERLAY;
1328 break;
1333 void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture,
1334 WORD flags, const struct wined3d_color_key *color_key)
1336 struct wined3d_cs_set_color_key *op;
1338 op = cs->ops->require_space(cs, sizeof(*op));
1339 op->opcode = WINED3D_CS_OP_SET_COLOR_KEY;
1340 op->texture = texture;
1341 op->flags = flags;
1342 if (color_key)
1344 op->color_key = *color_key;
1345 op->set = 1;
1347 else
1348 op->set = 0;
1350 cs->ops->submit(cs);
1353 static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data)
1355 const struct wined3d_cs_set_material *op = data;
1357 cs->state.material = op->material;
1358 device_invalidate_state(cs->device, STATE_MATERIAL);
1361 void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material)
1363 struct wined3d_cs_set_material *op;
1365 op = cs->ops->require_space(cs, sizeof(*op));
1366 op->opcode = WINED3D_CS_OP_SET_MATERIAL;
1367 op->material = *material;
1369 cs->ops->submit(cs);
1372 static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data)
1374 struct wined3d_adapter *adapter = cs->device->adapter;
1376 state_cleanup(&cs->state);
1377 memset(&cs->state, 0, sizeof(cs->state));
1378 state_init(&cs->state, &cs->fb, &adapter->gl_info, &adapter->d3d_info,
1379 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT);
1382 void wined3d_cs_emit_reset_state(struct wined3d_cs *cs)
1384 struct wined3d_cs_reset_state *op;
1386 op = cs->ops->require_space(cs, sizeof(*op));
1387 op->opcode = WINED3D_CS_OP_RESET_STATE;
1389 cs->ops->submit(cs);
1392 static void wined3d_cs_exec_destroy_object(struct wined3d_cs *cs, const void *data)
1394 const struct wined3d_cs_destroy_object *op = data;
1396 op->callback(op->object);
1399 void wined3d_cs_emit_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object)
1401 struct wined3d_cs_destroy_object *op;
1403 op = cs->ops->require_space(cs, sizeof(*op));
1404 op->opcode = WINED3D_CS_OP_DESTROY_OBJECT;
1405 op->callback = callback;
1406 op->object = object;
1408 cs->ops->submit(cs);
1411 static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data)
1413 const struct wined3d_cs_query_issue *op = data;
1414 struct wined3d_query *query = op->query;
1416 query->query_ops->query_issue(query, op->flags);
1419 void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags)
1421 struct wined3d_cs_query_issue *op;
1423 op = cs->ops->require_space(cs, sizeof(*op));
1424 op->opcode = WINED3D_CS_OP_QUERY_ISSUE;
1425 op->query = query;
1426 op->flags = flags;
1428 cs->ops->submit(cs);
1431 static void wined3d_cs_exec_preload_resource(struct wined3d_cs *cs, const void *data)
1433 const struct wined3d_cs_preload_resource *op = data;
1434 struct wined3d_resource *resource = op->resource;
1436 resource->resource_ops->resource_preload(resource);
1437 wined3d_resource_release(resource);
1440 void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource)
1442 struct wined3d_cs_preload_resource *op;
1444 op = cs->ops->require_space(cs, sizeof(*op));
1445 op->opcode = WINED3D_CS_OP_PRELOAD_RESOURCE;
1446 op->resource = resource;
1448 wined3d_resource_acquire(resource);
1450 cs->ops->submit(cs);
1453 static void wined3d_cs_exec_unload_resource(struct wined3d_cs *cs, const void *data)
1455 const struct wined3d_cs_unload_resource *op = data;
1456 struct wined3d_resource *resource = op->resource;
1458 resource->resource_ops->resource_unload(resource);
1459 wined3d_resource_release(resource);
1462 void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource)
1464 struct wined3d_cs_unload_resource *op;
1466 op = cs->ops->require_space(cs, sizeof(*op));
1467 op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE;
1468 op->resource = resource;
1470 wined3d_resource_acquire(resource);
1472 cs->ops->submit(cs);
1475 static void wined3d_cs_exec_map(struct wined3d_cs *cs, const void *data)
1477 const struct wined3d_cs_map *op = data;
1478 struct wined3d_resource *resource = op->resource;
1480 *op->hr = resource->resource_ops->resource_sub_resource_map(resource,
1481 op->sub_resource_idx, op->map_desc, op->box, op->flags);
1484 HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx,
1485 struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags)
1487 struct wined3d_cs_map *op;
1488 HRESULT hr;
1490 op = cs->ops->require_space(cs, sizeof(*op));
1491 op->opcode = WINED3D_CS_OP_MAP;
1492 op->resource = resource;
1493 op->sub_resource_idx = sub_resource_idx;
1494 op->map_desc = map_desc;
1495 op->box = box;
1496 op->flags = flags;
1497 op->hr = &hr;
1499 cs->ops->submit(cs);
1501 return hr;
1504 static void wined3d_cs_exec_unmap(struct wined3d_cs *cs, const void *data)
1506 const struct wined3d_cs_unmap *op = data;
1507 struct wined3d_resource *resource = op->resource;
1509 *op->hr = resource->resource_ops->resource_sub_resource_unmap(resource, op->sub_resource_idx);
1512 HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx)
1514 struct wined3d_cs_unmap *op;
1515 HRESULT hr;
1517 op = cs->ops->require_space(cs, sizeof(*op));
1518 op->opcode = WINED3D_CS_OP_UNMAP;
1519 op->resource = resource;
1520 op->sub_resource_idx = sub_resource_idx;
1521 op->hr = &hr;
1523 cs->ops->submit(cs);
1525 return hr;
1528 static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
1530 /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
1531 /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear,
1532 /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch,
1533 /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
1534 /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication,
1535 /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
1536 /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
1537 /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
1538 /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view,
1539 /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
1540 /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
1541 /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
1542 /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output,
1543 /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
1544 /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer,
1545 /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
1546 /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view,
1547 /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view,
1548 /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler,
1549 /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader,
1550 /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state,
1551 /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state,
1552 /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state,
1553 /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state,
1554 /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform,
1555 /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane,
1556 /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key,
1557 /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material,
1558 /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state,
1559 /* WINED3D_CS_OP_DESTROY_OBJECT */ wined3d_cs_exec_destroy_object,
1560 /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue,
1561 /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource,
1562 /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource,
1563 /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map,
1564 /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap,
1567 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
1569 if (size > cs->data_size)
1571 void *new_data;
1573 size = max( size, cs->data_size * 2 );
1574 if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size)))
1575 return NULL;
1577 cs->data_size = size;
1578 cs->data = new_data;
1581 return cs->data;
1584 static void wined3d_cs_st_submit(struct wined3d_cs *cs)
1586 enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data;
1588 wined3d_cs_op_handlers[opcode](cs, cs->data);
1591 static void wined3d_cs_st_push_constants(struct wined3d_cs *cs, enum wined3d_push_constants p,
1592 unsigned int start_idx, unsigned int count, const void *constants)
1594 struct wined3d_device *device = cs->device;
1595 unsigned int context_count;
1596 unsigned int i;
1597 size_t offset;
1599 static const struct
1601 size_t offset;
1602 size_t size;
1603 DWORD mask;
1605 push_constant_info[] =
1607 /* WINED3D_PUSH_CONSTANTS_VS_F */
1608 {FIELD_OFFSET(struct wined3d_state, vs_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_VS_F},
1609 /* WINED3D_PUSH_CONSTANTS_PS_F */
1610 {FIELD_OFFSET(struct wined3d_state, ps_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_PS_F},
1611 /* WINED3D_PUSH_CONSTANTS_VS_I */
1612 {FIELD_OFFSET(struct wined3d_state, vs_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_VS_I},
1613 /* WINED3D_PUSH_CONSTANTS_PS_I */
1614 {FIELD_OFFSET(struct wined3d_state, ps_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_PS_I},
1615 /* WINED3D_PUSH_CONSTANTS_VS_B */
1616 {FIELD_OFFSET(struct wined3d_state, vs_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_VS_B},
1617 /* WINED3D_PUSH_CONSTANTS_PS_B */
1618 {FIELD_OFFSET(struct wined3d_state, ps_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_PS_B},
1621 if (p == WINED3D_PUSH_CONSTANTS_VS_F)
1622 device->shader_backend->shader_update_float_vertex_constants(device, start_idx, count);
1623 else if (p == WINED3D_PUSH_CONSTANTS_PS_F)
1624 device->shader_backend->shader_update_float_pixel_constants(device, start_idx, count);
1626 offset = push_constant_info[p].offset + start_idx * push_constant_info[p].size;
1627 memcpy((BYTE *)&cs->state + offset, constants, count * push_constant_info[p].size);
1628 for (i = 0, context_count = device->context_count; i < context_count; ++i)
1630 device->contexts[i]->constant_update_mask |= push_constant_info[p].mask;
1634 static const struct wined3d_cs_ops wined3d_cs_st_ops =
1636 wined3d_cs_st_require_space,
1637 wined3d_cs_st_submit,
1638 wined3d_cs_st_push_constants,
1641 struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device)
1643 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1644 struct wined3d_cs *cs;
1646 if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs))))
1647 return NULL;
1649 if (!(cs->fb.render_targets = wined3d_calloc(gl_info->limits.buffers, sizeof(*cs->fb.render_targets))))
1651 HeapFree(GetProcessHeap(), 0, cs);
1652 return NULL;
1655 state_init(&cs->state, &cs->fb, gl_info, &device->adapter->d3d_info,
1656 WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT);
1658 cs->ops = &wined3d_cs_st_ops;
1659 cs->device = device;
1661 cs->data_size = WINED3D_INITIAL_CS_SIZE;
1662 if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size)))
1664 state_cleanup(&cs->state);
1665 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1666 HeapFree(GetProcessHeap(), 0, cs);
1667 return NULL;
1670 return cs;
1673 void wined3d_cs_destroy(struct wined3d_cs *cs)
1675 state_cleanup(&cs->state);
1676 HeapFree(GetProcessHeap(), 0, cs->fb.render_targets);
1677 HeapFree(GetProcessHeap(), 0, cs->data);
1678 HeapFree(GetProcessHeap(), 0, cs);