From: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 2 +- dlls/wined3d/device.c | 10 ++++++---- dlls/wined3d/wined3d_private.h | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 9864093c999..fc7a8964923 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4564,7 +4564,7 @@ static HRESULT adapter_gl_init_3d(struct wined3d_device *device) { TRACE("device %p.\n", device);
- wined3d_cs_init_object(device->cs, wined3d_device_create_primary_opengl_context_cs, device); + wined3d_cs_init_object(device->cs, wined3d_device_gl_create_primary_opengl_context_cs, wined3d_device_gl(device)); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); if (!wined3d_swapchain_gl(device->swapchains[0])->context_count) return E_FAIL; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index c516594c269..067d54d58e3 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -989,17 +989,19 @@ void wined3d_device_delete_opengl_contexts_cs(void *object) } }
-void wined3d_device_create_primary_opengl_context_cs(void *object) +void wined3d_device_gl_create_primary_opengl_context_cs(void *object) { - struct wined3d_device *device = object; + struct wined3d_device_gl *device_gl = object; struct wined3d_context_gl *context_gl; struct wined3d_swapchain *swapchain; struct wined3d_context *context; struct wined3d_texture *target; + struct wined3d_device *device; HRESULT hr;
- TRACE("device %p.\n", device); + TRACE("device %p.\n", device_gl);
+ device = &device_gl->d; swapchain = device->swapchains[0]; target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer; if (!(context = context_acquire(device, target, 0))) @@ -1032,7 +1034,7 @@ void wined3d_device_create_primary_opengl_context_cs(void *object) wined3d_fbo_blitter_create(&device->blitter, context_gl->gl_info); wined3d_raw_blitter_create(&device->blitter, context_gl->gl_info);
- wined3d_device_gl_create_dummy_textures(wined3d_device_gl(device), context_gl); + wined3d_device_gl_create_dummy_textures(device_gl, context_gl); wined3d_device_create_default_samplers(device, context); context_release(context); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b30a4108b0b..c8f24c41fd5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3920,7 +3920,6 @@ BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *c void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; void wined3d_device_create_default_samplers(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; -void wined3d_device_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; void wined3d_device_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN; void wined3d_device_destroy_default_samplers(struct wined3d_device *device) DECLSPEC_HIDDEN; HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined3d, @@ -3964,6 +3963,8 @@ static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device return CONTAINING_RECORD(device, struct wined3d_device_gl, d); }
+void wined3d_device_gl_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; + struct wined3d_null_resources_vk { struct wined3d_bo_vk bo;
From: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 2 +- dlls/wined3d/device.c | 10 ++++------ dlls/wined3d/wined3d_private.h | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index fc7a8964923..6cc2f0cd9a8 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4577,7 +4577,7 @@ static void adapter_gl_uninit_3d(struct wined3d_device *device) TRACE("device %p.\n", device);
wined3d_device_destroy_default_samplers(device); - wined3d_cs_destroy_object(device->cs, wined3d_device_delete_opengl_contexts_cs, device); + wined3d_cs_destroy_object(device->cs, wined3d_device_gl_delete_opengl_contexts_cs, wined3d_device_gl(device)); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); }
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 067d54d58e3..2e98e13093e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -955,18 +955,16 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi wined3d_device_context_set_depth_stencil_view(context, ds_enable ? device->auto_depth_stencil_view : NULL); }
-void wined3d_device_delete_opengl_contexts_cs(void *object) +void wined3d_device_gl_delete_opengl_contexts_cs(void *object) { + struct wined3d_device_gl *device_gl = object; struct wined3d_swapchain_gl *swapchain_gl; - struct wined3d_device *device = object; struct wined3d_context_gl *context_gl; - struct wined3d_device_gl *device_gl; struct wined3d_context *context; + struct wined3d_device *device; struct wined3d_shader *shader;
- TRACE("device %p.\n", device); - - device_gl = wined3d_device_gl(device); + device = &device_gl->d;
LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c8f24c41fd5..ecb5182eb13 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3920,7 +3920,6 @@ BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *c void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; void wined3d_device_create_default_samplers(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; -void wined3d_device_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN; void wined3d_device_destroy_default_samplers(struct wined3d_device *device) DECLSPEC_HIDDEN; HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined3d, unsigned int adapter_idx, enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, @@ -3964,6 +3963,7 @@ static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device }
void wined3d_device_gl_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; +void wined3d_device_gl_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN;
struct wined3d_null_resources_vk {
On Thu, 9 Dec 2021 at 05:41, Zebediah Figura zfigura@codeweavers.com wrote:
+void wined3d_device_gl_delete_opengl_contexts_cs(void *object) {
- struct wined3d_device_gl *device_gl = object; struct wined3d_swapchain_gl *swapchain_gl;
- struct wined3d_device *device = object; struct wined3d_context_gl *context_gl;
- struct wined3d_device_gl *device_gl; struct wined3d_context *context;
- struct wined3d_device *device; struct wined3d_shader *shader;
- TRACE("device %p.\n", device);
- device_gl = wined3d_device_gl(device);
- device = &device_gl->d;
I think that TRACE is useful, and it was in fact explicitly added not that long ago in 7ba0cc908506b821abef10ea2748e55d9de10787.
On 12/9/21 06:53, Henri Verbeet wrote:
On Thu, 9 Dec 2021 at 05:41, Zebediah Figura zfigura@codeweavers.com wrote:
+void wined3d_device_gl_delete_opengl_contexts_cs(void *object) {
- struct wined3d_device_gl *device_gl = object; struct wined3d_swapchain_gl *swapchain_gl;
- struct wined3d_device *device = object; struct wined3d_context_gl *context_gl;
- struct wined3d_device_gl *device_gl; struct wined3d_context *context;
- struct wined3d_device *device; struct wined3d_shader *shader;
- TRACE("device %p.\n", device);
- device_gl = wined3d_device_gl(device);
- device = &device_gl->d;
I think that TRACE is useful, and it was in fact explicitly added not that long ago in 7ba0cc908506b821abef10ea2748e55d9de10787.
Indeed. I think my brain saw the trace in adapter_gl_uninit_3d() and decided that it was close enough, without realizing that there was a CS boundary, plus a few other wined3d calls, between the two. I'll resend with the trace restored.
From: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 1 + dlls/wined3d/context_gl.c | 302 ++++++++++++++++++++++++++++----- dlls/wined3d/device.c | 110 ++++++++++++ dlls/wined3d/wined3d_private.h | 66 ++++--- 4 files changed, 420 insertions(+), 59 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 6cc2f0cd9a8..03bb3e75047 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4281,6 +4281,7 @@ static void adapter_gl_destroy_device(struct wined3d_device *device) struct wined3d_device_gl *device_gl = wined3d_device_gl(device);
wined3d_device_cleanup(&device_gl->d); + heap_free(device_gl->retired_blocks); heap_free(device_gl); }
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 6391f6788e9..71b6e4fda53 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2618,6 +2618,37 @@ static void wined3d_context_gl_poll_fences(struct wined3d_context_gl *context_gl } }
+static void wined3d_context_gl_cleanup_resources(struct wined3d_context_gl *context_gl) +{ + struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); + struct wined3d_retired_block_gl *r, *blocks; + SIZE_T count, i = 0; + uint64_t id; + + wined3d_context_gl_poll_fences(context_gl); + id = device_gl->completed_fence_id; + + blocks = device_gl->retired_blocks; + count = device_gl->retired_block_count; + while (i < count) + { + r = &blocks[i]; + + if (r->fence_id > id) + { + ++i; + continue; + } + + wined3d_allocator_block_free(r->block); + if (i != --count) + *r = blocks[count]; + else + ++i; + } + device_gl->retired_block_count = count; +} + void wined3d_context_gl_wait_command_fence(struct wined3d_context_gl *context_gl, uint64_t id) { struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); @@ -2635,7 +2666,7 @@ void wined3d_context_gl_wait_command_fence(struct wined3d_context_gl *context_gl
if ((ret = wined3d_fence_wait(context_gl->submitted.fences[i].fence, &device_gl->d)) != WINED3D_FENCE_OK) ERR("Failed to wait for command fence with id 0x%s, ret %#x.\n", wine_dbgstr_longlong(id), ret); - wined3d_context_gl_poll_fences(context_gl); + wined3d_context_gl_cleanup_resources(context_gl); return; }
@@ -2665,7 +2696,133 @@ void wined3d_context_gl_submit_command_fence(struct wined3d_context_gl *context_ device_gl->completed_fence_id = 0; device_gl->current_fence_id = 1; } - wined3d_context_gl_poll_fences(context_gl); + wined3d_context_gl_cleanup_resources(context_gl); +} + +static void wined3d_context_gl_destroy_allocator_block(struct wined3d_context_gl *context_gl, + struct wined3d_allocator_block *block, uint64_t fence_id) +{ + struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); + struct wined3d_retired_block_gl *r; + + if (device_gl->completed_fence_id > fence_id) + { + wined3d_allocator_block_free(block); + TRACE("Freed block %p.\n", block); + return; + } + + if (!wined3d_array_reserve((void **)&device_gl->retired_blocks, + &device_gl->retired_blocks_size, device_gl->retired_block_count + 1, + sizeof(*device_gl->retired_blocks))) + { + ERR("Leaking block %p.\n", block); + return; + } + + r = &device_gl->retired_blocks[device_gl->retired_block_count++]; + r->block = block; + r->fence_id = fence_id; +} + +/* We always have buffer storage here. */ +GLuint wined3d_context_gl_allocate_vram_chunk_buffer(struct wined3d_context_gl *context_gl, + unsigned int pool, size_t size) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + GLbitfield flags; + GLuint id = 0; + + TRACE("context_gl %p, pool %u, size %zu.\n", context_gl, pool, size); + + GL_EXTCALL(glGenBuffers(1, &id)); + if (!id) + { + checkGLcall("buffer object creation"); + return 0; + } + wined3d_context_gl_bind_bo(context_gl, GL_PIXEL_UNPACK_BUFFER, id); + + flags = wined3d_device_gl_get_memory_type_flags(pool) | GL_DYNAMIC_STORAGE_BIT; + if (flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) + flags |= GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; + GL_EXTCALL(glBufferStorage(GL_PIXEL_UNPACK_BUFFER, size, NULL, flags)); + + checkGLcall("buffer object creation"); + + TRACE("Created buffer object %u.\n", id); + + return id; +} + +static struct wined3d_allocator_block *wined3d_context_gl_allocate_memory(struct wined3d_context_gl *context_gl, + unsigned int memory_type, GLsizeiptr size, GLuint *id) +{ + struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); + struct wined3d_allocator *allocator = &device_gl->allocator; + struct wined3d_allocator_block *block; + + if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2) + { + *id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type, size); + return NULL; + } + + if (!(block = wined3d_allocator_allocate(allocator, &context_gl->c, memory_type, size))) + { + *id = 0; + return NULL; + } + + *id = wined3d_allocator_chunk_gl(block->chunk)->gl_buffer; + + return block; +} + +static void *wined3d_allocator_chunk_gl_map(struct wined3d_allocator_chunk_gl *chunk_gl, + struct wined3d_context_gl *context_gl) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + + TRACE("chunk %p, gl_buffer %u, map_ptr %p.\n", chunk_gl, chunk_gl->gl_buffer, chunk_gl->c.map_ptr); + + if (!chunk_gl->c.map_ptr) + { + unsigned int flags = wined3d_device_gl_get_memory_type_flags(chunk_gl->memory_type) & ~GL_CLIENT_STORAGE_BIT; + + flags |= GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; + if (!(flags & GL_MAP_READ_BIT)) + flags |= GL_MAP_UNSYNCHRONIZED_BIT; + if (flags & GL_MAP_WRITE_BIT) + flags |= GL_MAP_FLUSH_EXPLICIT_BIT; + wined3d_context_gl_bind_bo(context_gl, GL_PIXEL_UNPACK_BUFFER, chunk_gl->gl_buffer); + chunk_gl->c.map_ptr = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, + 0, WINED3D_ALLOCATOR_CHUNK_SIZE, flags)); + if (!chunk_gl->c.map_ptr) + { + ERR("Failed to map chunk memory.\n"); + return NULL; + } + } + + ++chunk_gl->c.map_count; + + return chunk_gl->c.map_ptr; +} + +static void wined3d_allocator_chunk_gl_unmap(struct wined3d_allocator_chunk_gl *chunk_gl, + struct wined3d_context_gl *context_gl) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + + TRACE("chunk_gl %p, context_gl %p.\n", chunk_gl, context_gl); + + if (!--chunk_gl->c.map_count && !wined3d_map_persistent()) + { + wined3d_context_gl_bind_bo(context_gl, GL_PIXEL_UNPACK_BUFFER, chunk_gl->gl_buffer); + GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); + chunk_gl->c.map_ptr = NULL; + } }
static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, struct wined3d_context_gl *context_gl, uint32_t flags) @@ -2708,33 +2865,65 @@ map: if (bo->b.map_ptr) return (uint8_t *)bo->b.map_ptr;
- gl_info = context_gl->gl_info; - wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); - - if (gl_info->supported[ARB_BUFFER_STORAGE]) + if (bo->memory) { - if ((map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, - GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | wined3d_resource_gl_map_flags(bo, flags))))) + struct wined3d_allocator_chunk_gl *chunk_gl = wined3d_allocator_chunk_gl(bo->memory->chunk); + + if (!(map_ptr = wined3d_allocator_chunk_gl_map(chunk_gl, context_gl))) { - if (wined3d_map_persistent()) - bo->b.map_ptr = map_ptr; + ERR("Failed to map chunk.\n"); + return NULL; } } - else if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) - { - map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, wined3d_resource_gl_map_flags(bo, flags))); - } else { - map_ptr = GL_EXTCALL(glMapBuffer(bo->binding, wined3d_resource_gl_legacy_map_flags(flags))); - } + gl_info = context_gl->gl_info; + wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id);
- wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); - checkGLcall("Map buffer object"); + if (gl_info->supported[ARB_BUFFER_STORAGE]) + { + if ((map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, + GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | wined3d_resource_gl_map_flags(bo, flags))))) + { + if (wined3d_map_persistent()) + bo->b.map_ptr = map_ptr; + } + } + else if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, wined3d_resource_gl_map_flags(bo, flags))); + } + else + { + map_ptr = GL_EXTCALL(glMapBuffer(bo->binding, wined3d_resource_gl_legacy_map_flags(flags))); + } + + wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); + checkGLcall("Map buffer object"); + }
return map_ptr; }
+static void wined3d_bo_gl_unmap(struct wined3d_bo_gl *bo, struct wined3d_context_gl *context_gl) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + + if (bo->b.map_ptr) + return; + + gl_info = context_gl->gl_info; + wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); + + if (bo->memory) + wined3d_allocator_chunk_gl_unmap(wined3d_allocator_chunk_gl(bo->memory->chunk), context_gl); + else + GL_EXTCALL(glUnmapBuffer(bo->binding)); + + wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); + checkGLcall("Unmap buffer object"); +} + void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *data, size_t size, uint32_t flags) { @@ -2794,7 +2983,6 @@ static void flush_bo_ranges(struct wined3d_context_gl *context_gl, const struct void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges) { - const struct wined3d_gl_info *gl_info; struct wined3d_bo_gl *bo;
if (!data->buffer_object) @@ -2802,15 +2990,7 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, bo = wined3d_bo_gl(data->buffer_object);
flush_bo_ranges(context_gl, wined3d_const_bo_address(data), range_count, ranges); - - if (bo->b.map_ptr) - return; - - gl_info = context_gl->gl_info; - wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); - GL_EXTCALL(glUnmapBuffer(bo->binding)); - wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); - checkGLcall("Unmap buffer object"); + wined3d_bo_gl_unmap(bo, context_gl); }
void wined3d_context_gl_flush_bo_address(struct wined3d_context_gl *context_gl, @@ -2893,7 +3073,23 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct
TRACE("context_gl %p, bo %p.\n", context_gl, bo);
+ if (bo->memory) + { + if (bo->b.map_ptr) + wined3d_allocator_chunk_gl_unmap(wined3d_allocator_chunk_gl(bo->memory->chunk), context_gl); + wined3d_context_gl_destroy_allocator_block(context_gl, bo->memory, bo->command_fence_id); + bo->id = 0; + return; + } + + if (bo->b.map_ptr) + { + wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); + GL_EXTCALL(glUnmapBuffer(bo->binding)); + } + TRACE("Destroying GL buffer %u.\n", bo->id); + GL_EXTCALL(glDeleteBuffers(1, &bo->id)); checkGLcall("buffer object destruction"); bo->id = 0; @@ -2902,12 +3098,45 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) { + unsigned int memory_type_idx = wined3d_device_gl_find_memory_type(flags); const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct wined3d_allocator_block *memory = NULL; + GLsizeiptr buffer_offset = 0; GLuint id = 0;
TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, flags %#x, bo %p.\n", context_gl, size, binding, usage, coherent, flags, bo);
+ if (gl_info->supported[ARB_BUFFER_STORAGE]) + { + switch (binding) + { + case GL_ARRAY_BUFFER: + case GL_ATOMIC_COUNTER_BUFFER: + case GL_DRAW_INDIRECT_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_TEXTURE_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + if ((memory = wined3d_context_gl_allocate_memory(context_gl, memory_type_idx, size, &id))) + buffer_offset = memory->offset; + break; + + default: + WARN_(d3d_perf)("Not allocating chunk memory for binding type %#x.\n", binding); + id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type_idx, size); + break; + } + + if (!id) + { + WARN("Failed to allocate buffer.\n"); + return false; + } + + goto done; + } + GL_EXTCALL(glGenBuffers(1, &id)); if (!id) { @@ -2922,22 +3151,15 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); }
- if (gl_info->supported[ARB_BUFFER_STORAGE]) - { - if (flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) - flags |= GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; - GL_EXTCALL(glBufferStorage(binding, size, NULL, flags | GL_DYNAMIC_STORAGE_BIT)); - } - else - { - GL_EXTCALL(glBufferData(binding, size, NULL, usage)); - } + GL_EXTCALL(glBufferData(binding, size, NULL, usage));
wined3d_context_gl_bind_bo(context_gl, binding, 0); checkGLcall("buffer object creation");
+done: TRACE("Created buffer object %u.\n", id); bo->id = id; + bo->memory = memory; bo->size = size; bo->binding = binding; bo->usage = usage; @@ -2945,8 +3167,8 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei bo->b.coherent = coherent; list_init(&bo->b.users); bo->command_fence_id = 0; - bo->b.memory_offset = 0; - bo->b.buffer_offset = 0; + bo->b.buffer_offset = buffer_offset; + bo->b.memory_offset = bo->b.buffer_offset; bo->b.map_ptr = NULL;
return true; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2e98e13093e..6f9e8464587 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -955,6 +955,101 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi wined3d_device_context_set_depth_stencil_view(context, ds_enable ? device->auto_depth_stencil_view : NULL); }
+static struct wined3d_allocator_chunk *wined3d_allocator_gl_create_chunk(struct wined3d_allocator *allocator, + struct wined3d_context *context, unsigned int memory_type, size_t chunk_size) +{ + struct wined3d_context_gl *context_gl = wined3d_context_gl(context); + struct wined3d_allocator_chunk_gl *chunk_gl; + + TRACE("allocator %p, context %p, memory_type %u, chunk_size %zu.\n", allocator, context, memory_type, chunk_size); + + if (!(chunk_gl = heap_alloc(sizeof(*chunk_gl)))) + return NULL; + + if (!wined3d_allocator_chunk_init(&chunk_gl->c, allocator)) + { + heap_free(chunk_gl); + return NULL; + } + + chunk_gl->memory_type = memory_type; + if (!(chunk_gl->gl_buffer = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type, chunk_size))) + { + wined3d_allocator_chunk_cleanup(&chunk_gl->c); + heap_free(chunk_gl); + return NULL; + } + list_add_head(&allocator->pools[memory_type].chunks, &chunk_gl->c.entry); + + return &chunk_gl->c; +} + +static void wined3d_allocator_gl_destroy_chunk(struct wined3d_allocator_chunk *chunk) +{ + struct wined3d_allocator_chunk_gl *chunk_gl = wined3d_allocator_chunk_gl(chunk); + const struct wined3d_gl_info *gl_info; + struct wined3d_context_gl *context_gl; + struct wined3d_device_gl *device_gl; + + TRACE("chunk %p.\n", chunk); + + device_gl = CONTAINING_RECORD(chunk_gl->c.allocator, struct wined3d_device_gl, allocator); + context_gl = wined3d_context_gl(context_acquire(&device_gl->d, NULL, 0)); + gl_info = context_gl->gl_info; + + wined3d_context_gl_bind_bo(context_gl, GL_PIXEL_UNPACK_BUFFER, chunk_gl->gl_buffer); + if (chunk_gl->c.map_ptr) + GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); + GL_EXTCALL(glDeleteBuffers(1, &chunk_gl->gl_buffer)); + TRACE("Freed buffer %u.\n", chunk_gl->gl_buffer); + wined3d_allocator_chunk_cleanup(&chunk_gl->c); + heap_free(chunk_gl); + + context_release(&context_gl->c); +} + +static const struct wined3d_allocator_ops wined3d_allocator_gl_ops = +{ + .allocator_create_chunk = wined3d_allocator_gl_create_chunk, + .allocator_destroy_chunk = wined3d_allocator_gl_destroy_chunk, +}; + +static const struct +{ + GLbitfield flags; +} +gl_memory_types[] = +{ + {0}, + {GL_MAP_READ_BIT}, + {GL_MAP_WRITE_BIT}, + {GL_MAP_READ_BIT | GL_MAP_WRITE_BIT}, + + {GL_CLIENT_STORAGE_BIT}, + {GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT}, + {GL_CLIENT_STORAGE_BIT | GL_MAP_WRITE_BIT}, + {GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT}, +}; + +unsigned int wined3d_device_gl_find_memory_type(GLbitfield flags) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gl_memory_types); ++i) + { + if (gl_memory_types[i].flags == flags) + return i; + } + + assert(0); + return 0; +} + +GLbitfield wined3d_device_gl_get_memory_type_flags(unsigned int memory_type_idx) +{ + return gl_memory_types[memory_type_idx].flags; +} + void wined3d_device_gl_delete_opengl_contexts_cs(void *object) { struct wined3d_device_gl *device_gl = object; @@ -976,6 +1071,12 @@ void wined3d_device_gl_delete_opengl_contexts_cs(void *object) device->blitter->ops->blitter_destroy(device->blitter, context); device->shader_backend->shader_free_private(device, context); wined3d_device_gl_destroy_dummy_textures(device_gl, context_gl); + + wined3d_context_gl_submit_command_fence(context_gl); + wined3d_context_gl_wait_command_fence(context_gl, + wined3d_device_gl(context_gl->c.device)->current_fence_id - 1); + wined3d_allocator_cleanup(&device_gl->allocator); + context_release(context);
while (device->context_count) @@ -1008,10 +1109,18 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) return; }
+ if (!wined3d_allocator_init(&device_gl->allocator, ARRAY_SIZE(gl_memory_types), &wined3d_allocator_gl_ops)) + { + WARN("Failed to initialise allocator.\n"); + context_release(context); + return; + } + if (FAILED(hr = device->shader_backend->shader_alloc_private(device, device->adapter->vertex_pipe, device->adapter->fragment_pipe))) { ERR("Failed to allocate shader private data, hr %#x.\n", hr); + wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); return; } @@ -1020,6 +1129,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) { ERR("Failed to create CPU blitter.\n"); device->shader_backend->shader_free_private(device, NULL); + wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); return; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ecb5182eb13..05f9be2c30f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1607,6 +1607,9 @@ struct wined3d_bo_gl struct wined3d_bo b;
GLuint id; + + struct wined3d_allocator_block *memory; + GLsizeiptr size; GLenum binding; GLenum usage; @@ -2345,6 +2348,8 @@ void wined3d_context_gl_alloc_so_statistics_query(struct wined3d_context_gl *con struct wined3d_so_statistics_query *query) DECLSPEC_HIDDEN; void wined3d_context_gl_alloc_timestamp_query(struct wined3d_context_gl *context_gl, struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; +GLuint wined3d_context_gl_allocate_vram_chunk_buffer(struct wined3d_context_gl *context_gl, + unsigned int pool, size_t size) DECLSPEC_HIDDEN; void wined3d_context_gl_apply_blit_state(struct wined3d_context_gl *context_gl, const struct wined3d_device *device) DECLSPEC_HIDDEN; BOOL wined3d_context_gl_apply_clear_state(struct wined3d_context_gl *context_gl, const struct wined3d_state *state, @@ -3946,25 +3951,6 @@ static inline struct wined3d_device_no3d *wined3d_device_no3d(struct wined3d_dev return CONTAINING_RECORD(device, struct wined3d_device_no3d, d); }
-struct wined3d_device_gl -{ - struct wined3d_device d; - - /* Textures for when no other textures are bound. */ - struct wined3d_dummy_textures dummy_textures; - - uint64_t completed_fence_id; - uint64_t current_fence_id; -}; - -static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device *device) -{ - return CONTAINING_RECORD(device, struct wined3d_device_gl, d); -} - -void wined3d_device_gl_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; -void wined3d_device_gl_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN; - struct wined3d_null_resources_vk { struct wined3d_bo_vk bo; @@ -4011,6 +3997,18 @@ void wined3d_allocator_chunk_cleanup(struct wined3d_allocator_chunk *chunk) DECL bool wined3d_allocator_chunk_init(struct wined3d_allocator_chunk *chunk, struct wined3d_allocator *allocator) DECLSPEC_HIDDEN;
+struct wined3d_allocator_chunk_gl +{ + struct wined3d_allocator_chunk c; + unsigned int memory_type; + GLuint gl_buffer; +}; + +static inline struct wined3d_allocator_chunk_gl *wined3d_allocator_chunk_gl(struct wined3d_allocator_chunk *chunk) +{ + return CONTAINING_RECORD(chunk, struct wined3d_allocator_chunk_gl, c); +} + struct wined3d_allocator_chunk_vk { struct wined3d_allocator_chunk c; @@ -4145,6 +4143,36 @@ void wined3d_device_vk_destroy_null_views(struct wined3d_device_vk *device_vk, void wined3d_device_vk_uav_clear_state_init(struct wined3d_device_vk *device_vk) DECLSPEC_HIDDEN; void wined3d_device_vk_uav_clear_state_cleanup(struct wined3d_device_vk *device_vk) DECLSPEC_HIDDEN;
+struct wined3d_device_gl +{ + struct wined3d_device d; + + /* Textures for when no other textures are bound. */ + struct wined3d_dummy_textures dummy_textures; + + struct wined3d_allocator allocator; + uint64_t completed_fence_id; + uint64_t current_fence_id; + + struct wined3d_retired_block_gl + { + struct wined3d_allocator_block *block; + uint64_t fence_id; + } *retired_blocks; + SIZE_T retired_blocks_size; + SIZE_T retired_block_count; +}; + +static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device *device) +{ + return CONTAINING_RECORD(device, struct wined3d_device_gl, d); +} + +void wined3d_device_gl_create_primary_opengl_context_cs(void *object) DECLSPEC_HIDDEN; +void wined3d_device_gl_delete_opengl_contexts_cs(void *object) DECLSPEC_HIDDEN; +unsigned int wined3d_device_gl_find_memory_type(GLbitfield flags) DECLSPEC_HIDDEN; +GLbitfield wined3d_device_gl_get_memory_type_flags(unsigned int memory_type_idx) DECLSPEC_HIDDEN; + static inline float wined3d_alpha_ref(const struct wined3d_state *state) { return (state->render_states[WINED3D_RS_ALPHAREF] & 0xff) / 255.0f;
On Thu, 9 Dec 2021 at 05:41, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -2902,12 +3098,45 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) {
unsigned int memory_type_idx = wined3d_device_gl_find_memory_type(flags); const struct wined3d_gl_info *gl_info = context_gl->gl_info;
struct wined3d_allocator_block *memory = NULL;
GLsizeiptr buffer_offset = 0; GLuint id = 0;
TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, flags %#x, bo %p.\n", context_gl, size, binding, usage, coherent, flags, bo);
if (gl_info->supported[ARB_BUFFER_STORAGE])
{
switch (binding)
{
case GL_ARRAY_BUFFER:
case GL_ATOMIC_COUNTER_BUFFER:
case GL_DRAW_INDIRECT_BUFFER:
case GL_PIXEL_UNPACK_BUFFER:
case GL_TEXTURE_BUFFER:
case GL_TRANSFORM_FEEDBACK_BUFFER:
case GL_UNIFORM_BUFFER:
if ((memory = wined3d_context_gl_allocate_memory(context_gl, memory_type_idx, size, &id)))
buffer_offset = memory->offset;
break;
default:
WARN_(d3d_perf)("Not allocating chunk memory for binding type %#x.\n", binding);
id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type_idx, size);
break;
}
if (!id)
{
WARN("Failed to allocate buffer.\n");
return false;
}
goto done;
}
GL_EXTCALL(glGenBuffers(1, &id)); if (!id) {
For bisection purposes, it would probably make sense to split this into several patches by binding type. I'm also a little hesitant about committing this so close before code-freeze. This is a fairly significant change to the way things work, and there are certainly opportunities for regressions here.
On 12/9/21 06:59, Henri Verbeet wrote:
On Thu, 9 Dec 2021 at 05:41, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -2902,12 +3098,45 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) {
unsigned int memory_type_idx = wined3d_device_gl_find_memory_type(flags); const struct wined3d_gl_info *gl_info = context_gl->gl_info;
struct wined3d_allocator_block *memory = NULL;
GLsizeiptr buffer_offset = 0; GLuint id = 0;
TRACE("context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, flags %#x, bo %p.\n", context_gl, size, binding, usage, coherent, flags, bo);
if (gl_info->supported[ARB_BUFFER_STORAGE])
{
switch (binding)
{
case GL_ARRAY_BUFFER:
case GL_ATOMIC_COUNTER_BUFFER:
case GL_DRAW_INDIRECT_BUFFER:
case GL_PIXEL_UNPACK_BUFFER:
case GL_TEXTURE_BUFFER:
case GL_TRANSFORM_FEEDBACK_BUFFER:
case GL_UNIFORM_BUFFER:
if ((memory = wined3d_context_gl_allocate_memory(context_gl, memory_type_idx, size, &id)))
buffer_offset = memory->offset;
break;
default:
WARN_(d3d_perf)("Not allocating chunk memory for binding type %#x.\n", binding);
id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type_idx, size);
break;
}
if (!id)
{
WARN("Failed to allocate buffer.\n");
return false;
}
goto done;
}
GL_EXTCALL(glGenBuffers(1, &id)); if (!id) {
For bisection purposes, it would probably make sense to split this into several patches by binding type. I'm also a little hesitant about committing this so close before code-freeze. This is a fairly significant change to the way things work, and there are certainly opportunities for regressions here.
Indeed, both good points...
I'll split this, and save it for after code freeze.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/buffer.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 2539401bf43..c078ba7e634 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1372,25 +1372,22 @@ static void wined3d_buffer_gl_unload_location(struct wined3d_buffer *buffer, static void wined3d_buffer_gl_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context, const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges) { - struct wined3d_context_gl *context_gl = wined3d_context_gl(context); - struct wined3d_bo_gl *bo_gl = wined3d_bo_gl(buffer->buffer_object); - struct wined3d_buffer_gl *buffer_gl = wined3d_buffer_gl(buffer); - const struct wined3d_gl_info *gl_info = context_gl->gl_info; - const struct wined3d_range *range; + struct wined3d_bo_address src, dst;
TRACE("buffer %p, context %p, data %p, data_offset %u, range_count %u, ranges %p.\n", buffer, context, data, data_offset, range_count, ranges);
- wined3d_buffer_gl_bind(buffer_gl, context_gl); + dst.buffer_object = buffer->buffer_object; + src.buffer_object = NULL;
while (range_count--) { - range = &ranges[range_count]; - GL_EXTCALL(glBufferSubData(bo_gl->binding, bo_gl->b.buffer_offset + range->offset, - range->size, (BYTE *)data + range->offset - data_offset)); + const struct wined3d_range *range = &ranges[range_count]; + + src.addr = (uint8_t *)data + range->offset - data_offset; + dst.addr = (void *)(uintptr_t)range->offset; + wined3d_context_copy_bo_address(context, &dst, &src, range->size); } - wined3d_context_gl_reference_bo(context_gl, bo_gl); - checkGLcall("buffer upload"); }
/* Context activation is done by the caller. */