wined3d: Implement indirect draws.
Signed-off-by: Józef Kucia <jkucia@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c736181da4
commit
f4aa2911a6
|
@ -120,12 +120,7 @@ struct wined3d_cs_draw
|
|||
enum wined3d_cs_op opcode;
|
||||
GLenum primitive_type;
|
||||
GLint patch_vertex_count;
|
||||
int base_vertex_idx;
|
||||
unsigned int start_idx;
|
||||
unsigned int index_count;
|
||||
unsigned int start_instance;
|
||||
unsigned int instance_count;
|
||||
BOOL indexed;
|
||||
struct wined3d_draw_parameters parameters;
|
||||
};
|
||||
|
||||
struct wined3d_cs_flush
|
||||
|
@ -758,14 +753,21 @@ void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs *cs,
|
|||
|
||||
static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
|
||||
struct wined3d_state *state = &cs->state;
|
||||
const struct wined3d_cs_draw *op = data;
|
||||
int load_base_vertex_idx;
|
||||
unsigned int i;
|
||||
|
||||
if (!cs->device->adapter->gl_info.supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]
|
||||
&& state->load_base_vertex_index != op->base_vertex_idx)
|
||||
/* ARB_draw_indirect always supports a base vertex offset. */
|
||||
if (!op->parameters.indirect && !gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
|
||||
load_base_vertex_idx = op->parameters.u.direct.base_vertex_idx;
|
||||
else
|
||||
load_base_vertex_idx = 0;
|
||||
|
||||
if (state->load_base_vertex_index != load_base_vertex_idx)
|
||||
{
|
||||
state->load_base_vertex_index = op->base_vertex_idx;
|
||||
state->load_base_vertex_index = load_base_vertex_idx;
|
||||
device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX);
|
||||
}
|
||||
|
||||
|
@ -777,10 +779,15 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
|
|||
}
|
||||
state->gl_patch_vertices = op->patch_vertex_count;
|
||||
|
||||
draw_primitive(cs->device, state, op->base_vertex_idx, op->start_idx,
|
||||
op->index_count, op->start_instance, op->instance_count, op->indexed);
|
||||
draw_primitive(cs->device, state, &op->parameters);
|
||||
|
||||
if (op->indexed)
|
||||
if (op->parameters.indirect)
|
||||
{
|
||||
struct wined3d_buffer *buffer = op->parameters.u.indirect.buffer;
|
||||
wined3d_resource_release(&buffer->resource);
|
||||
}
|
||||
|
||||
if (op->parameters.indexed)
|
||||
wined3d_resource_release(&state->index_buffer->resource);
|
||||
for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
|
||||
{
|
||||
|
@ -797,7 +804,7 @@ static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
|
|||
if (state->textures[i])
|
||||
wined3d_resource_release(&state->textures[i]->resource);
|
||||
}
|
||||
for (i = 0; i < cs->device->adapter->gl_info.limits.buffers; ++i)
|
||||
for (i = 0; i < gl_info->limits.buffers; ++i)
|
||||
{
|
||||
if (state->fb->render_targets[i])
|
||||
wined3d_resource_release(state->fb->render_targets[i]->resource);
|
||||
|
@ -855,18 +862,41 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, unsigned
|
|||
op->opcode = WINED3D_CS_OP_DRAW;
|
||||
op->primitive_type = primitive_type;
|
||||
op->patch_vertex_count = patch_vertex_count;
|
||||
op->base_vertex_idx = base_vertex_idx;
|
||||
op->start_idx = start_idx;
|
||||
op->index_count = index_count;
|
||||
op->start_instance = start_instance;
|
||||
op->instance_count = instance_count;
|
||||
op->indexed = indexed;
|
||||
op->parameters.indirect = FALSE;
|
||||
op->parameters.u.direct.base_vertex_idx = base_vertex_idx;
|
||||
op->parameters.u.direct.start_idx = start_idx;
|
||||
op->parameters.u.direct.index_count = index_count;
|
||||
op->parameters.u.direct.start_instance = start_instance;
|
||||
op->parameters.u.direct.instance_count = instance_count;
|
||||
op->parameters.indexed = indexed;
|
||||
|
||||
acquire_graphics_pipeline_resources(state, indexed, gl_info);
|
||||
|
||||
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
|
||||
}
|
||||
|
||||
void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count,
|
||||
struct wined3d_buffer *buffer, unsigned int offset, BOOL indexed)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
|
||||
const struct wined3d_state *state = &cs->device->state;
|
||||
struct wined3d_cs_draw *op;
|
||||
|
||||
op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
|
||||
op->opcode = WINED3D_CS_OP_DRAW;
|
||||
op->primitive_type = primitive_type;
|
||||
op->patch_vertex_count = patch_vertex_count;
|
||||
op->parameters.indirect = TRUE;
|
||||
op->parameters.u.indirect.buffer = buffer;
|
||||
op->parameters.u.indirect.offset = offset;
|
||||
op->parameters.indexed = indexed;
|
||||
|
||||
acquire_graphics_pipeline_resources(state, indexed, gl_info);
|
||||
wined3d_resource_acquire(&buffer->resource);
|
||||
|
||||
cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT);
|
||||
}
|
||||
|
||||
static void wined3d_cs_exec_flush(struct wined3d_cs *cs, const void *data)
|
||||
{
|
||||
struct wined3d_context *context;
|
||||
|
|
|
@ -3703,6 +3703,15 @@ void CDECL wined3d_device_draw_primitive_instanced(struct wined3d_device *device
|
|||
0, start_vertex, vertex_count, start_instance, instance_count, FALSE);
|
||||
}
|
||||
|
||||
void CDECL wined3d_device_draw_primitive_instanced_indirect(struct wined3d_device *device,
|
||||
struct wined3d_buffer *buffer, unsigned int offset)
|
||||
{
|
||||
TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
|
||||
|
||||
wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
|
||||
buffer, offset, FALSE);
|
||||
}
|
||||
|
||||
HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count)
|
||||
{
|
||||
TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
|
||||
|
@ -3733,6 +3742,15 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device
|
|||
device->state.base_vertex_index, start_idx, index_count, start_instance, instance_count, TRUE);
|
||||
}
|
||||
|
||||
void CDECL wined3d_device_draw_indexed_primitive_instanced_indirect(struct wined3d_device *device,
|
||||
struct wined3d_buffer *buffer, unsigned int offset)
|
||||
{
|
||||
TRACE("device %p, buffer %p, offset %u.\n", device, buffer, offset);
|
||||
|
||||
wined3d_cs_emit_draw_indirect(device->cs, device->state.gl_primitive_type, device->state.gl_patch_vertices,
|
||||
buffer, offset, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
|
||||
struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture)
|
||||
{
|
||||
|
|
|
@ -460,8 +460,7 @@ static GLenum gl_tfb_primitive_type_from_d3d(enum wined3d_primitive_type primiti
|
|||
|
||||
/* Routine common to the draw primitive and draw indexed primitive routines */
|
||||
void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state,
|
||||
int base_vertex_idx, unsigned int start_idx, unsigned int index_count,
|
||||
unsigned int start_instance, unsigned int instance_count, BOOL indexed)
|
||||
const struct wined3d_draw_parameters *parameters)
|
||||
{
|
||||
BOOL emulation = FALSE, rasterizer_discard = FALSE;
|
||||
const struct wined3d_fb_state *fb = state->fb;
|
||||
|
@ -474,7 +473,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
|
|||
unsigned int i, idx_size = 0;
|
||||
const void *idx_data = NULL;
|
||||
|
||||
if (!index_count)
|
||||
if (!parameters->indirect && !parameters->u.direct.index_count)
|
||||
return;
|
||||
|
||||
if (!(rtv = fb->render_targets[0]))
|
||||
|
@ -541,10 +540,8 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
|
|||
}
|
||||
|
||||
stream_info = &context->stream_info;
|
||||
if (context->instance_count)
|
||||
instance_count = context->instance_count;
|
||||
|
||||
if (indexed)
|
||||
if (parameters->indexed)
|
||||
{
|
||||
struct wined3d_buffer *index_buffer = state->index_buffer;
|
||||
if (!index_buffer->buffer_object || !stream_info->all_vbo)
|
||||
|
@ -631,12 +628,51 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
|
|||
checkGLcall("glPatchParameteri");
|
||||
}
|
||||
|
||||
if (parameters->indirect)
|
||||
{
|
||||
if (!context->use_immediate_mode_draw && !emulation)
|
||||
{
|
||||
struct wined3d_buffer *buffer = parameters->u.indirect.buffer;
|
||||
|
||||
wined3d_buffer_load(buffer, context, state);
|
||||
GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->buffer_object));
|
||||
|
||||
if (idx_size)
|
||||
{
|
||||
GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||
GL_EXTCALL(glDrawElementsIndirect(state->gl_primitive_type, idx_type,
|
||||
(void *)(GLintptr)parameters->u.indirect.offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_EXTCALL(glDrawArraysIndirect(state->gl_primitive_type,
|
||||
(void *)(GLintptr)parameters->u.indirect.offset));
|
||||
}
|
||||
|
||||
GL_EXTCALL(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0));
|
||||
|
||||
checkGLcall("draw indirect");
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("Indirect draws with immediate mode/emulation are not supported.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int instance_count = parameters->u.direct.instance_count;
|
||||
if (context->instance_count)
|
||||
instance_count = context->instance_count;
|
||||
|
||||
if (context->use_immediate_mode_draw || emulation)
|
||||
draw_primitive_immediate_mode(context, state, stream_info, idx_data,
|
||||
idx_size, base_vertex_idx, start_idx, index_count, instance_count);
|
||||
idx_size, parameters->u.direct.base_vertex_idx,
|
||||
parameters->u.direct.start_idx, parameters->u.direct.index_count, instance_count);
|
||||
else
|
||||
draw_primitive_arrays(context, state, idx_data, idx_size, base_vertex_idx,
|
||||
start_idx, index_count, start_instance, instance_count);
|
||||
draw_primitive_arrays(context, state, idx_data, idx_size, parameters->u.direct.base_vertex_idx,
|
||||
parameters->u.direct.start_idx, parameters->u.direct.index_count,
|
||||
parameters->u.direct.start_instance, instance_count);
|
||||
}
|
||||
|
||||
if (context->uses_uavs)
|
||||
{
|
||||
|
|
|
@ -45,8 +45,10 @@
|
|||
@ cdecl wined3d_device_dispatch_compute_indirect(ptr ptr long)
|
||||
@ cdecl wined3d_device_draw_indexed_primitive(ptr long long)
|
||||
@ cdecl wined3d_device_draw_indexed_primitive_instanced(ptr long long long long)
|
||||
@ cdecl wined3d_device_draw_indexed_primitive_instanced_indirect(ptr ptr long)
|
||||
@ cdecl wined3d_device_draw_primitive(ptr long long)
|
||||
@ cdecl wined3d_device_draw_primitive_instanced(ptr long long long long)
|
||||
@ cdecl wined3d_device_draw_primitive_instanced_indirect(ptr ptr long)
|
||||
@ cdecl wined3d_device_end_scene(ptr)
|
||||
@ cdecl wined3d_device_end_stateblock(ptr ptr)
|
||||
@ cdecl wined3d_device_evict_managed_resources(ptr)
|
||||
|
|
|
@ -1515,9 +1515,34 @@ struct wined3d_dispatch_parameters
|
|||
} u;
|
||||
};
|
||||
|
||||
struct wined3d_direct_draw_parameters
|
||||
{
|
||||
int base_vertex_idx;
|
||||
unsigned int start_idx;
|
||||
unsigned int index_count;
|
||||
unsigned int start_instance;
|
||||
unsigned int instance_count;
|
||||
};
|
||||
|
||||
struct wined3d_indirect_draw_parameters
|
||||
{
|
||||
struct wined3d_buffer *buffer;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
struct wined3d_draw_parameters
|
||||
{
|
||||
BOOL indirect;
|
||||
union
|
||||
{
|
||||
struct wined3d_direct_draw_parameters direct;
|
||||
struct wined3d_indirect_draw_parameters indirect;
|
||||
} u;
|
||||
BOOL indexed;
|
||||
};
|
||||
|
||||
void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state,
|
||||
int base_vertex_idx, unsigned int start_idx, unsigned int index_count,
|
||||
unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN;
|
||||
const struct wined3d_draw_parameters *draw_parameters) DECLSPEC_HIDDEN;
|
||||
void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state,
|
||||
const struct wined3d_dispatch_parameters *dispatch_parameters) DECLSPEC_HIDDEN;
|
||||
DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
|
||||
|
@ -3472,6 +3497,8 @@ void wined3d_cs_emit_dispatch_indirect(struct wined3d_cs *cs,
|
|||
void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count,
|
||||
int base_vertex_idx, unsigned int start_idx, unsigned int index_count,
|
||||
unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count,
|
||||
struct wined3d_buffer *buffer, unsigned int offset, BOOL indexed) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain,
|
||||
|
|
|
@ -2222,9 +2222,13 @@ void __cdecl wined3d_device_dispatch_compute_indirect(struct wined3d_device *dev
|
|||
HRESULT __cdecl wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count);
|
||||
void __cdecl wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device,
|
||||
UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count);
|
||||
void __cdecl wined3d_device_draw_indexed_primitive_instanced_indirect(struct wined3d_device *device,
|
||||
struct wined3d_buffer *buffer, unsigned int offset);
|
||||
HRESULT __cdecl wined3d_device_draw_primitive(struct wined3d_device *device, UINT start_vertex, UINT vertex_count);
|
||||
void __cdecl wined3d_device_draw_primitive_instanced(struct wined3d_device *device,
|
||||
UINT start_vertex, UINT vertex_count, UINT start_instance, UINT instance_count);
|
||||
void __cdecl wined3d_device_draw_primitive_instanced_indirect(struct wined3d_device *device,
|
||||
struct wined3d_buffer *buffer, unsigned int offset);
|
||||
HRESULT __cdecl wined3d_device_end_scene(struct wined3d_device *device);
|
||||
HRESULT __cdecl wined3d_device_end_stateblock(struct wined3d_device *device, struct wined3d_stateblock **stateblock);
|
||||
void __cdecl wined3d_device_evict_managed_resources(struct wined3d_device *device);
|
||||
|
|
Loading…
Reference in New Issue