private void CreateDescriptorSetLayout(IntPtr program, Dictionary <string, UniformInfo> uniformInfoLookup)
        {
            var updateTemplate    = new List <DescriptorSetUpdateTemplateEntry>();
            var bindings          = new List <SharpVulkan.DescriptorSetLayoutBinding>();
            var uniformBlockCount = ShaderCompiler.GetActiveUniformBlockCount(program);

            for (var i = 0; i < uniformBlockCount; i++)
            {
                var binding = ShaderCompiler.GetActiveUniformBlockBinding(program, i);
                bindings.Add(new SharpVulkan.DescriptorSetLayoutBinding {
                    Binding         = (uint)binding,
                    DescriptorType  = SharpVulkan.DescriptorType.UniformBuffer,
                    DescriptorCount = 1,
                    StageFlags      = GetVKShaderStageFlags(ShaderCompiler.GetActiveUniformBlockStage(program, i))
                });
                updateTemplate.Add(new DescriptorSetUpdateTemplateEntry {
                    Binding        = binding,
                    DescriptorType = SharpVulkan.DescriptorType.UniformBuffer,
                    BufferSlot     = i,
                    TextureSlot    = -1
                });
                uniformBufferCount++;
            }
            var uniformCount = ShaderCompiler.GetActiveUniformCount(program);

            for (var i = 0; i < uniformCount; i++)
            {
                var name = AdjustUniformName(ShaderCompiler.GetActiveUniformName(program, i));
                var info = uniformInfoLookup[name];
                if (info.TextureSlot >= 0)
                {
                    var binding = ShaderCompiler.GetActiveUniformBinding(program, i);
                    bindings.Add(new SharpVulkan.DescriptorSetLayoutBinding {
                        Binding         = (uint)binding,
                        DescriptorType  = SharpVulkan.DescriptorType.CombinedImageSampler,
                        DescriptorCount = 1,
                        StageFlags      = GetVKShaderStageFlags(ShaderCompiler.GetActiveUniformStage(program, i))
                    });
                    updateTemplate.Add(new DescriptorSetUpdateTemplateEntry {
                        Binding        = binding,
                        DescriptorType = SharpVulkan.DescriptorType.CombinedImageSampler,
                        BufferSlot     = -1,
                        TextureSlot    = info.TextureSlot
                    });
                    combinedImageSamplerCount++;
                }
            }

            fixed(SharpVulkan.DescriptorSetLayoutBinding *bindingsPtr = bindings.ToArray())
            {
                var layoutCreateInfo = new SharpVulkan.DescriptorSetLayoutCreateInfo {
                    StructureType = SharpVulkan.StructureType.DescriptorSetLayoutCreateInfo,
                    BindingCount  = (uint)bindings.Count,
                    Bindings      = new IntPtr(bindingsPtr)
                };

                descriptorSetLayout         = context.Device.CreateDescriptorSetLayout(ref layoutCreateInfo);
                descriptorSetUpdateTemplate = updateTemplate.ToArray();
            }
        }
Exemple #2
0
        private void Create(string source)
        {
            var compilerStage = Stage == ShaderStageMask.Vertex
                                ? ShaderCompiler.Stage.Vertex
                                : ShaderCompiler.Stage.Fragment;

            shader = ShaderCompiler.CreateShader();
            var hash = ComputeHash(Stage, source);
            var spv  = context.PipelineCache.GetShaderSpv(hash);

            if (spv != null)
            {
                fixed(byte *spvPtr = spv)
                {
                    ShaderCompiler.SetShaderSpv(shader, new IntPtr(spvPtr), (uint)spv.Length);
                }
            }
            else
            {
                if (!ShaderCompiler.CompileShader(shader, compilerStage, source))
                {
                    var infoLog = ShaderCompiler.GetShaderInfoLog(shader);
                    ShaderCompiler.DestroyShader(shader);
                    throw new InvalidOperationException($"Shader compilation failed:\n{infoLog}");
                }
                spv = new byte[ShaderCompiler.GetShaderSpvSize(shader)];
                Marshal.Copy(ShaderCompiler.GetShaderSpv(shader), spv, 0, spv.Length);
                context.PipelineCache.AddShaderSpv(hash, spv);
            }
        }
