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(); } }
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); } }
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); }