public bool GetStorageBufferBindingForSlot(uint set, uint slot, out OpenGLShaderStorageBinding binding) { Debug.Assert(_setInfos != null, "EnsureResourcesCreated must be called before accessing resource set information."); SetBindingsInfo setInfo = _setInfos[set]; return(setInfo.GetStorageBufferBindingForSlot(slot, out binding)); }
public bool GetSamplerBindingInfo(uint set, uint slot, out OpenGLSamplerBindingSlotInfo binding) { Debug.Assert(_setInfos != null, "EnsureResourcesCreated must be called before accessing resource set information."); SetBindingsInfo setInfo = _setInfos[set]; return(setInfo.GetSamplerBindingInfo(slot, out binding)); }
public OpenGLTextureBindingSlotInfo GetTextureBindingInfo(uint set, uint slot) { Debug.Assert(_setInfos != null, "EnsureResourcesCreated must be called before accessing resource set information."); SetBindingsInfo setInfo = _setInfos[set]; return(setInfo.GetTextureBindingInfo(slot)); }
private void ProcessResourceSetLayouts(ResourceLayout[] layouts) { int resourceLayoutCount = layouts.Length; _setInfos = new SetBindingsInfo[resourceLayoutCount]; int lastTextureLocation = -1; int relativeTextureIndex = -1; int relativeImageIndex = -1; uint storageBlockIndex = 0; // Tracks OpenGL ES storage buffers. for (uint setSlot = 0; setSlot < resourceLayoutCount; setSlot++) { ResourceLayout setLayout = layouts[setSlot]; OpenGLResourceLayout glSetLayout = Util.AssertSubtype <ResourceLayout, OpenGLResourceLayout>(setLayout); ResourceLayoutElementDescription[] resources = glSetLayout.Elements; Dictionary <uint, OpenGLUniformBinding> uniformBindings = new Dictionary <uint, OpenGLUniformBinding>(); Dictionary <uint, OpenGLTextureBindingSlotInfo> textureBindings = new Dictionary <uint, OpenGLTextureBindingSlotInfo>(); Dictionary <uint, OpenGLSamplerBindingSlotInfo> samplerBindings = new Dictionary <uint, OpenGLSamplerBindingSlotInfo>(); Dictionary <uint, OpenGLShaderStorageBinding> storageBufferBindings = new Dictionary <uint, OpenGLShaderStorageBinding>(); List <int> samplerTrackedRelativeTextureIndices = new List <int>(); for (uint i = 0; i < resources.Length; i++) { ResourceLayoutElementDescription resource = resources[i]; if (resource.Kind == ResourceKind.UniformBuffer) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. uint blockIndex = glGetUniformBlockIndex(_program, resourceNamePtr); CheckLastError(); if (blockIndex != GL_INVALID_INDEX) { int blockSize; glGetActiveUniformBlockiv(_program, blockIndex, ActiveUniformBlockParameter.UniformBlockDataSize, &blockSize); CheckLastError(); uniformBindings[i] = new OpenGLUniformBinding(_program, blockIndex, (uint)blockSize); } } else if (resource.Kind == ResourceKind.TextureReadOnly) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetUniformLocation(_program, resourceNamePtr); CheckLastError(); relativeTextureIndex += 1; textureBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeTextureIndex, UniformLocation = location }; lastTextureLocation = location; samplerTrackedRelativeTextureIndices.Add(relativeTextureIndex); } else if (resource.Kind == ResourceKind.TextureReadWrite) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetUniformLocation(_program, resourceNamePtr); CheckLastError(); relativeImageIndex += 1; textureBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeImageIndex, UniformLocation = location }; } else if (resource.Kind == ResourceKind.StructuredBufferReadOnly || resource.Kind == ResourceKind.StructuredBufferReadWrite) { uint storageBlockBinding; if (_gd.BackendType == GraphicsBackend.OpenGL) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. storageBlockBinding = glGetProgramResourceIndex( _program, ProgramInterface.ShaderStorageBlock, resourceNamePtr); CheckLastError(); } else { storageBlockBinding = storageBlockIndex; storageBlockIndex += 1; } storageBufferBindings[i] = new OpenGLShaderStorageBinding(storageBlockBinding); } else { Debug.Assert(resource.Kind == ResourceKind.Sampler); int[] relativeIndices = samplerTrackedRelativeTextureIndices.ToArray(); samplerTrackedRelativeTextureIndices.Clear(); samplerBindings[i] = new OpenGLSamplerBindingSlotInfo() { RelativeIndices = relativeIndices }; } } _setInfos[setSlot] = new SetBindingsInfo(uniformBindings, textureBindings, samplerBindings, storageBufferBindings); } }
private void ProcessResourceSetLayouts(ResourceLayout[] layouts) { int resourceLayoutCount = layouts.Length; _setInfos = new SetBindingsInfo[resourceLayoutCount]; int lastTextureLocation = -1; int relativeTextureIndex = -1; int relativeImageIndex = -1; uint storageBlockIndex = 0; // Tracks OpenGL ES storage buffers. for (uint setSlot = 0; setSlot < resourceLayoutCount; setSlot++) { ResourceLayout setLayout = layouts[setSlot]; OpenGLResourceLayout glSetLayout = Util.AssertSubtype <ResourceLayout, OpenGLResourceLayout>(setLayout); ResourceLayoutElementDescription[] resources = glSetLayout.Elements; Dictionary <uint, OpenGLUniformBinding> uniformBindings = new Dictionary <uint, OpenGLUniformBinding>(); Dictionary <uint, OpenGLTextureBindingSlotInfo> textureBindings = new Dictionary <uint, OpenGLTextureBindingSlotInfo>(); Dictionary <uint, OpenGLSamplerBindingSlotInfo> samplerBindings = new Dictionary <uint, OpenGLSamplerBindingSlotInfo>(); Dictionary <uint, OpenGLShaderStorageBinding> storageBufferBindings = new Dictionary <uint, OpenGLShaderStorageBinding>(); List <int> samplerTrackedRelativeTextureIndices = new List <int>(); for (uint i = 0; i < resources.Length; i++) { ResourceLayoutElementDescription resource = resources[i]; if (resource.Kind == ResourceKind.UniformBuffer) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. uint blockIndex = glGetUniformBlockIndex(_program, resourceNamePtr); CheckLastError(); if (blockIndex != GL_INVALID_INDEX) { int blockSize; glGetActiveUniformBlockiv(_program, blockIndex, ActiveUniformBlockParameter.UniformBlockDataSize, &blockSize); CheckLastError(); uniformBindings[i] = new OpenGLUniformBinding(_program, blockIndex, (uint)blockSize); } #if DEBUG && GL_VALIDATE_SHADER_RESOURCE_NAMES else { uint uniformBufferIndex = 0; uint bufferNameByteCount = 64; byte *bufferNamePtr = stackalloc byte[(int)bufferNameByteCount]; var names = new List <string>(); while (true) { uint actualLength; glGetActiveUniformBlockName(_program, uniformBufferIndex, bufferNameByteCount, &actualLength, bufferNamePtr); if (glGetError() != 0) { break; } string name = Encoding.UTF8.GetString(bufferNamePtr, (int)actualLength); names.Add(name); uniformBufferIndex++; } throw new VeldridException($"Unable to bind uniform buffer \"{resourceName}\" by name. Valid names for this pipeline are: {string.Join(", ", names)}"); } #endif } else if (resource.Kind == ResourceKind.TextureReadOnly) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetUniformLocation(_program, resourceNamePtr); CheckLastError(); #if DEBUG && GL_VALIDATE_SHADER_RESOURCE_NAMES if (location == -1) { ReportInvalidResourceName(resourceName); } #endif relativeTextureIndex += 1; textureBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeTextureIndex, UniformLocation = location }; lastTextureLocation = location; samplerTrackedRelativeTextureIndices.Add(relativeTextureIndex); } else if (resource.Kind == ResourceKind.TextureReadWrite) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetUniformLocation(_program, resourceNamePtr); CheckLastError(); #if DEBUG && GL_VALIDATE_SHADER_RESOURCE_NAMES if (location == -1) { ReportInvalidResourceName(resourceName); } #endif relativeImageIndex += 1; textureBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeImageIndex, UniformLocation = location }; } else if (resource.Kind == ResourceKind.StructuredBufferReadOnly || resource.Kind == ResourceKind.StructuredBufferReadWrite) { uint storageBlockBinding; if (_gd.BackendType == GraphicsBackend.OpenGL) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. storageBlockBinding = glGetProgramResourceIndex( _program, ProgramInterface.ShaderStorageBlock, resourceNamePtr); CheckLastError(); } else { storageBlockBinding = storageBlockIndex; storageBlockIndex += 1; } storageBufferBindings[i] = new OpenGLShaderStorageBinding(storageBlockBinding); } else { Debug.Assert(resource.Kind == ResourceKind.Sampler); int[] relativeIndices = samplerTrackedRelativeTextureIndices.ToArray(); samplerTrackedRelativeTextureIndices.Clear(); samplerBindings[i] = new OpenGLSamplerBindingSlotInfo() { RelativeIndices = relativeIndices }; } } _setInfos[setSlot] = new SetBindingsInfo(uniformBindings, textureBindings, samplerBindings, storageBufferBindings); } }
private void CreateGLResources() { ShaderSetDescription shaderSet = Description.ShaderSet; _program = glCreateProgram(); CheckLastError(); foreach (ShaderStageDescription stageDesc in shaderSet.ShaderStages) { OpenGLShader glShader = Util.AssertSubtype <Shader, OpenGLShader>(stageDesc.Shader); glShader.EnsureResourcesCreated(); glAttachShader(_program, glShader.Shader); CheckLastError(); } uint slot = 0; foreach (VertexLayoutDescription layoutDesc in shaderSet.VertexLayouts) { for (int i = 0; i < layoutDesc.Elements.Length; i++) { string elementName = layoutDesc.Elements[i].Name; int byteCount = Encoding.UTF8.GetByteCount(elementName) + 1; byte * elementNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = elementName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, elementName.Length, elementNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } elementNamePtr[byteCount - 1] = 0; // Add null terminator. glBindAttribLocation(_program, slot, elementNamePtr); CheckLastError(); slot += 1; } } glLinkProgram(_program); CheckLastError(); #if DEBUG && GL_VALIDATE_VERTEX_INPUT_ELEMENTS slot = 0; foreach (VertexLayoutDescription layoutDesc in shaderSet.VertexLayouts) { for (int i = 0; i < layoutDesc.Elements.Length; i++) { string elementName = layoutDesc.Elements[i].Name; int byteCount = Encoding.UTF8.GetByteCount(elementName) + 1; byte * elementNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = elementName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, elementName.Length, elementNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } elementNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetAttribLocation(_program, elementNamePtr); if (location == -1) { throw new VeldridException("There was no attribute variable with the name " + layoutDesc.Elements[i].Name); } slot += 1; } } #endif int linkStatus; glGetProgramiv(_program, GetProgramParameterName.LinkStatus, &linkStatus); CheckLastError(); if (linkStatus != 1) { byte *infoLog = stackalloc byte[4096]; uint bytesWritten; glGetProgramInfoLog(_program, 4096, &bytesWritten, infoLog); CheckLastError(); string log = Encoding.UTF8.GetString(infoLog, (int)bytesWritten); throw new VeldridException($"Error linking GL program: {log}"); } int resourceLayoutCount = Description.ResourceLayouts.Length; _setInfos = new SetBindingsInfo[resourceLayoutCount]; int lastTextureLocation = -1; int relativeTextureIndex = -1; for (uint setSlot = 0; setSlot < resourceLayoutCount; setSlot++) { ResourceLayout setLayout = Description.ResourceLayouts[setSlot]; OpenGLResourceLayout glSetLayout = Util.AssertSubtype <ResourceLayout, OpenGLResourceLayout>(setLayout); ResourceLayoutElementDescription[] resources = glSetLayout.Description.Elements; Dictionary <uint, OpenGLUniformBinding> uniformBindings = new Dictionary <uint, OpenGLUniformBinding>(); Dictionary <uint, OpenGLTextureBindingSlotInfo> textureBindings = new Dictionary <uint, OpenGLTextureBindingSlotInfo>(); Dictionary <uint, OpenGLTextureBindingSlotInfo> samplerBindings = new Dictionary <uint, OpenGLTextureBindingSlotInfo>(); for (uint i = 0; i < resources.Length; i++) { ResourceLayoutElementDescription resource = resources[i]; if (resource.Kind == ResourceKind.Uniform) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. uint blockIndex = glGetUniformBlockIndex(_program, resourceNamePtr); if (blockIndex != GL_INVALID_INDEX) { uniformBindings[i] = new OpenGLUniformBinding(_program, blockIndex); } else { throw new System.NotImplementedException(); //int uniformLocation = glGetUniformLocation(_program, resource.Name); //OpenGLUniformStorageAdapter storageAdapter = new OpenGLUniformStorageAdapter(_program, uniformLocation); //_constantBindings[i] = new OpenGLUniformBinding(_program, storageAdapter); } } else if (resource.Kind == ResourceKind.Texture) { string resourceName = resource.Name; int byteCount = Encoding.UTF8.GetByteCount(resourceName) + 1; byte * resourceNamePtr = stackalloc byte[byteCount]; fixed(char *charPtr = resourceName) { int bytesWritten = Encoding.UTF8.GetBytes(charPtr, resourceName.Length, resourceNamePtr, byteCount); Debug.Assert(bytesWritten == byteCount - 1); } resourceNamePtr[byteCount - 1] = 0; // Add null terminator. int location = glGetUniformLocation(_program, resourceNamePtr); relativeTextureIndex += 1; textureBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeTextureIndex, UniformLocation = location }; lastTextureLocation = location; } else { Debug.Assert(resource.Kind == ResourceKind.Sampler); // TODO: Samplers should be able to bind to multiple texture slots // if multiple textures are declared without an intervening sampler. For example: // Slot Resource // ------------------------- // [0] Texture0 // [1] Sampler0 // [2] Texture1 // [3] Texture2 // [4] Sampler1* // Sampler1 should be active for both Texture1 and Texture2. samplerBindings[i] = new OpenGLTextureBindingSlotInfo() { RelativeIndex = relativeTextureIndex, UniformLocation = lastTextureLocation }; } } _setInfos[setSlot] = new SetBindingsInfo(uniformBindings, textureBindings, samplerBindings); } Created = true; }