mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-11 23:10:28 +01:00
st/nine: Add RAM memory manager for textures
On 32 bits, virtual memory is sometimes too short for apps. Textures can hold virtual memory 3 ways: 1) MANAGED textures have a RAM copy of any texture 2) SYSTEMMEM is used to have RAM copy of DEFAULT textures (to upload them for example) 3) Textures being mapped. Nine cannot do much for 3). It's up to driver to really unmap textures when possible on 32 bits to reduce virtual memory usage. It's not clear whether on Windows anything special is done for 1) and 2). However there is clear indication some efforts have been done on 3) to really unmap when it makes sense. My understanding is that other implementations reduce the usage of 1) by deleting the RAM copy once the texture is uploaded (Dxvk's behaviour is controlled by evictManagedOnUnlock). The obvious issue with that approach is whether the texture is read by the application after some time. In that case, we have to recreate the RAM backing from the GPU buffer. And apps DO that. Indeed I found that for example Mass Effect 2 with High Texture mods (one of the crash case fixed by this patch serie), When the character gets close to an object, a high res texture and replaces the low res one. The high res one simply has more levels, and the game seems to optimize reading the high res texture by retrieving the small-resolution levels from the original low res texture. In other words during gameplay, the game will randomly read MANAGED textures. This is expected to be fast as the data is supposed to be in RAM... Instead of taking that RAM copy eviction approach, this patchset proposes a different approach: storing in memfd and release the virtual memory until needed. Basically instead of using malloc(), we create a memfd file and map it. When the data doesn't seem to be accessed anymore, we can unmap the memfd file. If the data is needed, the memfd file is mapped again. This trick enables to allocate more than 4GB on 32 bits apps. The advantage of this approach over the RAM eviction one, is that the load is much faster and doesn't block the GPU. Of course we have problems if there's not enough memory to map the memfd file. But the problem is the same for the RAM eviction approach. Naturally on 64 bits, we do not use memfd. Signed-off-by: Axel Davy <davyaxel0@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9377>
This commit is contained in:
parent
6087ff44ae
commit
90a7573a65
3 changed files with 1253 additions and 0 deletions
|
|
@ -38,6 +38,7 @@ nine_st_files = files(
|
|||
'nine_ff.c',
|
||||
'nine_helpers.c',
|
||||
'nine_lock.c',
|
||||
'nine_memory_helper.c',
|
||||
'nine_pipe.c',
|
||||
'nine_quirk.c',
|
||||
'nine_queue.c',
|
||||
|
|
|
|||
1181
src/gallium/frontends/nine/nine_memory_helper.c
Normal file
1181
src/gallium/frontends/nine/nine_memory_helper.c
Normal file
File diff suppressed because it is too large
Load diff
71
src/gallium/frontends/nine/nine_memory_helper.h
Normal file
71
src/gallium/frontends/nine/nine_memory_helper.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2020 Axel Davy <davyaxel0@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef _NINE_MEMORY_HELPER_H_
|
||||
#define _NINE_MEMORY_HELPER_H_
|
||||
|
||||
|
||||
struct NineDevice9;
|
||||
|
||||
struct nine_allocator;
|
||||
struct nine_allocation;
|
||||
|
||||
/* Note: None of these functions are thread safe, thus the worker thread is disallowed
|
||||
* to call any of them. Only exception is nine_free_worker reserved for it. */
|
||||
|
||||
struct nine_allocation *
|
||||
nine_allocate(struct nine_allocator *allocator, unsigned size);
|
||||
|
||||
/* Note: Suballocations MUST be freed before their parent */
|
||||
void nine_free(struct nine_allocator *allocator, struct nine_allocation *allocation);
|
||||
void nine_free_worker(struct nine_allocator *allocator, struct nine_allocation *allocation);
|
||||
|
||||
void *nine_get_pointer(struct nine_allocator *allocator, struct nine_allocation *allocation);
|
||||
|
||||
/* We don't need the pointer anymore, but we are likely to need it again soon */
|
||||
void nine_pointer_weakrelease(struct nine_allocator *allocator, struct nine_allocation *allocation);
|
||||
|
||||
/* We don't need the pointer anymore, probably for a long time */
|
||||
void nine_pointer_strongrelease(struct nine_allocator *allocator, struct nine_allocation *allocation);
|
||||
|
||||
/* You can strong release when counter becomes 0.
|
||||
* Once a counter is used for a given allocation, the same must keep being used */
|
||||
void nine_pointer_delayedstrongrelease(struct nine_allocator *allocator,
|
||||
struct nine_allocation *allocation,
|
||||
unsigned *counter);
|
||||
|
||||
/* Note: It is disallowed to release a suballocation before its parent.
|
||||
* It is disallowed to suballocate on a suballocation. */
|
||||
struct nine_allocation *
|
||||
nine_suballocate(struct nine_allocator* allocator, struct nine_allocation *allocation, int offset);
|
||||
|
||||
/* Won't be freed - but at least we can use the same interface */
|
||||
struct nine_allocation *
|
||||
nine_wrap_external_pointer(struct nine_allocator* allocator, void* data);
|
||||
|
||||
struct nine_allocator *
|
||||
nine_allocator_create(struct NineDevice9 *device);
|
||||
|
||||
void
|
||||
nine_allocator_destroy(struct nine_allocator *allocator);
|
||||
|
||||
#endif /* _NINE_MEMORY_HELPER_H_ */
|
||||
Loading…
Add table
Reference in a new issue