Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/buffer.c | 3 +- dlls/wined3d/context_gl.c | 116 +-------------------------------- dlls/wined3d/device.c | 116 ++++++++++++++++++++++++++++++++- dlls/wined3d/texture.c | 5 +- dlls/wined3d/view.c | 5 +- dlls/wined3d/wined3d_private.h | 6 +- 6 files changed, 127 insertions(+), 124 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index cab93ccc4e3..7c3537e466e 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -201,6 +201,7 @@ static void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *bu static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buffer_gl, struct wined3d_context_gl *context_gl) { + struct wined3d_device_gl *device_gl = wined3d_device_gl(buffer_gl->b.resource.device); const struct wined3d_gl_info *gl_info = context_gl->gl_info; GLenum usage = GL_STATIC_DRAW; GLbitfield gl_storage_flags; @@ -223,7 +224,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf coherent = false; } gl_storage_flags = wined3d_resource_gl_storage_flags(&buffer_gl->b.resource); - if (!wined3d_context_gl_create_bo(context_gl, size, binding, usage, coherent, gl_storage_flags, bo)) + if (!wined3d_device_gl_create_bo(device_gl, context_gl, size, binding, usage, coherent, gl_storage_flags, bo)) { ERR("Failed to create OpenGL buffer object.\n"); buffer_gl->b.flags &= ~WINED3D_BUFFER_USE_BO; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 77e0379ee61..8901bafcce3 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2766,30 +2766,6 @@ GLuint wined3d_context_gl_allocate_vram_chunk_buffer(struct wined3d_context_gl * 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) { @@ -2852,7 +2828,7 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, struct wined3d_context_
if ((flags & WINED3D_MAP_DISCARD) && bo->command_fence_id > device_gl->completed_fence_id) { - if (wined3d_context_gl_create_bo(context_gl, bo->size, + if (wined3d_device_gl_create_bo(device_gl, context_gl, bo->size, bo->binding, bo->usage, bo->b.coherent, bo->flags, &tmp)) { list_move_head(&tmp.b.users, &bo->b.users); @@ -3157,96 +3133,6 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct bo->id = 0; }
-static bool use_buffer_chunk_suballocation(const struct wined3d_gl_info *gl_info, GLenum binding) -{ - switch (binding) - { - case GL_ARRAY_BUFFER: - case GL_ATOMIC_COUNTER_BUFFER: - case GL_DRAW_INDIRECT_BUFFER: - case GL_PIXEL_UNPACK_BUFFER: - case GL_UNIFORM_BUFFER: - return true; - - case GL_TEXTURE_BUFFER: - return gl_info->supported[ARB_TEXTURE_BUFFER_RANGE]; - - default: - return false; - } -} - -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]) - { - if (use_buffer_chunk_suballocation(gl_info, binding)) - { - if ((memory = wined3d_context_gl_allocate_memory(context_gl, memory_type_idx, size, &id))) - buffer_offset = memory->offset; - } - else - { - 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); - } - - if (!id) - { - WARN("Failed to allocate buffer.\n"); - return false; - } - } - else - { - GL_EXTCALL(glGenBuffers(1, &id)); - if (!id) - { - checkGLcall("buffer object creation"); - return false; - } - wined3d_context_gl_bind_bo(context_gl, binding, id); - - if (!coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) - { - GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); - GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); - } - - GL_EXTCALL(glBufferData(binding, size, NULL, usage)); - - wined3d_context_gl_bind_bo(context_gl, binding, 0); - checkGLcall("buffer object creation"); - } - - TRACE("Created buffer object %u.\n", id); - bo->id = id; - bo->memory = memory; - bo->size = size; - bo->binding = binding; - bo->usage = usage; - bo->flags = flags; - bo->b.coherent = coherent; - list_init(&bo->b.users); - bo->command_fence_id = 0; - bo->b.buffer_offset = buffer_offset; - bo->b.memory_offset = bo->b.buffer_offset; - bo->b.map_ptr = NULL; - bo->b.client_map_count = 0; - - return true; -} - static void wined3d_context_gl_set_render_offscreen(struct wined3d_context_gl *context_gl, BOOL offscreen) { if (context_gl->c.render_offscreen == offscreen) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 4dac9220f0f..84d2e3a0ce8 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -29,6 +29,7 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); WINE_DECLARE_DEBUG_CHANNEL(winediag);
struct wined3d_matrix_3x3 @@ -1033,7 +1034,7 @@ gl_memory_types[] = {GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT}, };
-unsigned int wined3d_device_gl_find_memory_type(GLbitfield flags) +static unsigned int wined3d_device_gl_find_memory_type(GLbitfield flags) { unsigned int i;
@@ -1052,6 +1053,119 @@ GLbitfield wined3d_device_gl_get_memory_type_flags(unsigned int memory_type_idx) return gl_memory_types[memory_type_idx].flags; }
+static struct wined3d_allocator_block *wined3d_device_gl_allocate_memory(struct wined3d_device_gl *device_gl, + struct wined3d_context_gl *context_gl, unsigned int memory_type, GLsizeiptr size, GLuint *id) +{ + 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 bool use_buffer_chunk_suballocation(const struct wined3d_gl_info *gl_info, GLenum binding) +{ + switch (binding) + { + case GL_ARRAY_BUFFER: + case GL_ATOMIC_COUNTER_BUFFER: + case GL_DRAW_INDIRECT_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_UNIFORM_BUFFER: + return true; + + case GL_TEXTURE_BUFFER: + return gl_info->supported[ARB_TEXTURE_BUFFER_RANGE]; + + default: + return false; + } +} + +bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, 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 = &device_gl->d.adapter->gl_info; + struct wined3d_allocator_block *memory = NULL; + GLsizeiptr buffer_offset = 0; + GLuint id = 0; + + TRACE("device_gl %p, context_gl %p, size %lu, binding %#x, usage %#x, coherent %#x, flags %#x, bo %p.\n", + device_gl, context_gl, size, binding, usage, coherent, flags, bo); + + if (gl_info->supported[ARB_BUFFER_STORAGE]) + { + if (use_buffer_chunk_suballocation(gl_info, binding)) + { + if ((memory = wined3d_device_gl_allocate_memory(device_gl, context_gl, memory_type_idx, size, &id))) + buffer_offset = memory->offset; + } + else + { + 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); + } + + if (!id) + { + WARN("Failed to allocate buffer.\n"); + return false; + } + } + else + { + GL_EXTCALL(glGenBuffers(1, &id)); + if (!id) + { + checkGLcall("buffer object creation"); + return false; + } + wined3d_context_gl_bind_bo(context_gl, binding, id); + + if (!coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) + { + GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); + GL_EXTCALL(glBufferParameteriAPPLE(binding, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); + } + + GL_EXTCALL(glBufferData(binding, size, NULL, usage)); + + wined3d_context_gl_bind_bo(context_gl, binding, 0); + checkGLcall("buffer object creation"); + } + + TRACE("Created buffer object %u.\n", id); + bo->id = id; + bo->memory = memory; + bo->size = size; + bo->binding = binding; + bo->usage = usage; + bo->flags = flags; + bo->b.coherent = coherent; + list_init(&bo->b.users); + bo->command_fence_id = 0; + bo->b.buffer_offset = buffer_offset; + bo->b.memory_offset = bo->b.buffer_offset; + bo->b.map_ptr = NULL; + bo->b.client_map_count = 0; + + return true; +} + void wined3d_device_gl_delete_opengl_contexts_cs(void *object) { struct wined3d_device_gl *device_gl = object; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 18925338285..b1fd1e7bde2 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2019,8 +2019,9 @@ static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl * if (bo->id) return;
- if (!wined3d_context_gl_create_bo(context_gl, sub_resource->size, GL_PIXEL_UNPACK_BUFFER, - GL_STREAM_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo)) + if (!wined3d_device_gl_create_bo(wined3d_device_gl(texture_gl->t.resource.device), + context_gl, sub_resource->size, GL_PIXEL_UNPACK_BUFFER, GL_STREAM_DRAW, true, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo)) return;
TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo->id, texture_gl, sub_resource_idx); diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 4483a21a6d0..a345626cf5e 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -1671,10 +1671,11 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object)
if (resource->type == WINED3D_RTYPE_BUFFER) { + struct wined3d_device_gl *device_gl = wined3d_device_gl(resource->device); struct wined3d_buffer *buffer = buffer_from_resource(resource); struct wined3d_context_gl *context_gl;
- context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0)); + context_gl = wined3d_context_gl(context_acquire(&device_gl->d, NULL, 0)); create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format); view_gl->bo_user.valid = true; list_add_head(&buffer->buffer_object->users, &view_gl->bo_user.entry); @@ -1683,7 +1684,7 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object) struct wined3d_bo_gl *bo = &view_gl->counter_bo;
view_gl->v.counter_bo = &bo->b; - wined3d_context_gl_create_bo(context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER, + wined3d_device_gl_create_bo(device_gl, context_gl, sizeof(uint32_t), GL_ATOMIC_COUNTER_BUFFER, GL_STATIC_DRAW, true, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT, bo); wined3d_unordered_access_view_set_counter(&view_gl->v, 0); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index cfd1d98d6ad..48b760edc1b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2382,8 +2382,6 @@ void wined3d_context_gl_check_fbo_status(const struct wined3d_context_gl *contex void wined3d_context_gl_copy_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, unsigned int range_count, const struct wined3d_range *ranges) DECLSPEC_HIDDEN; -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) DECLSPEC_HIDDEN; void wined3d_context_gl_destroy(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN; void wined3d_context_gl_draw_shaded_quad(struct wined3d_context_gl *context_gl, struct wined3d_texture_gl *texture_gl, @@ -4214,9 +4212,11 @@ static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device return CONTAINING_RECORD(device, struct wined3d_device_gl, d); }
+bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, + struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding, + GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN; 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)
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 4 ++++ dlls/wined3d/context_gl.c | 12 ++++++++++-- dlls/wined3d/device.c | 5 +++++ dlls/wined3d/wined3d_private.h | 11 +++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 2e31d140dd5..bc54f46222f 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4274,6 +4274,8 @@ static HRESULT adapter_gl_create_device(struct wined3d *wined3d, const struct wi return hr; }
+ wined3d_lock_init(&device_gl->allocator_cs, "wined3d_device_gl.allocator_cs"); + *device = &device_gl->d; return WINED3D_OK; } @@ -4283,6 +4285,8 @@ 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); + wined3d_lock_cleanup(&device_gl->allocator_cs); + 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 8901bafcce3..8217d04686c 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2629,6 +2629,14 @@ static void wined3d_context_gl_poll_fences(struct wined3d_context_gl *context_gl } }
+static void wined3d_device_gl_free_memory(struct wined3d_device_gl *device_gl, struct wined3d_allocator_block *block) +{ + assert(block->chunk->allocator == &device_gl->allocator); + wined3d_device_gl_allocator_lock(device_gl); + wined3d_allocator_block_free(block); + wined3d_device_gl_allocator_unlock(device_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); @@ -2651,7 +2659,7 @@ static void wined3d_context_gl_cleanup_resources(struct wined3d_context_gl *cont continue; }
- wined3d_allocator_block_free(r->block); + wined3d_device_gl_free_memory(device_gl, r->block); if (i != --count) *r = blocks[count]; else @@ -2718,7 +2726,7 @@ static void wined3d_context_gl_destroy_allocator_block(struct wined3d_context_gl
if (device_gl->completed_fence_id > fence_id) { - wined3d_allocator_block_free(block); + wined3d_device_gl_free_memory(device_gl, block); TRACE("Freed block %p.\n", block); return; } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 84d2e3a0ce8..e302e1917a6 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1059,20 +1059,25 @@ static struct wined3d_allocator_block *wined3d_device_gl_allocate_memory(struct struct wined3d_allocator *allocator = &device_gl->allocator; struct wined3d_allocator_block *block;
+ wined3d_device_gl_allocator_lock(device_gl); + if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2) { *id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type, size); + wined3d_device_gl_allocator_unlock(device_gl); return NULL; }
if (!(block = wined3d_allocator_allocate(allocator, &context_gl->c, memory_type, size))) { + wined3d_device_gl_allocator_unlock(device_gl); *id = 0; return NULL; }
*id = wined3d_allocator_chunk_gl(block->chunk)->gl_buffer;
+ wined3d_device_gl_allocator_unlock(device_gl); return block; }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 48b760edc1b..96ce75fbb58 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4194,6 +4194,7 @@ struct wined3d_device_gl /* Textures for when no other textures are bound. */ struct wined3d_dummy_textures dummy_textures;
+ CRITICAL_SECTION allocator_cs; struct wined3d_allocator allocator; uint64_t completed_fence_id; uint64_t current_fence_id; @@ -4212,6 +4213,16 @@ static inline struct wined3d_device_gl *wined3d_device_gl(struct wined3d_device return CONTAINING_RECORD(device, struct wined3d_device_gl, d); }
+static inline void wined3d_device_gl_allocator_lock(struct wined3d_device_gl *device_gl) +{ + EnterCriticalSection(&device_gl->allocator_cs); +} + +static inline void wined3d_device_gl_allocator_unlock(struct wined3d_device_gl *device_gl) +{ + LeaveCriticalSection(&device_gl->allocator_cs); +} + bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, struct wined3d_context_gl *context_gl, GLsizeiptr size, GLenum binding, GLenum usage, bool coherent, GLbitfield flags, struct wined3d_bo_gl *bo) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/device.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index e302e1917a6..9488e8c642e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -961,11 +961,15 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi 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; + struct wined3d_context_gl *context_gl;
TRACE("allocator %p, context %p, memory_type %u, chunk_size %zu.\n", allocator, context, memory_type, chunk_size);
+ if (!context) + return NULL; + context_gl = wined3d_context_gl(context); + if (!(chunk_gl = heap_alloc(sizeof(*chunk_gl)))) return NULL;
@@ -1063,12 +1067,13 @@ static struct wined3d_allocator_block *wined3d_device_gl_allocate_memory(struct
if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2) { - *id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type, size); + if (context_gl) + *id = wined3d_context_gl_allocate_vram_chunk_buffer(context_gl, memory_type, size); wined3d_device_gl_allocator_unlock(device_gl); return NULL; }
- if (!(block = wined3d_allocator_allocate(allocator, &context_gl->c, memory_type, size))) + if (!(block = wined3d_allocator_allocate(allocator, context_gl ? &context_gl->c : NULL, memory_type, size))) { wined3d_device_gl_allocator_unlock(device_gl); *id = 0; @@ -1119,7 +1124,7 @@ bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, struct win if ((memory = wined3d_device_gl_allocate_memory(device_gl, context_gl, memory_type_idx, size, &id))) buffer_offset = memory->offset; } - else + else if (context_gl) { 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); @@ -1133,6 +1138,9 @@ bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, struct win } else { + if (!context_gl) + return false; + GL_EXTCALL(glGenBuffers(1, &id)); if (!id) {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/cs.c | 9 +++++++++ dlls/wined3d/shader_spirv.c | 2 ++ 2 files changed, 11 insertions(+)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index dede21d19b6..56abc146733 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3079,12 +3079,21 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str * a texture can be invalidated to even count. */ if (resource->type == WINED3D_RTYPE_BUFFER && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) { + const struct wined3d_d3d_info *d3d_info = &context->device->adapter->d3d_info; struct wined3d_client_resource *client = &resource->client; struct wined3d_device *device = context->device; struct wined3d_bo_address addr; struct wined3d_bo *bo; uint8_t *map_ptr;
+ /* We can't use persistent maps if we might need to do vertex attribute + * conversion; that will cause the CS thread to invalidate the BO. */ + if (!d3d_info->xyzrhw || !d3d_info->vertex_bgra || !d3d_info->ffp_generic_attributes) + { + TRACE("Not returning a persistent buffer because we might need to do vertex attribute conversion.\n"); + return NULL; + } + if (flags & WINED3D_MAP_DISCARD) { if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr)) diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index 1e6a03040b9..9ad11f34ebd 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -1176,6 +1176,8 @@ static void spirv_vertex_pipe_vk_vp_enable(const struct wined3d_context *context static void spirv_vertex_pipe_vk_vp_get_caps(const struct wined3d_adapter *adapter, struct wined3d_vertex_caps *caps) { memset(caps, 0, sizeof(*caps)); + caps->xyzrhw = TRUE; + caps->ffp_generic_attributes = TRUE; }
static uint32_t spirv_vertex_pipe_vk_vp_get_emul_mask(const struct wined3d_gl_info *gl_info)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 43 ++++++++++++++++++++++++++++++++++ dlls/wined3d/buffer.c | 2 +- dlls/wined3d/cs.c | 36 ++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 4 ++++ 4 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index bc54f46222f..cb0c34823aa 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4616,6 +4616,49 @@ static void adapter_gl_flush_bo_address(struct wined3d_context *context, static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_bo_address *addr) { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_device_gl *device_gl = wined3d_device_gl(device); + + wined3d_not_from_cs(device->cs); + assert(device->context_count); + + if (resource->type == WINED3D_RTYPE_BUFFER) + { + GLenum usage = GL_STATIC_DRAW; + struct wined3d_bo_gl *bo_gl; + bool coherent = true; + + if (resource->usage & WINED3DUSAGE_DYNAMIC) + { + usage = GL_STREAM_DRAW_ARB; + coherent = false; + } + + if (!(bo_gl = heap_alloc(sizeof(*bo_gl)))) + return false; + + if (!(wined3d_device_gl_create_bo(device_gl, NULL, resource->size, + wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags), + usage, coherent, wined3d_resource_gl_storage_flags(resource), bo_gl))) + { + WARN("Failed to create OpenGL buffer.\n"); + heap_free(bo_gl); + return false; + } + + addr->buffer_object = &bo_gl->b; + addr->addr = NULL; + + if (!bo_gl->b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n", + bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL); + wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD); + } + + return true; + } + return false; }
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 7c3537e466e..434e21402db 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -137,7 +137,7 @@ void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD loc wined3d_buffer_invalidate_range(buffer, location, 0, 0); }
-static GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, uint32_t bind_flags) +GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, uint32_t bind_flags) { if (!bind_flags) return GL_PIXEL_UNPACK_BUFFER; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 56abc146733..0986165a59d 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -120,6 +120,7 @@ enum wined3d_cs_op WINED3D_CS_OP_UNLOAD_RESOURCE, WINED3D_CS_OP_MAP, WINED3D_CS_OP_UNMAP, + WINED3D_CS_OP_MAP_BO_ADDRESS, WINED3D_CS_OP_BLT_SUB_RESOURCE, WINED3D_CS_OP_UPDATE_SUB_RESOURCE, WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION, @@ -454,6 +455,14 @@ struct wined3d_cs_unmap HRESULT *hr; };
+struct wined3d_cs_map_bo_address +{ + enum wined3d_cs_op opcode; + struct wined3d_bo_address addr; + size_t size; + uint32_t flags; +}; + struct wined3d_cs_blt_sub_resource { enum wined3d_cs_op opcode; @@ -594,6 +603,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op) WINED3D_TO_STR(WINED3D_CS_OP_UNLOAD_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_MAP); WINED3D_TO_STR(WINED3D_CS_OP_UNMAP); + WINED3D_TO_STR(WINED3D_CS_OP_MAP_BO_ADDRESS); WINED3D_TO_STR(WINED3D_CS_OP_BLT_SUB_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_UPDATE_SUB_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION); @@ -2550,6 +2560,31 @@ HRESULT wined3d_device_context_emit_unmap(struct wined3d_device_context *context return hr; }
+static void wined3d_cs_exec_map_bo_address(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_map_bo_address *op = data; + struct wined3d_context *context; + + context = context_acquire(cs->c.device, NULL, 0); + wined3d_context_map_bo_address(context, &op->addr, op->size, op->flags); + context_release(context); +} + +void wined3d_cs_map_bo_address(struct wined3d_cs *cs, + struct wined3d_bo_address *addr, size_t size, unsigned int flags) +{ + struct wined3d_device_context *context = &cs->c; + struct wined3d_cs_map_bo_address *op; + + op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_MAP); + op->opcode = WINED3D_CS_OP_MAP_BO_ADDRESS; + op->addr = *addr; + op->size = size; + op->flags = flags; + wined3d_device_context_submit(context, WINED3D_CS_QUEUE_MAP); + wined3d_device_context_finish(context, WINED3D_CS_QUEUE_MAP); +} + static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_blt_sub_resource *op = data; @@ -2968,6 +3003,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* 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_MAP_BO_ADDRESS */ wined3d_cs_exec_map_bo_address, /* 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, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 96ce75fbb58..b8e2a96001a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -5018,6 +5018,8 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; +void wined3d_cs_map_bo_address(struct wined3d_cs *cs, + struct wined3d_bo_address *addr, size_t size, unsigned int flags) DECLSPEC_HIDDEN;
static inline void wined3d_cs_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id) { @@ -5201,6 +5203,8 @@ static inline const struct wined3d_buffer_gl *wined3d_buffer_gl_const(const stru return CONTAINING_RECORD(buffer, struct wined3d_buffer_gl, b); }
+GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, + uint32_t bind_flags) DECLSPEC_HIDDEN; HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device, const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
On Wed, 16 Feb 2022 at 04:43, Zebediah Figura zfigura@codeweavers.com wrote:
dlls/wined3d/adapter_gl.c | 43 ++++++++++++++++++++++++++++++++++ dlls/wined3d/buffer.c | 2 +- dlls/wined3d/cs.c | 36 ++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 4 ++++ 4 files changed, 84 insertions(+), 1 deletion(-)
Unfortunately this introduces test failures for me in ddraw's test_vb_discard():
ddraw7.c:4285: Test failed: Vertex buffer data byte 0 is 0x00, expected 0xaa
That's with csmt disabled, although that may not be consequential; it's simply the first configuration I ran the tests with.