Beispiel #1
0
        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));
        }
Beispiel #2
0
 public bool GetStorageBufferBindingForSlot(uint slot, out OpenGLShaderStorageBinding binding)
 {
     return(_storageBufferBindings.TryGetValue(slot, out binding));
 }
Beispiel #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);
                        }
                    }
                    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);
            }
        }
Beispiel #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);
                        }
#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);
            }
        }