Как сказал Стефан Ханке как альредт, вы этого не сделаете.
Когда вы сможете позвонить glDeleteTextures
? Когда контекст OpenGL, который создал базовую текстуру (и) (или, точнее, он разделяет пространство имен объектов) является текущим в вызывающем потоке.
Финализатор (деструктор класса) запускает поток GC, но на самом деле я не знаю, указано ли в нем, как выполняется GC (это ответственность .NET JIT); Я думаю, что наиболее очевидная реализация - это отдельный поток. В самом деле, вызывать glDeleteTextures
в финализаторе не рекомендуется, поскольку вы не знаете, является ли контекст OpenGL текущим в этом потоке.
Реализация IDisposable
может быть идеей, но проблема остается, поскольку реализация Dispose должна знать, действительно ли контекст OpenGL актуален. Для этой цели вы можете использовать процедуры, зависящие от платформы, например wglGetCurrentContext.
Я столкнулся с той же проблемой и пришел к следующему решению.
Абстракция контекста (RenderContext), которая сопоставляет контекст OpenGL с потоком. Вот реализация MakeCurrent:
public void MakeCurrent(IDeviceContext deviceContext, bool flag)
{
if (deviceContext == null)
throw new ArgumentNullException("deviceContext");
if (mDeviceContext == null)
throw new ObjectDisposedException("no context associated with this RenderContext");
int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
if (flag) {
// Make this context current on device
if (Gl.MakeContextCurrent(deviceContext, mRenderContext) == false)
throw new InvalidOperationException("context cannot be current because error " + Marshal.GetLastWin32Error());
// Cache current device context
mCurrentDeviceContext = deviceContext;
// Set current context on this thread (only on success)
lock (sRenderThreadsLock) {
sRenderThreads[threadId] = this;
}
} else {
// Make this context uncurrent on device
bool res = Gl.MakeContextCurrent(deviceContext, mRenderContext);
// Reset current context on this thread (even on error)
lock (sRenderThreadsLock) {
sRenderThreads[threadId] = null;
}
if (res == false)
throw new InvalidOperationException("context cannot be uncurrent because error " + Marshal.GetLastWin32Error());
}
}
public static RenderContext GetCurrentContext()
{
int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
lock (sRenderThreadsLock) {
RenderContext currentThreadContext;
if (sRenderThreads.TryGetValue(threadId, out currentThreadContext) == false)
return (null);
return (currentThreadContext);
}
}
private static readonly object sRenderThreadsLock = new object();
private static readonly Dictionary<int, RenderContext> sRenderThreads = new Dictionary<int,RenderContext>();
Если (и только если) контекстная валюта выполняется с использованием метода MakeCurrent, класс RenderContext может знать, является ли она текущей для вызывающего потока. В заключение, реализация Dispose может использовать класс RenderContext для реального удаления объектов OpenGL.
Но что, если вызывающий поток не имеет текущего контекста OpenGL? Я решил эту проблему, представив GraphicGarbageCollector, который собирает список ресурсов (имена текстур, ...), которые освобождаются в соответствующем потоке (при текущем правильном контексте OpenGL).
По сути, каждый ресурс имеет пространство имен объектов (список совместного использования контекста OpenGL; я определил с помощью GUID). Используя пространство имен объектов, экземпляр ресурса может получить соответствующий GraphicGarbageCollector, поставить в очередь имя ресурса (например, идентификатор текстуры); когда более уместно, GraphicGarbageCollector освобождает поставленные в очередь ресурсы, используя базовый контекст.
Тот же механизм можно использовать с системой ссылок: когда счетчик ссылок достигает 0, она удаляет ресурс, собирая его для сборки мусора. Это последовательная реализация: вы можете найти мою здесь.
person
Luca
schedule
02.05.2012
SynchronizationContext
, чтобы запланировать удаление в потоке OpenGL. 2. Создайте вторичный контекст сwglShareLists
, единственная цель которого - освободить дескрипторы OpenGL. Не думаю, что есть решение, которое не заставит вас съежиться ... - person Stefan Hanke   schedule 29.04.2012