From f4a34acf1773ffe4cfaab78af3c9f595fa033fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Fri, 12 May 2017 15:09:20 +0200 Subject: [PATCH] wined3d: Implement clearing buffer unordered access views. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/cs.c | 123 +++++++++++++++++++++------------ dlls/wined3d/device.c | 8 +++ dlls/wined3d/utils.c | 8 +++ dlls/wined3d/view.c | 69 +++++++++++++++--- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 5 ++ include/wine/wined3d.h | 2 + 7 files changed, 162 insertions(+), 54 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index d1d654c8f2b..c878d2488a3 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -69,6 +69,7 @@ enum wined3d_cs_op WINED3D_CS_OP_BLT_SUB_RESOURCE, WINED3D_CS_OP_UPDATE_SUB_RESOURCE, WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION, + WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW, WINED3D_CS_OP_STOP, }; @@ -409,6 +410,13 @@ struct wined3d_cs_add_dirty_texture_region unsigned int layer; }; +struct wined3d_cs_clear_unordered_access_view +{ + enum wined3d_cs_op opcode; + struct wined3d_unordered_access_view *view; + struct wined3d_uvec4 clear_value; +}; + struct wined3d_cs_stop { enum wined3d_cs_op opcode; @@ -2184,6 +2192,34 @@ void wined3d_cs_emit_add_dirty_texture_region(struct wined3d_cs *cs, cs->ops->submit(cs); } +static void wined3d_cs_exec_clear_unordered_access_view(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_clear_unordered_access_view *op = data; + struct wined3d_unordered_access_view *view = op->view; + struct wined3d_context *context; + + context = context_acquire(cs->device, NULL, 0); + wined3d_unordered_access_view_clear_uint(view, &op->clear_value, context); + context_release(context); + + wined3d_resource_release(view->resource); +} + +void wined3d_cs_emit_clear_unordered_access_view_uint(struct wined3d_cs *cs, + struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value) +{ + struct wined3d_cs_clear_unordered_access_view *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW; + op->view = view; + op->clear_value = *clear_value; + + wined3d_resource_acquire(view->resource); + + cs->ops->submit(cs); +} + static void wined3d_cs_emit_stop(struct wined3d_cs *cs) { struct wined3d_cs_stop *op; @@ -2197,49 +2233,50 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs) static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = { - /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, - /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, - /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, - /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch, - /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, - /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush, - /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, - /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, - /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, - /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, - /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, - /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, - /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, - /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, - /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, - /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, - /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, - /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, - /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, - /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view, - /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, - /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, - /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state, - /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, - /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, - /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, - /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, - /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, - /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, - /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, - /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, - /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, - /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, - /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, - /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback, - /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, - /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource, - /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, - /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, - /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, - /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, - /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, - /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region, + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, + /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, + /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, + /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch, + /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, + /* WINED3D_CS_OP_FLUSH */ wined3d_cs_exec_flush, + /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, + /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, + /* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect, + /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, + /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, + /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, + /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, + /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, + /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, + /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, + /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, + /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, + /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, + /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view, + /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, + /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, + /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state, + /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, + /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, + /* WINED3D_CS_OP_SET_SAMPLER_STATE */ wined3d_cs_exec_set_sampler_state, + /* WINED3D_CS_OP_SET_TRANSFORM */ wined3d_cs_exec_set_transform, + /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, + /* WINED3D_CS_OP_SET_COLOR_KEY */ wined3d_cs_exec_set_color_key, + /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, + /* WINED3D_CS_OP_SET_LIGHT */ wined3d_cs_exec_set_light, + /* WINED3D_CS_OP_SET_LIGHT_ENABLE */ wined3d_cs_exec_set_light_enable, + /* WINED3D_CS_OP_PUSH_CONSTANTS */ wined3d_cs_exec_push_constants, + /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, + /* WINED3D_CS_OP_CALLBACK */ wined3d_cs_exec_callback, + /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, + /* WINED3D_CS_OP_PRELOAD_RESOURCE */ wined3d_cs_exec_preload_resource, + /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, + /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, + /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, + /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, + /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, + /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region, + /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view, }; static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 4b4baeefcf8..61be30eb162 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4255,6 +4255,14 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi return WINED3D_OK; } +void CDECL wined3d_device_clear_unordered_access_view_uint(struct wined3d_device *device, + struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value) +{ + TRACE("device %p, view %p, clear_value %s.\n", device, view, debug_uvec4(clear_value)); + + wined3d_cs_emit_clear_unordered_access_view_uint(device->cs, view, clear_value); +} + struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, unsigned int view_idx) { diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index bd83446b914..fb4a8495538 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3757,6 +3757,14 @@ const char *debug_ivec4(const struct wined3d_ivec4 *v) v->x, v->y, v->z, v->w); } +const char *debug_uvec4(const struct wined3d_uvec4 *v) +{ + if (!v) + return "(null)"; + return wine_dbg_sprintf("{%u, %u, %u, %u}", + v->x, v->y, v->z, v->w); +} + const char *debug_vec4(const struct wined3d_vec4 *v) { if (!v) diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 3abd85be9be..fce3ea25ff6 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -250,23 +250,29 @@ static void create_buffer_texture(struct wined3d_gl_view *view, struct wined3d_c context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); } +static void get_buffer_view_range(const struct wined3d_buffer *buffer, + const struct wined3d_view_desc *desc, const struct wined3d_format *view_format, + unsigned int *offset, unsigned int *size) +{ + if (desc->format_id == WINED3DFMT_UNKNOWN) + { + *offset = desc->u.buffer.start_idx * buffer->desc.structure_byte_stride; + *size = desc->u.buffer.count * buffer->desc.structure_byte_stride; + } + else + { + *offset = desc->u.buffer.start_idx * view_format->byte_count; + *size = desc->u.buffer.count * view_format->byte_count; + } +} + static void create_buffer_view(struct wined3d_gl_view *view, struct wined3d_context *context, const struct wined3d_view_desc *desc, struct wined3d_buffer *buffer, const struct wined3d_format *view_format) { unsigned int offset, size; - if (desc->format_id == WINED3DFMT_UNKNOWN) - { - offset = desc->u.buffer.start_idx * buffer->desc.structure_byte_stride; - size = desc->u.buffer.count * buffer->desc.structure_byte_stride; - } - else - { - offset = desc->u.buffer.start_idx * view_format->byte_count; - size = desc->u.buffer.count * view_format->byte_count; - } - + get_buffer_view_range(buffer, desc, view_format, &offset, &size); create_buffer_texture(view, context, buffer, view_format, offset, size); } @@ -850,6 +856,47 @@ void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_ wined3d_view_invalidate_location(view->resource, &view->desc, location); } +void wined3d_unordered_access_view_clear_uint(struct wined3d_unordered_access_view *view, + const struct wined3d_uvec4 *clear_value, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_format *format; + struct wined3d_resource *resource; + struct wined3d_buffer *buffer; + unsigned int offset, size; + + resource = view->resource; + if (resource->type != WINED3D_RTYPE_BUFFER) + { + FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); + return; + } + + if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT]) + { + FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n"); + return; + } + + format = view->format; + if (format->id != WINED3DFMT_R32_UINT && format->id != WINED3DFMT_R32_SINT + && format->id != WINED3DFMT_R32G32B32A32_UINT + && format->id != WINED3DFMT_R32G32B32A32_SINT) + { + FIXME("Not implemented for format %s.\n", debug_d3dformat(format->id)); + return; + } + + buffer = buffer_from_resource(resource); + wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER); + wined3d_unordered_access_view_invalidate_location(view, ~WINED3D_LOCATION_BUFFER); + + get_buffer_view_range(buffer, &view->desc, format, &offset, &size); + context_bind_bo(context, buffer->buffer_type_hint, buffer->buffer_object); + GL_EXTCALL(glClearBufferSubData(buffer->buffer_type_hint, format->glInternal, + offset, size, format->glFormat, format->glType, clear_value)); +} + static void wined3d_unordered_access_view_cs_init(void *object) { struct wined3d_unordered_access_view *view = object; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 4e728f30dfd..26af67145e2 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -35,6 +35,7 @@ @ cdecl wined3d_device_begin_stateblock(ptr) @ cdecl wined3d_device_clear(ptr long ptr long ptr float long) @ cdecl wined3d_device_clear_rendertarget_view(ptr ptr ptr long ptr float long) +@ cdecl wined3d_device_clear_unordered_access_view_uint(ptr ptr ptr) @ cdecl wined3d_device_copy_resource(ptr ptr ptr) @ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr) @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e68f03a26b7..38e5a4597a8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3291,6 +3291,8 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; void wined3d_cs_emit_clear_rendertarget_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, const RECT *rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; +void wined3d_cs_emit_clear_unordered_access_view_uint(struct wined3d_cs *cs, + struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value) DECLSPEC_HIDDEN; void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) DECLSPEC_HIDDEN; void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, int base_vertex_idx, @@ -3511,6 +3513,8 @@ struct wined3d_unordered_access_view struct wined3d_view_desc desc; }; +void wined3d_unordered_access_view_clear_uint(struct wined3d_unordered_access_view *view, + const struct wined3d_uvec4 *clear_value, struct wined3d_context *context) DECLSPEC_HIDDEN; void wined3d_unordered_access_view_invalidate_location(struct wined3d_unordered_access_view *view, DWORD location) DECLSPEC_HIDDEN; @@ -3588,6 +3592,7 @@ const char *debug_fboattachment(GLenum attachment) DECLSPEC_HIDDEN; const char *debug_fbostatus(GLenum status) DECLSPEC_HIDDEN; const char *debug_glerror(GLenum error) DECLSPEC_HIDDEN; const char *debug_ivec4(const struct wined3d_ivec4 *v) DECLSPEC_HIDDEN; +const char *debug_uvec4(const struct wined3d_uvec4 *v) DECLSPEC_HIDDEN; const char *debug_shader_type(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN; const char *debug_vec4(const struct wined3d_vec4 *v) DECLSPEC_HIDDEN; void dump_color_fixup_desc(struct color_fixup_desc fixup) DECLSPEC_HIDDEN; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 96de6f90758..d58c4b4dfba 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2175,6 +2175,8 @@ HRESULT __cdecl wined3d_device_clear(struct wined3d_device *device, DWORD rect_c HRESULT __cdecl wined3d_device_clear_rendertarget_view(struct wined3d_device *device, struct wined3d_rendertarget_view *view, const RECT *rect, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil); +void __cdecl wined3d_device_clear_unordered_access_view_uint(struct wined3d_device *device, + struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value); void __cdecl wined3d_device_copy_resource(struct wined3d_device *device, struct wined3d_resource *dst_resource, struct wined3d_resource *src_resource); HRESULT __cdecl wined3d_device_copy_sub_resource_region(struct wined3d_device *device,