Exemplo n.º 1
0
        public bool GetTextureBindingInfo(uint set, uint slot, out OpenGLTextureBindingSlotInfo binding)
        {
            Debug.Assert(_setInfos != null, "EnsureResourcesCreated must be called before accessing resource set information.");
            SetBindingsInfo setInfo = _setInfos[set];

            return(setInfo.GetTextureBindingInfo(slot, out binding));
        }
Exemplo n.º 2
0
 public bool GetTextureBindingInfo(uint slot, out OpenGLTextureBindingSlotInfo binding)
 {
     return(_textureBindings.TryGetValue(slot, out binding));
 }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
0
        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);
            }
        }
Exemplo n.º 5
0
        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;
        }