public GLES2HardwareVertexBuffer(HardwareBufferManagerBase manager, VertexDeclaration vertexDeclaration, int numVertices, BufferUsage usage, bool useShadowBuffer) : base(manager, vertexDeclaration, numVertices, usage, false, useShadowBuffer) { if (!useShadowBuffer) { throw new AxiomException("Only supported with shadowBuffer"); } var buffers = new int[1]; GL.GenBuffers(1, buffers); GLES2Config.GlCheckError(this); this._bufferID = buffers[0]; if (this._bufferID == 0) { throw new AxiomException("Cannot create GL ES vertex buffer"); } (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); }
protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { if (IsLocked) { throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked."); } BufferBase retPtr; var glBufManager = (HardwareBufferManager.Instance as GLES2HardwareBufferManager); //Try to use scratch buffers for smaller buffers if (length < glBufManager.MapBufferThreshold) { retPtr = glBufManager.AllocateScratch(length); if (retPtr != null) { this._lockedToScratch = true; this._scratchOffset = offset; this._scratchSize = length; this._scratchPtr = retPtr; this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly); if (locking != BufferLocking.Discard) { //have to read back the data before returning the pointer this.ReadData(offset, length, retPtr); } } } else { throw new AxiomException("Invalid Buffer lockSize"); } if (retPtr == null) { GLenum access = GLenum.Zero; (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); if (locking == BufferLocking.Discard) { //Discard the buffer GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) == BufferUsage.WriteOnly) { access = GLenum.WriteOnlyOes; } var pbuffer = GL.Oes.MapBuffer(GLenum.ArrayBuffer, access); GLES2Config.GlCheckError(this); if (pbuffer == IntPtr.Zero) { throw new AxiomException("Vertex Buffer: Out of memory"); } //return offsetted retPtr = BufferBase.Wrap(pbuffer, sizeInBytes) + offset; this._lockedToScratch = false; } isLocked = true; return(retPtr); }
protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); (Root.Instance.RenderSystem as GLES2RenderSystem).BindGLBuffer(GLenum.ArrayBuffer, this._bufferID); //Update whole buffer if possible, otherwise normal if (lockStart == 0 && lockSize == sizeInBytes) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), srcData.Pin(), GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { //Ogre FIXME: GPU frequently stalls here - DJR GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcData.Pin()); GLES2Config.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer) { //Update the shadow buffer if (useShadowBuffer) { var destData = shadowBuffer.Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal); src = destData; shadowBuffer.Unlock(); } if (offset == 0 && length == sizeInBytes) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), src.Pin(), GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { if (discardWholeBuffer) { GL.BufferData(GLenum.ArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } GL.BufferSubData(GLenum.ArrayBuffer, new IntPtr(offset), new IntPtr(length), src.Pin()); GLES2Config.GlCheckError(this); } }
public GLES2HardwareIndexBuffer(HardwareBufferManagerBase manager, IndexType type, int numIndices, BufferUsage usage, bool useShadowBuffer) : base(manager, type, numIndices, usage, false, useShadowBuffer) { if (type == IndexType.Size32) { throw new AxiomException("32 bit hardware buffers are not allowed in OpenGL ES."); } if (!useShadowBuffer) { throw new AxiomException("Only support with shadowBuffer"); } OpenGL.GenBuffers(1, ref this._bufferId); GLES2Config.GlCheckError(this); if (this._bufferId == 0) { throw new AxiomException("Cannot create GL index buffer"); } OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); }
/// <summary> /// </summary> protected override void UpdateFromShadow() { if (useShadowBuffer && shadowUpdated && !suppressHardwareUpdate) { var srcData = shadowBuffer.Lock(lockStart, lockSize, BufferLocking.ReadOnly); OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); var srcPtr = new IntPtr(srcData.Ptr); // Update whole buffer if possible, otherwise normal if (lockStart == 0 && lockSize == sizeInBytes) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), srcPtr, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(lockStart), new IntPtr(lockSize), srcPtr); GLES2Config.GlCheckError(this); } shadowBuffer.Unlock(); shadowUpdated = false; } }
/// <summary> /// </summary> /// <param name="offset"> </param> /// <param name="length"> </param> /// <param name="src"> </param> /// <param name="discardWholeBuffer"> </param> public override void WriteData(int offset, int length, BufferBase src, bool discardWholeBuffer) { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); // Update the shadow buffer if (useShadowBuffer) { var destData = shadowBuffer.Lock(offset, length, discardWholeBuffer ? BufferLocking.Discard : BufferLocking.Normal); Memory.Copy(src, destData, length); shadowBuffer.Unlock(); } var srcPtr = src.Ptr; if (offset == 0 && length == sizeInBytes) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), ref srcPtr, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } else { if (discardWholeBuffer) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } // Now update the real buffer OpenGL.BufferSubData(All.ElementArrayBuffer, new IntPtr(offset), new IntPtr(length), ref srcPtr); GLES2Config.GlCheckError(this); } if (src.Ptr != srcPtr) { LogManager.Instance.Write("[GLES2] HardwareIndexBuffer.WriteData - buffer pointer modified by GL.BufferData."); } }
/// <summary> /// </summary> /// <param name="offset"> </param> /// <param name="length"> </param> /// <param name="locking"> </param> /// <returns> </returns> protected override BufferBase LockImpl(int offset, int length, BufferLocking locking) { All access = 0; if (isLocked) { throw new AxiomException("Invalid attempt to lock an index buffer that has already been locked"); } BufferBase retPtr = null; if (length < MapBufferThreshold) { retPtr = ((GLES2HardwareBufferManager)HardwareBufferManager.Instance).AllocateScratch(length); if (retPtr != null) { this._lockedToScratch = true; this._scratchOffset = offset; this._scratchSize = length; this._scratchPtr = retPtr; this._scratchUploadOnUnlock = (locking != BufferLocking.ReadOnly); if (locking != BufferLocking.Discard) { this.ReadData(offset, length, retPtr); } } } else { throw new AxiomException("Invalid Buffer lockSize"); } if (retPtr == null) { OpenGL.BindBuffer(All.ElementArrayBuffer, this._bufferId); GLES2Config.GlCheckError(this); // Use glMapBuffer if (locking == BufferLocking.Discard) { OpenGL.BufferData(All.ElementArrayBuffer, new IntPtr(sizeInBytes), IntPtr.Zero, GLES2HardwareBufferManager.GetGLUsage(usage)); GLES2Config.GlCheckError(this); } if ((usage & BufferUsage.WriteOnly) != 0) { access = All.WriteOnlyOes; } IntPtr pBuffer = OpenGLOES.MapBuffer(All.ElementArrayBuffer, access); GLES2Config.GlCheckError(this); if (pBuffer == IntPtr.Zero) { throw new AxiomException("Index Buffer: Out of memory"); } unsafe { // return offset retPtr = BufferBase.Wrap(pBuffer, sizeInBytes); } this._lockedToScratch = false; } isLocked = true; return(retPtr); }