/// <summary> /// Sets the texture's data from managed memory. /// </summary> private unsafe void SetDataInternal <T>(Int32 level, Rectangle?rect, T[] data, Int32 startIndex, Int32 elementCount) where T : struct { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var region = rect ?? new Rectangle(0, 0, width, height); var regionWidth = region.Width; var regionHeight = region.Height; var pixelSizeInBytes = (format == gl.GL_RGB || format == gl.GL_BGR) ? 3 : 4; if (pixelSizeInBytes * width * height != elementSizeInBytes * elementCount) { throw new ArgumentException(UltravioletStrings.BufferIsWrongSize); } Ultraviolet.QueueWorkItem(state => { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { using (OpenGLState.ScopedBindTexture2D(OpenGLName)) { var pData = dataHandle.AddrOfPinnedObject() + (startIndex * elementSizeInBytes); gl.TextureSubImage2D(OpenGLName, gl.GL_TEXTURE_2D, level, region.X, region.Y, region.Width, region.Height, format, type, (void *)pData); gl.ThrowIfError(); } } finally { dataHandle.Free(); } }, null, WorkItemOptions.ReturnNullOnSynchronousExecution)?.Wait(); }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { var glname = framebuffer; if (glname != 0 && !Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteFramebuffer(glname); gl.ThrowIfError(); }, null, WorkItemOptions.ReturnNullOnSynchronousExecution); } buffers.Clear(); framebuffer = 0; } base.Dispose(disposing); }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { var glname = vao; if (glname != 0) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteVertexArray(glname); gl.ThrowIfError(); OpenGLState.DeleteVertexArrayObject(glname, glElementArrayBufferBinding ?? 0); }, null, WorkItemOptions.ReturnNullOnSynchronousExecution); } vao = 0; } vbuffers.Clear(); ibuffer = null; } base.Dispose(disposing); }
/// <summary> /// Sets the texture's data from native memory. /// </summary> private unsafe void SetRawDataInternal(Int32 level, Rectangle?rect, IntPtr data, Int32 offsetInBytes, Int32 sizeInBytes) { var region = rect ?? new Rectangle(0, 0, width, height); var regionWidth = region.Width; var regionHeight = region.Height; var pixelSizeInBytes = (format == gl.GL_RGB || format == gl.GL_BGR) ? 3 : 4; if (pixelSizeInBytes * width * height != sizeInBytes) { throw new ArgumentException(UltravioletStrings.BufferIsWrongSize); } if (Ultraviolet.IsExecutingOnCurrentThread) { Upload(level, region, data, offsetInBytes); } else { Ultraviolet.QueueWorkItem(state => { Upload(level, region, data, offsetInBytes); }, null, WorkItemOptions.ReturnNullOnSynchronousExecution)?.Wait(); } }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { if (vao != 0) { Ultraviolet.QueueWorkItem((state) => { var vaoName = ((OpenGLGeometryStream)state).vao; gl.DeleteVertexArray(vaoName); gl.ThrowIfError(); OpenGLState.DeleteVertexArrayObject(vaoName, 0, glElementArrayBufferBinding ?? 0); }, this); } } vbuffers.Clear(); ibuffer = null; } base.Dispose(disposing); }
/// <inheritdoc/> public override void Resize(Int32 width, Int32 height, Int32 depth) { Contract.EnsureNotDisposed(this, Disposed); Contract.EnsureRange(width >= 1, nameof(width)); Contract.EnsureRange(height >= 1, nameof(height)); if (BoundForReading || BoundForWriting) { throw new InvalidOperationException(OpenGLStrings.InvalidOperationWhileBound); } this.width = width; this.height = height; this.depth = depth; if (immutable) { throw new InvalidOperationException(rbuffer ? OpenGLStrings.RenderBufferIsImmutable : OpenGLStrings.TextureIsImmutable); } if (Ultraviolet.IsExecutingOnCurrentThread) { ProcessResize(); } else { Ultraviolet.QueueWorkItem((state) => { ((OpenGLTexture3D)state).ProcessResize(); }, this); } }
/// <inheritdoc/> public override void Attach(RenderBuffer2D buffer) { Contract.Require(buffer, nameof(buffer)); Contract.Ensure <ArgumentException>( buffer.Width == width && buffer.Height == height, OpenGLStrings.RenderBufferIsWrongSize); Contract.EnsureNotDisposed(this, Disposed); Ultraviolet.ValidateResource(buffer); var oglBuffer = (OpenGLRenderBuffer2D)buffer; Ultraviolet.QueueWorkItem(state => { using (OpenGLState.ScopedBindFramebuffer(framebuffer)) { AttachRenderBuffer(oglBuffer); framebufferStatus = gl.CheckNamedFramebufferStatus(framebuffer, gl.GL_FRAMEBUFFER); gl.ThrowIfError(); } }).Wait(); oglBuffer.MarkAttached(); buffers.Add(oglBuffer); }
/// <summary> /// Releases resources associated with the object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { ((OpenGLUltravioletGraphics)Ultraviolet.GetGraphics()).UnbindTexture(this); } if (willNotBeSampled) { if (!Ultraviolet.Disposed && renderbuffer != 0) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteRenderBuffers(((OpenGLRenderBuffer2D)state).renderbuffer); gl.ThrowIfError(); }, this); } } else { SafeDispose.Dispose(texture); } } base.Dispose(disposing); }
/// <summary> /// Sets the texture's data. /// </summary> private void SetDataInternal <T>(Int32 level, Int32 left, Int32 top, Int32 right, Int32 bottom, Int32 front, Int32 back, T[] data, Int32 startIndex, Int32 elementCount) where T : struct { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var width = right - left; var height = bottom - top; var depth = back - front; var pixelSizeInBytes = (format == gl.GL_RGB || format == gl.GL_BGR) ? 3 : 4; if (pixelSizeInBytes * width * height * depth != elementSizeInBytes * elementCount) { throw new ArgumentException(UltravioletStrings.BufferIsWrongSize); } Ultraviolet.QueueWorkItem(state => { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { using (OpenGLState.ScopedBindTexture3D(OpenGLName)) { var pData = dataHandle.AddrOfPinnedObject() + (startIndex * elementSizeInBytes); gl.TextureSubImage3D(OpenGLName, gl.GL_TEXTURE_3D, level, left, top, front, right - left, bottom - top, back - front, format, type, (void *)pData); gl.ThrowIfError(); } } finally { dataHandle.Free(); } }).Wait(); }
/// <summary> /// Sets the texture's data from native memory. /// </summary> private void SetRawDataInternal(Int32 level, Int32 left, Int32 top, Int32 right, Int32 bottom, Int32 front, Int32 back, IntPtr data, Int32 offsetInBytes, Int32 sizeInBytes) { var width = right - left; var height = bottom - top; var depth = back - front; var pixelSizeInBytes = (format == gl.GL_RGB || format == gl.GL_BGR) ? 3 : 4; if (pixelSizeInBytes * width * height * depth != sizeInBytes) { throw new ArgumentException(UltravioletStrings.BufferIsWrongSize); } if (Ultraviolet.IsExecutingOnCurrentThread) { Upload(level, left, top, right, bottom, front, back, data, offsetInBytes, sizeInBytes); } else { Ultraviolet.QueueWorkItem(state => { Upload(level, left, top, right, bottom, front, back, data, offsetInBytes, sizeInBytes); }, null, WorkItemOptions.ReturnNullOnSynchronousExecution)?.Wait(); } }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { var glname = texture; if (glname != 0 && !Ultraviolet.Disposed) { ((OpenGLUltravioletGraphics)Ultraviolet.GetGraphics()).UnbindTexture(this); Ultraviolet.QueueWorkItem((state) => { gl.DeleteTexture(glname); gl.ThrowIfError(); }, this, WorkItemOptions.ReturnNullOnSynchronousExecution); } texture = 0; } base.Dispose(disposing); }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (OpenGLState.GL_ARRAY_BUFFER_BINDING == buffer) { OpenGLState.GL_ARRAY_BUFFER_BINDING.Update(0); } var glname = buffer; if (glname != 0 && !Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteBuffer(glname); gl.ThrowIfError(); }, this, WorkItemOptions.ReturnNullOnSynchronousExecution); } buffer = 0; } base.Dispose(disposing); }
/// <summary> /// Releases resources associated with the object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteProgram(((OpenGLShaderProgram)state).program); gl.ThrowIfError(); }, this); } if (programOwnsShaders) { SafeDispose.Dispose(vertexShader); SafeDispose.Dispose(fragmentShader); } } base.Dispose(disposing); }
/// <summary> /// Releases resources associated with this object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { var glname = buffer; Ultraviolet.QueueWorkItem((state) => { gl.DeleteBuffer(glname); gl.ThrowIfError(); }, this, WorkItemOptions.ReturnNullOnSynchronousExecution); } buffer = 0; } base.Dispose(disposing); }
/// <summary> /// Releases resources associated with the object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { var glname = program; if (glname != 0 && !Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteProgram(glname); gl.ThrowIfError(); }, this, WorkItemOptions.ReturnNullOnSynchronousExecution); } if (programOwnsShaders) { SafeDispose.Dispose(vertexShader); SafeDispose.Dispose(fragmentShader); } program = 0; } base.Dispose(disposing); }
/// <summary> /// Sets the buffer's data from native memory. /// </summary> private void SetRawDataInternal(IntPtr data, Int32 offsetInBytes, Int32 countInBytes, SetDataOptions options) { if (Ultraviolet.IsExecutingOnCurrentThread) { Upload(data, offsetInBytes, countInBytes, options); } else { Ultraviolet.QueueWorkItem(state => { Upload(data, offsetInBytes, countInBytes, options); }, null, WorkItemOptions.ForceAsynchronousExecution)?.Wait(); } }
/// <summary> /// Releases resources associated with this object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteShader(((OpenGLVertexShader)state).shader); gl.ThrowIfError(); }, this); } } base.Dispose(disposing); }
/// <summary> /// Uploads texture data to the graphics device. /// </summary> private unsafe Task Upload(Int32 level, Rectangle region, IntPtr ldata, Int32 startIndex, Int32 elementSizeInBytes) { if (Ultraviolet.IsExecutingOnCurrentThread) { using (OpenGLState.ScopedBindTexture2D(OpenGLName)) { var pData = ldata + (startIndex * elementSizeInBytes); gl.TextureSubImage2D(OpenGLName, gl.GL_TEXTURE_2D, level, region.X, region.Y, region.Width, region.Height, format, type, (void *)pData); gl.ThrowIfError(); } return(null); } else { return(Ultraviolet.QueueWorkItem(state => { Upload(level, region, ldata, startIndex, elementSizeInBytes); })); } }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { ((OpenGLUltravioletGraphics)Ultraviolet.GetGraphics()).UnbindTexture(this); Ultraviolet.QueueWorkItem((state) => { gl.DeleteTexture(((OpenGLTexture2D)state).texture); gl.ThrowIfError(); }, this); } } base.Dispose(disposing); }
/// <inheritdoc/> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteFramebuffer(((OpenGLRenderTarget2D)state).framebuffer); gl.ThrowIfError(); }, this); } buffers.Clear(); } base.Dispose(disposing); }
/// <summary> /// Releases resources associated with the object. /// </summary> /// <param name="disposing">true if the object is being disposed; false if the object is being finalized.</param> protected override void Dispose(Boolean disposing) { if (Disposed) { return; } if (disposing) { if (!Ultraviolet.Disposed) { ((OpenGLUltravioletGraphics)Ultraviolet.GetGraphics()).UnbindTexture(this); } if (willNotBeSampled) { var glname = renderbuffer; if (!Ultraviolet.Disposed && glname != 0) { Ultraviolet.QueueWorkItem((state) => { gl.DeleteRenderBuffers(glname); gl.ThrowIfError(); }, null, WorkItemOptions.ReturnNullOnSynchronousExecution); } renderbuffer = 0; } else { SafeDispose.Dispose(texture); } } base.Dispose(disposing); }
/// <summary> /// Sets the buffer's data from native memory. /// </summary> private void SetDataInternal(Object data, Int32 srcOffsetInBytes, Int32 dstOffsetInBytes, Int32 countInBytes, SetDataOptions options) { if (Ultraviolet.IsExecutingOnCurrentThread) { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { Upload(pData.AddrOfPinnedObject() + srcOffsetInBytes, dstOffsetInBytes, countInBytes, options); } finally { pData.Free(); } } else { Ultraviolet.QueueWorkItem(state => { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { Upload(pData.AddrOfPinnedObject() + srcOffsetInBytes, dstOffsetInBytes, countInBytes, options); } finally { pData.Free(); } }, null, WorkItemOptions.ForceAsynchronousExecution)?.Wait(); } }
/// <summary> /// Sets the texture's data from managed memory. /// </summary> private void SetDataInternal(Int32 level, Int32 left, Int32 top, Int32 right, Int32 bottom, Int32 front, Int32 back, Object data, Int32 offsetInBytes, Int32 sizeInBytes) { if (Ultraviolet.IsExecutingOnCurrentThread) { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { SetRawDataInternal(level, left, top, right, bottom, front, back, pData.AddrOfPinnedObject(), offsetInBytes, sizeInBytes); } finally { pData.Free(); } } else { Ultraviolet.QueueWorkItem(state => { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { SetRawDataInternal(level, left, top, right, bottom, front, back, pData.AddrOfPinnedObject(), 0, sizeInBytes); } finally { pData.Free(); } }, null, WorkItemOptions.ReturnNullOnSynchronousExecution)?.Wait(); } }
/// <summary> /// Sets the texture's data from managed memory. /// </summary> private unsafe void SetDataInternal(Int32 level, Rectangle?rect, Object data, Int32 offsetInBytes, Int32 sizeInBytes) { if (Ultraviolet.IsExecutingOnCurrentThread) { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { SetRawDataInternal(level, rect, pData.AddrOfPinnedObject(), offsetInBytes, sizeInBytes); } finally { pData.Free(); } } else { Ultraviolet.QueueWorkItem(state => { var pData = GCHandle.Alloc(data, GCHandleType.Pinned); try { SetRawDataInternal(level, rect, pData.AddrOfPinnedObject(), 0, sizeInBytes); } finally { pData.Free(); } }, null, WorkItemOptions.ReturnNullOnSynchronousExecution)?.Wait(); } }
/// <summary> /// Creates the effect pass' collection of uniforms. /// </summary> /// <param name="ssmd">The source metadata for this program.</param> /// <returns>The collection of uniforms that was created.</returns> private OpenGLShaderUniformCollection CreateUniformCollection(ShaderSourceMetadata ssmd) { var result = Ultraviolet.QueueWorkItem(state => { var programObject = ((OpenGLShaderProgram)state); var program = programObject.program; var uniforms = new List <OpenGLShaderUniform>(); var samplerCount = 0; var count = gl.GetProgrami(program, gl.GL_ACTIVE_UNIFORMS); gl.ThrowIfError(); for (uint i = 0; i < count; i++) { var type = 0u; var name = gl.GetActiveUniform(program, i, out type); gl.ThrowIfError(); var location = gl.GetUniformLocation(program, name); gl.ThrowIfError(); var isSampler = false; switch (type) { case gl.GL_SAMPLER_1D: case gl.GL_SAMPLER_1D_ARRAY: case gl.GL_SAMPLER_1D_ARRAY_SHADOW: case gl.GL_SAMPLER_1D_SHADOW: case gl.GL_SAMPLER_2D: case gl.GL_SAMPLER_2D_ARRAY: case gl.GL_SAMPLER_2D_ARRAY_SHADOW: case gl.GL_SAMPLER_2D_MULTISAMPLE: case gl.GL_SAMPLER_2D_MULTISAMPLE_ARRAY: case gl.GL_SAMPLER_2D_RECT: case gl.GL_SAMPLER_2D_RECT_SHADOW: case gl.GL_SAMPLER_2D_SHADOW: case gl.GL_SAMPLER_3D: case gl.GL_SAMPLER_CUBE: case gl.GL_SAMPLER_CUBE_MAP_ARRAY: case gl.GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: case gl.GL_SAMPLER_CUBE_SHADOW: isSampler = true; break; } var sampler = isSampler ? samplerCount++ : -1; if (isSampler && ssmd.PreferredSamplerIndices.ContainsKey(name)) { samplerCount = ssmd.PreferredSamplerIndices[name]; sampler = samplerCount++; } uniforms.Add(new OpenGLShaderUniform(programObject.Ultraviolet, name, type, program, location, sampler)); } return(uniforms); }, this).Result; // Validation: make sure all preferred samplers correspond to an actual uniform var missingUniform = ssmd.PreferredSamplerIndices.Keys.Where(x => !result.Where(y => String.Equals(y.Name, x, StringComparison.Ordinal)).Any()).FirstOrDefault(); if (missingUniform != null) { throw new ArgumentException(OpenGLStrings.SamplerDirectiveInvalidUniform.Format(missingUniform)); } return(new OpenGLShaderUniformCollection(result)); }