Exemple #3
0
 public void Dispose()
 {
     if (shader != IntPtr.Zero)
     {
         ShaderCompiler.DestroyShader(shader);
         shader = IntPtr.Zero;
     }
 }
        private SharpVulkan.ShaderModule CreateShaderModule(IntPtr program, ShaderCompiler.Stage stage)
        {
            var code       = ShaderCompiler.GetSpv(program, stage);
            var codeSize   = ShaderCompiler.GetSpvSize(program, stage);
            var createInfo = new SharpVulkan.ShaderModuleCreateInfo {
                StructureType = SharpVulkan.StructureType.ShaderModuleCreateInfo,
                CodeSize      = codeSize,
                Code          = code
            };

            return(context.Device.CreateShaderModule(ref createInfo));
        }
        private static Dictionary <string, UniformInfo> LinkUniforms(IntPtr program, ShaderProgram.Sampler[] samplers)
        {
            var infos        = new Dictionary <string, UniformInfo>();
            var uniformCount = ShaderCompiler.GetActiveUniformCount(program);

            for (var i = 0; i < uniformCount; i++)
            {
                var name      = AdjustUniformName(ShaderCompiler.GetActiveUniformName(program, i));
                var type      = ConvertShaderVariableType(ShaderCompiler.GetActiveUniformType(program, i));
                var stage     = ConvertShaderStage(ShaderCompiler.GetActiveUniformStage(program, i));
                var arraySize = ShaderCompiler.GetActiveUniformArraySize(program, i);
                if (infos.TryGetValue(name, out var info))
                {
                    if (info.Type != type)
                    {
                        throw new InvalidOperationException($"Uniform type mismatch: {name}");
                    }
                    info.ArraySize  = Math.Max(info.ArraySize, arraySize);
                    info.StageMask |= stage;
                }
                else
                {
                    infos.Add(name, new UniformInfo {
                        Name          = name,
                        Type          = type,
                        ArraySize     = arraySize,
                        StageMask     = stage,
                        StagingOffset = -1,
                        TextureSlot   = -1
                    });
                }
            }
            var stagingOffset = 0;

            foreach (var info in infos.Values)
            {
                if (info.Type.IsSampler())
                {
                    info.TextureSlot = samplers.First(sampler => sampler.Name == info.Name).Stage;
                }
                else
                {
                    info.StagingOffset = stagingOffset;
                    info.ColumnCount   = info.Type.GetColumnCount();
                    info.ColumnSize    = info.Type.GetRowCount() * 4;
                    info.ColumnStride  = 16;
                    stagingOffset     += info.ColumnStride * info.ColumnCount * info.ArraySize;
                }
            }
            return(infos);
        }
        private void LinkProgram(IPlatformShader[] shaders, ShaderProgram.AttribLocation[] attribLocations, ShaderProgram.Sampler[] samplers)
        {
            PlatformShader vertexShader   = null;
            PlatformShader fragmentShader = null;

            foreach (var shader in shaders.Cast <PlatformShader>())
            {
                switch (shader.Stage)
                {
                case ShaderStageMask.Vertex:
                    vertexShader = shader;
                    break;

                case ShaderStageMask.Fragment:
                    fragmentShader = shader;
                    break;
                }
            }
            if (vertexShader == null || fragmentShader == null)
            {
                throw new InvalidOperationException();
            }
            var program = ShaderCompiler.CreateProgram();

            try {
                foreach (var i in attribLocations)
                {
                    ShaderCompiler.BindAttribLocation(program, i.Name, i.Index);
                }
                if (!ShaderCompiler.LinkProgram(program, vertexShader.Shader, fragmentShader.Shader))
                {
                    var infoLog = ShaderCompiler.GetProgramInfoLog(program);
                    throw new InvalidOperationException($"Shader program link failed:\n{infoLog}");
                }
                vsModule = CreateShaderModule(program, ShaderCompiler.Stage.Vertex);
                fsModule = CreateShaderModule(program, ShaderCompiler.Stage.Fragment);
                var uniformInfoLookup = LinkUniforms(program, samplers);
                uniformInfos       = uniformInfoLookup.Values.ToArray();
                uniformBufferInfos = BuildUniformBufferUpdateTemplates(program, uniformInfoLookup);
                CreateUniformBuffers();
                CreateDescriptorSetLayout(program, uniformInfoLookup);
                CreatePipelineLayout();
            } finally {
                ShaderCompiler.DestroyProgram(program);
            }
        }
        private UniformBufferInfo[] BuildUniformBufferUpdateTemplates(IntPtr program, Dictionary <string, UniformInfo> uniformInfoLookup)
        {
            var uniformBlockCount            = ShaderCompiler.GetActiveUniformBlockCount(program);
            var uniformCount                 = ShaderCompiler.GetActiveUniformCount(program);
            var uniformBufferUpdateTemplates = new List <UniformBufferUpdateTemplateEntry> [uniformBlockCount];

            for (var i = 0; i < uniformBlockCount; i++)
            {
                uniformBufferUpdateTemplates[i] = new List <UniformBufferUpdateTemplateEntry>();
            }
            for (var i = 0; i < uniformCount; i++)
            {
                var blockIndex = ShaderCompiler.GetActiveUniformBlockIndex(program, i);
                if (blockIndex >= 0)
                {
                    var name        = AdjustUniformName(ShaderCompiler.GetActiveUniformName(program, i));
                    var blockOffset = ShaderCompiler.GetActiveUniformBlockOffset(program, i);
                    var arraySize   = ShaderCompiler.GetActiveUniformArraySize(program, i);
                    var info        = uniformInfoLookup[name];
                    uniformBufferUpdateTemplates[blockIndex].Add(new UniformBufferUpdateTemplateEntry {
                        StagingOffset = info.StagingOffset,
                        BufferOffset  = blockOffset,
                        Size          = info.ColumnStride * info.ColumnCount * arraySize
                    });
                }
            }
            var uniformBufferInfos = new UniformBufferInfo[uniformBlockCount];

            for (var i = 0; i < uniformBlockCount; i++)
            {
                uniformBufferInfos[i] = new UniformBufferInfo {
                    Stage          = ConvertShaderStage(ShaderCompiler.GetActiveUniformBlockStage(program, i)),
                    UpdateTemplate = uniformBufferUpdateTemplates[i].ToArray()
                };
            }
            return(uniformBufferInfos);
        }