public void SetVertexBuffers(ReadOnlySpan <VertexBufferDescriptor> vertexBuffers) { int bindingIndex; for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++) { VertexBufferDescriptor vb = vertexBuffers[bindingIndex]; if (vb.Buffer.Handle != BufferHandle.Null) { GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.VertexBindingDivisor(bindingIndex, vb.Divisor); _vertexBuffersInUse |= 1u << bindingIndex; } else { if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0) { GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); _vertexBuffersInUse &= ~(1u << bindingIndex); } } _vertexBuffers[bindingIndex] = vb; } _vertexBuffersCount = bindingIndex; _needsAttribsUpdate = true; }
public void SetVertexBuffers(ReadOnlySpan <VertexBufferDescriptor> vertexBuffers) { int bindingIndex = 0; for (int index = 0; index < vertexBuffers.Length; index++) { VertexBufferDescriptor vb = vertexBuffers[index]; if (vb.Buffer.Handle != null) { GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.VertexBindingDivisor(bindingIndex, vb.Divisor); } else { GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); } _vertexBuffers[index] = vb; bindingIndex++; } _vertexBuffersCount = bindingIndex; _needsAttribsUpdate = true; }
// buffer -> stream -> vertex -> element private void ParseStride(BinaryReader reader) { for (int i = 0; i < VertexBuffers.Length; ++i) { VertexBufferDescriptor vbo = VertexBuffers[i]; Stride[i] = new object[2][][]; long[] offset = { vbo.DataStream1Pointer, vbo.DataStream2Pointer }; byte[] sizes = { vbo.StrideStream1, vbo.StrideStream2 }; VertexElementDescriptor[][] elements = SplitVBE(VertexElements[i]); for (int j = 0; j < offset.Length; ++j) { Stride[i][j] = new object[vbo.VertexCount][]; reader.BaseStream.Position = offset[j]; for (int k = 0; k < vbo.VertexCount; ++k) { Stride[i][j][k] = new object[elements[j].Length]; long next = reader.BaseStream.Position + sizes[j]; long current = reader.BaseStream.Position; for (int l = 0; l < elements[j].Length; ++l) { reader.BaseStream.Position = current + elements[j][l].Offset; Stride[i][j][k][l] = ReadElement(elements[j][l].Format, reader); } reader.BaseStream.Position = next; } } } }
/// <summary> /// Ensures that the graphics engine bindings are visible to the host GPU. /// Note: this actually performs the binding using the host graphics API. /// </summary> public void CommitGraphicsBindings() { if (_indexBufferDirty || _rebind) { _indexBufferDirty = false; if (_indexBuffer.Address != 0) { BufferRange buffer = GetBufferRange(_indexBuffer.Address, _indexBuffer.Size); _context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type); } } else if (_indexBuffer.Address != 0) { SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size); } uint vbEnableMask = _vertexBuffersEnableMask; if (_vertexBuffersDirty || _rebind) { _vertexBuffersDirty = false; Span <VertexBufferDescriptor> vertexBuffers = stackalloc VertexBufferDescriptor[Constants.TotalVertexBuffers]; for (int index = 0; (vbEnableMask >> index) != 0; index++) { VertexBuffer vb = _vertexBuffers[index]; if (vb.Address == 0) { continue; } BufferRange buffer = GetBufferRange(vb.Address, vb.Size); vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor); } _context.Renderer.Pipeline.SetVertexBuffers(vertexBuffers); } else { for (int index = 0; (vbEnableMask >> index) != 0; index++) { VertexBuffer vb = _vertexBuffers[index]; if (vb.Address == 0) { continue; } SynchronizeBufferRange(vb.Address, vb.Size); } } if (_gpStorageBuffersDirty || _rebind) { _gpStorageBuffersDirty = false; BindBuffers(_gpStorageBuffers, isStorage: true); } else { UpdateBuffers(_gpStorageBuffers); } if (_gpUniformBuffersDirty || _rebind) { _gpUniformBuffersDirty = false; BindBuffers(_gpUniformBuffers, isStorage: false); } else { UpdateBuffers(_gpUniformBuffers); } _rebind = false; }
private VertexElementDescriptor[] ParseVBE(BinaryReader reader, VertexBufferDescriptor descriptor) { reader.BaseStream.Position = descriptor.VertexElementDescriptorPointer; return(reader.ReadArray <VertexElementDescriptor>(descriptor.VertexElementDescriptorCount)); }
/// <summary> /// Ensures that the graphics engine bindings are visible to the host GPU. /// Note: this actually performs the binding using the host graphics API. /// </summary> public void CommitGraphicsBindings() { var bufferCache = _channel.MemoryManager.Physical.BufferCache; if (_indexBufferDirty || _rebind) { _indexBufferDirty = false; if (_indexBuffer.Address != 0) { BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Address, _indexBuffer.Size); _context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type); } } else if (_indexBuffer.Address != 0) { bufferCache.SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size); } uint vbEnableMask = _vertexBuffersEnableMask; if (_vertexBuffersDirty || _rebind) { _vertexBuffersDirty = false; Span <VertexBufferDescriptor> vertexBuffers = stackalloc VertexBufferDescriptor[Constants.TotalVertexBuffers]; for (int index = 0; (vbEnableMask >> index) != 0; index++) { VertexBuffer vb = _vertexBuffers[index]; if (vb.Address == 0) { continue; } BufferRange buffer = bufferCache.GetBufferRange(vb.Address, vb.Size); vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor); } _context.Renderer.Pipeline.SetVertexBuffers(vertexBuffers); } else { for (int index = 0; (vbEnableMask >> index) != 0; index++) { VertexBuffer vb = _vertexBuffers[index]; if (vb.Address == 0) { continue; } bufferCache.SynchronizeBufferRange(vb.Address, vb.Size); } } if (_transformFeedbackBuffersDirty || _rebind) { _transformFeedbackBuffersDirty = false; Span <BufferRange> tfbs = stackalloc BufferRange[Constants.TotalTransformFeedbackBuffers]; for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++) { BufferBounds tfb = _transformFeedbackBuffers[index]; if (tfb.Address == 0) { tfbs[index] = BufferRange.Empty; continue; } tfbs[index] = bufferCache.GetBufferRange(tfb.Address, tfb.Size, write: true); } _context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs); } else { for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++) { BufferBounds tfb = _transformFeedbackBuffers[index]; if (tfb.Address == 0) { continue; } bufferCache.SynchronizeBufferRange(tfb.Address, tfb.Size); } } if (_gpStorageBuffersDirty || _rebind) { _gpStorageBuffersDirty = false; BindBuffers(bufferCache, _gpStorageBuffers, isStorage: true); } else { UpdateBuffers(_gpStorageBuffers); } if (_gpUniformBuffersDirty || _rebind) { _gpUniformBuffersDirty = false; BindBuffers(bufferCache, _gpUniformBuffers, isStorage: false); } else { UpdateBuffers(_gpUniformBuffers); } CommitBufferTextureBindings(); _rebind = false; }