Stefan Hanke как alreadt заявленный, вы этого не делаете.
Адрес: glDeleteTextures
Факс: glDeleteTextures
? Когда контекст OpenGL, который создал основную текстуру (ы) (точнее, он sharesobject name space) является текущим в вызывающем потоке.
Финализатор (деструктор класса) работает с потоком 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, он распоряжается ресурсом, собирая его для сбора мусора. Это последовательная реализация: вы можете найти шахту here.
Без ответа еще два варианта: 1. Используйте UI 'SynchronizationContext', чтобы запланировать удаление в потоке OpenGL. 2. Создайте вторичный контекст с помощью 'wglShareLists', единственной целью которого является выпуск дескрипторов OpenGL. Я не думаю, что есть решение, не заставляющее вас съеживаться ... –